合宙Air001开发板体验---Arduino下测试SPI通讯
通过GPIO口的复用,Air001芯片提供了SPI通讯设备。下图中,
使用PA口的4、5、6、7,可以实现SPI通讯。
SPI是一个单主机多从机的通信接口。SPI是一种事实标准,也就是说这种规范没有对应的技术标准。因此各个厂家生产的SPI器件配置不一样,不一定有互操作性。
一、SPI库函数
除了需要标准的SPI库函数,Air001还提供自己专用的SPI库函数。
Air001为用户提供了 3 种关于 CS 引脚管理的可能性:
· CS 引脚在传输数据之前由用户代码直接管理(如 Arduino SPI 库)
· 或者用户将 CS pin 号提供给库 API,库自行管理 CS pin
· 或者用户使用链接到 SPI 外设的硬件 CS 引脚
1、SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)
构造函数,用于初始化 SPI 外设,参数为 SPI 外设的引脚号。
· mosi:MOSI 引脚号
· miso:MISO 引脚号
· sclk:SCLK 引脚号
· ssel:CS 引脚号,该引脚必须是硬件 CS 引脚。如果配置该引脚,片选将由 SPI 外设管理。请勿在参数中使用带有 CS 引脚的 API 函数。
2、void SPIClass::begin(uint8_t _pin)
初始化 SPI 外设。
· _pin:CS 引脚号,由 SPI 库管理。
3、void beginTransaction(uint8_t pin, SPISettings settings)
允许使用其他参数配置SPI。这些新参数保存在关联的 CS 引脚上。
· pin:CS 引脚号,由 SPI 库管理。
· settings:SPI 设置,包括速率、位顺序和数据模式。
4、void endTransaction(uint8_t pin)
删除 CS 引脚和关联的 SPI 设置
· pin:CS 引脚号,由 SPI 库管理。
注1:
使用 begin() 或 beginTransaction() 初始化 SPI 实例后,必须调用以下函数。
如果要管理多个设备,可以多次调用 beginTransaction(),并在参数中包含不同的 CS 引脚。然后,您可以使用不同的 CS 引脚调用以下函数,而无需再次调用 beginTransaction()(直到调用 end() 或 endTransaction())。
注2:
如果模式设置为 SPI_CONTINUE,CS 引脚将保持启用状态。使用多个 CS 引脚时要小心。
5、byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST)
写入/读取一个字节
· pin: CS 引脚,由 SPI 库管理
· data:要写入的参数
· mode:(可选)如果 SPI_LAST mode CS 引脚复位, SPI_CONTINUE mode CS 引脚保持启用状态。返回接收到的数据
6、uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST)
写/读半字
· pin: CS 引脚,由 SPI 库管理
· data:要写入的参数
· mode:(可选)如果 SPI_LAST mode CS 引脚复位, SPI_CONTINUE mode CS 引脚保持启用状态。返回接收到的数据
7、void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST)
写入/读取几个字节。仅使用一个缓冲区来写入和读取数据
· pin: CS 引脚,由 SPI 库管理
· buf:指向要写入的数据的指针
· count:要写入/读取的数据数量
· mode:(可选)如果 SPI_LAST mode CS 引脚复位, SPI_CONTINUE mode CS 引脚保持启用状态。
8、void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST)
写入/读取几个字节。一个用于输出数据的缓冲区,一个用于输入数据的缓冲区
· pin: CS 引脚,由 SPI 库管理
· bufout:指向要写入的数据的指针
· bufin:指向要读取的数据的指针
· count:要写入/读取的数据数量
· mode:(可选)如果 SPI_LAST mode CS 引脚复位, SPI_CONTINUE mode CS 引脚保持启用状态。
二、引脚管理的示例
1、CS 引脚管理的示例
#include <SPI.h> // MOSI MISO SCLK SPIClass SPI_3(PC12, PC11, PC10); void setup() { SPI_3.begin(2); //Enables the SPI_3 instance with default settings and attaches the CS pin SPI_3.beginTransaction(1, settings); //Attaches another CS pin and configure the SPI_3 instance with other settings SPI_3.transfer(2, 0x52); //Transfers data to the first device SPI_3.transfer(1, 0xA4); //Transfers data to the second device. The SPI_3 instance is configured with the right settings SPI_3.end() //SPI_3 instance is disabled }
2、更改默认 SPI 实例引脚的示例
void setMISO(uint32_t miso) void setMOSI(uint32_t mosi) void setSCLK(uint32_t sclk) void setSSEL(uint32_t ssel) void setMISO(PinName miso) void setMOSI(PinName mosi) void setSCLK(PinName sclk) void setSSEL(PinName ssel)
注意:这些 API 必须在调用 begin() 之前调用。
下面我们以W25Q64为例测试Air001的SPI通讯,W25Q64使用专用模块,就不需要自己手工焊接了。W25Q64的工作电压:2.7~3.6V,时钟频率≤104MHz。通过SPI接口,用标准的SPI协议发送相应指令给flash,然后flash根据命令进行W25Q64的各种相关操作。
CS:CS为片选管脚,低电平有效。上电之后,在执行一条新的指令之前,必须让/CS管脚先有一个下降沿。
DO(MISO):DO为串行数据输出引脚,在CLK(串行时钟)管脚的下降沿输出数据。
WP:WP为写保护管脚,有效电平为低电平。高电平可读可写,低电平仅仅可读。
DI(MOSI):DI为串行数据输入引脚,数据、地址和命令从DI引脚输入到芯片内部,在CLK(串行时钟)管脚的上升沿捕获捕获数据。
CLK(SLCK):CLK为串行时钟引脚。SPI时钟引脚,为输入输出提供时钟脉冲。
HOLD:HOLD为保持管脚,低电平有效。当CS为低电平,并且把HOLD拉低时,数据输出管脚将保持高阻态,并且会忽略数据输入管脚和时钟管脚上的信号。把HOLD管脚拉高,器件恢复正常工作。
VCC:电源2.7V~3.6V。
GND:地。
W25Q64常用操作命令
与Air001开发板的接线如下:
W25Q64 Air001开发板
CS PA4(CS)
DO PA6(MISO)
DI PA7(MOSI)
CLK PA5(CLK)
测试不使用W25Q64的高速和半高速模式,只使用普通的SPI的通讯模式。
程序运行截图:
程序执行了过程:
1、初始化设备
2、取得芯片的JEDEC ID
3、取得芯片的唯一识别ID
4、取得单元地址=0~15中的16字节数据,并显示。用去确认最初数据状态。
5、擦除编号为0的扇区数据
6、取得单元地址=0~15中的16字节数据,并显示。用去确认擦除结果是否正常。
7、向单元地址=0~15中写入16字节数据
8、取得单元地址=0~15中的16字节数据,并显示。用去确认写入是否正常。
9、显示状态寄存器1数据
10、显示状态寄存器2数据
处理中由于W25Q64有自己的命令集,这里专门为它单独做成了一个处理。
后面附加了整个测试工程,可供下载:TestSPI.zip