SPI引脚
上程序
#include "spi_interface.h"
SpiAttr spiConfig;//配置SPI
SpiData SpiSend;//配置SPI发送的数据
2.配置GPIO,设置为主机模式
3.关于发送数据 首先大家不要被官方规定的发送的几种数据所迷惑
你要明白,无论是啥命令,地址,数据 都是用SPI发送数据而已 你要是这都不明白....说明你已经被协议弄糊涂了 其实对于通信而言你需要把大的方向搞明白 什么叫:通信方式 (SPI,串口) 什么叫:通信协议 (在通信方式基础上规定的数据协议)
之所以有命令,地址,和数据之分,其实是咱和某个支持SPI的芯片通信的时候 如果想读取SPI芯片某个寄存器里面的值 你需要先用SPI发送发送读命令(告诉芯片我要读数据) 然后用SPI发送要读取的地址 然后另一个芯片就返回过来数据了
3.发送一个字节数据 用cmd测试
为了方便我监控数据,使用了一个1S的硬件定时器
SpiSend.cmd= 0x55;//设置发送的数据 SpiSend.cmdLen=1;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
监控如下
4.发送两个字节数据
SpiSend.cmd= 0x55aa;//设置发送的数据
SpiSend.cmdLen=2;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
测试如下 先传的0xaa 后传输的 0x55 用户实际应用的时候要注意!
5.再看一下 addr addr最大可以传输一个32位的数据(4字节)
5.1 注意下下面的情况
测试如下: 注意: 其实实际上设置为传输1位的时候芯片内部默认先取addr数据地址的 低八位 uint32_t data = 0x01; 实际上 data = 0x01000000 传输数据的时候芯片先取的最后面的00 使用addr传输的1位数据的时候需要注意
注意: 注意: 注意: 使用 addr 只要是不传输4位数据 芯片内部都会默认先传低八位
使用 addr 无论是只要是不传输4位数据 芯片内部都会默认先传低八位
使用 addr 无论是只要是不传输4位数据 芯片内部都会默认先传低八位
下面看用addr传输4位数据
u32 cnt = 0;
uint32_t data = 0x0103070f;
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.addr= &data;//设置发送的数据
SpiSend.addrLen=4;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
测试如下: 正好传输4位数据的时候,芯片内部默认先传输高八位
5.2 传输一个u8型4字节的数组,传输个数是2字节 芯片默认是先传输数组后面的数据,依次向前
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
SpiSend.addrLen=2;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
5.3 传输一个u8型4字节的数组,如果传输个数是4字节 芯片也会先传输数组后面的数据,依次向前
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
SpiSend.addrLen=2;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
以上为 使用addr 传输数据时需要注意的地方
6 现在看一下 data 只要记住一点即可 data 和 上面的 addr 传输的时候取数据的方式完全相反 data就不再多加测试:用户只需要记住上面的话即可! 由此便推导出使用data应该会怎么传输 我想官方这样做是为了应对客户不同的传输数据情况!
6.1 测试使用data ,u8型数组传输2字节的情况
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.data= (uint32_t *)(&temp);//设置发送的数据
SpiSend.dataLen=2;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
测试如下: 和addr完全相反,data是先传输数组前面的数据
6.2 测试使用data ,u8型数组传输4字节的情况
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.data= (uint32_t *)(&temp);//设置发送的数据
SpiSend.dataLen=4;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
测试如下:
关于组合起来
u32 cnt = 0;
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
cnt++;
if(cnt>1000)//1S
{
cnt=0;
SpiSend.cmd = 0x55;
SpiSend.cmdLen = 1;
SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
SpiSend.addrLen=4;//发送的数据个数(字节为单位)
SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
}
}
测试如下: 总结: cmd,addr,data的数据该怎么传还是怎么传 但是是先传 cmd 然后 addr 最后 data
如果想SPI发送数据的时候接收数据
SPIMasterRecvData(SpiNum spiNum, SpiData* pOutData)
史上最短的引脚模拟SPI
/*** @brief SPI函数
* @param value--发送的数据
* @param None
* @param None
* @retval SPI接收的数据
* @example
**/
unsigned char SPIWriteRead(unsigned char value)
{
unsigned char i=0,temp=0;
SPI_CLK = 0;//进入之前其实是高电平
if(SPI_MISO)temp|=0x80;//接收数据
for(i=0;i<8;i++)
{
SPI_MOSI=value&(0x80>>i);//准备数据
SPI_CLK=1;
SPI_CLK = 0;
if(i<7)if(SPI_MISO)temp|=0x80>>(i+1);//接收数据
}
return temp;
}
源码在默认最大是20M 按照规律修改为其它频率
typedef enum
{
SpiSpeed_2MHz = 40 - 1,
SpiSpeed_5MHz = 16 - 1,
SpiSpeed_10MHz = 8 - 1,
SpiSpeed_16MHz = 5 - 1,
SpiSpeed_20MHz = 4 - 1,
SpiSpeed_40MHz = 2 - 1,
SpiSpeed_80MHz = 1 - 1,
} SpiSpeed;
NONOS_SDK版本区别
#include "driver/spi_interface.h"
/*配置SPI GPIO 口*/
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
/*配置SPI 模式*/
spiConfig.mode = SpiMode_Master;//主机
spiConfig.speed = SpiSpeed_20MHz;//时钟频率
spiConfig.subMode = SpiSubMode_0;//模式0
spiConfig.bitOrder = SpiBitOrder_MSBFirst;//先传输高位
SpiSend.addr=0;
SpiSend.addrLen=0;
SpiSend.cmd=0;
SpiSend.cmdLen=0;
SPIInit(SpiNum_HSPI,&spiConfig);//初始化SPI
其它频率
typedef enum
{
SpiSpeed_0_5MHz = 160,
SpiSpeed_1MHz = 80,
SpiSpeed_2MHz = 40,
SpiSpeed_5MHz = 16,
SpiSpeed_8MHz = 10,
SpiSpeed_10MHz = 8,
SpiSpeed_20MHz = 4,
SpiSpeed_40MHz = 2,
SpiSpeed_80MHz = 1,
} SpiSpeed;
|