关于STM32 SPI通讯发送过程问题的探讨

多年前在使用STM32中的硬件SPI通讯过程中,发现所给的例程实际上是有问题的。最近我的学生跟同事总跟我反映:“SPI通讯他们调试速度总是上不去,芯片支持到25MHz,我们只能做到1M左右。”
今天台式SPI的时候,我将这个问题放上来说一下。
在STM32的SPI通讯过程中,非DMA模式下,每发送一个数据后,我们的代码是这样写的:

void SPI1_Send_Byte(unsigned char dat)
{
 SPI_I2S_SendData(SPI1,dat);//写1个字节数据
 while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待数据寄存器空,为空不一定传输完成
}

while也可以放在SPI_I2S_SendData前面,但是这样的通讯,如果SPI从机需要CS信号来锁存,则会出现问题,while中实际在判断SPI_I2S_FLAG_TXE是否复位,也就是发送寄存器是否为空,而许多处理器他的SPI结构是这样的。
在这里插入图片描述
从图中其实不难理解,发送缓冲区空,数据其实还没有被完全发送给从机,数据要出去必须一位一位的移走。只是发送缓冲区为空:仅仅表示你可以继续向SPI写数据而已。所以,很多时候,我们采用为空,表示我们发送结束,继而操作CS,则会出现问题,如下:

void SPI1_Write(unsigned short reg, unsigned char dat)
{
 GPIO_ResetBits(SCS_PORT, nSCS);//置SCS为低电平
   
 SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址 
 SPI1_Send_Byte(0x05);//通过SPI1写16位寄存器地址 
 SPI1_Send_Byte(dat);//写16位数据
 
 GPIO_SetBits(SCS_PORT, nSCS); //置W5500的SCS为高电平
}

代码中,reg为0,dat为0
在这里插入图片描述从图中明显看出,通过
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待数
判断发送寄存器为空来操作CS,会导致最后一个数据没有发出来,CS就被拉高了。
如何解决这个问题?很多时候,我们就采用延时的办法,延时多久呢?延时一个8位数据的时间,显然这样的操作不是特么那么那么爽。其实在最后一个数据操作CS的时候,我们可以采用SPI的另一个标志来判断,也就是busy位。见数据手册说明:
在这里插入图片描述
要注意的是,不要用BUSY为来判断是否可以发送数据,理所当然的这样会影响通讯效率。增加一行代码如下:

void SPI1_Write(unsigned short reg, unsigned char dat)
{
 GPIO_ResetBits(SCS_PORT, nSCS);//置SCS为低电平
   
 SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址 
 SPI1_Send_Byte(0x05);//通过SPI1写16位寄存器地址 
 SPI1_Send_Byte(dat);//写16位数据
 
 while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //是否传输完成?
 GPIO_SetBits(SCS_PORT, nSCS); //置W5500的SCS为高电平
}

在这里插入图片描述

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值