最近要用到STM32的SPI从机模式,从其他板子读SPI数据过来,踩了2天坑,记录一下过程。
(因为hal库提供了三种函数,我调试的过程是阻塞、中断、DMA依次来调试学习的,这份代码为使用DMA方式的代码。)
软件:keil5、STM32CubeMX
硬件:两块STM32F103C8T6最小系统
实现功能:两块板子进行SPI通信,一主一从,都是使用的SPI1。
代码下载github:https://github.com/wyfroom/SPI_Master_Slave_STM32(第一次编程过程中使用git管理代码)
代码下载蓝奏云:https://wwzr.lanzout.com/b04885ouf 密码:372j
强调!!!!!!!!!!!强调!!!!!!!!!!!!强调!!!!!!!!!!!!!
如果你SPI通了,但是莫名其妙数据乱码、能发不能收等问题,啥都别干了,先把杜邦线换新,一共5根线,一根共地线,四根SPI线。
基础的工程配置,这边就不贴图了,可以看这个有详细的步骤:http://t.csdn.cn/Wpcpk
直接看spi的配置,主要注意以下几点:
如果要用SPI中断,要勾选中断。
如果要用DMA,要对DMA进行配置。
补充:片选还是要选,不然高速传输会出问题。
从机配置仅模式选择和主机不同,其他都一样且必须一样。
如果使用中断,要勾选:
DMA配置:(和主机一样)
补充:片选还是要选,不然高速传输时会出问题。
HAL库提供了三种SPI调用方式。都试了一遍,最后还是选用了DMA,高效,简洁。
//阻塞方式使用SPI
HAL_SPI_Transmit()
HAL_SPI_Receive()
HAL_SPI_TransmitReceive()
//中断方式使用SPI
HAL_SPI_Transmit_IT()
HAL_SPI_Receive_IT()
HAL_SPI_TransmitReceive_IT()
//DMA方式使用SPI
HAL_SPI_Transmit_DMA()
HAL_SPI_Receive_DMA()
HAL_SPI_TransmitReceive_DMA()
主机轮询,从机中断。
这个我就不演示了,就正常流程,注意就行,在main里启动中断,在中断函数里再次启动中断。
//main里启动中断
HAL_SPI_TransmitReceive_IT(&hspi1, sendData, receiveData, 8);
//中断回调函数
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
// 数据发送完成回调函数
if (hspi == &hspi1)
{
HAL_SPI_TransmitReceive_IT(&hspi1, sendData, receiveData, 8);
}
}
主机使用阻塞函数,从机使用DMA函数。(原因是我试了主从全部使用DMA的话,速度太快了,会卡死和数据传输乱码。解决啦,可以看问题一,这一部分还是演示轮询+DMA)
debug测试:
之前高速使用时出现了程序卡死和数据乱码的现象。(高速使用:用阻塞函数while里不加延时、主从都用中断、主从都用DMA)
解决方法如下:
直接Debug:(模拟实际上电,debug先点从机启动,再点主机启动)
CRC计算生成的校验值可以用于检测数据在传输或存储过程中是否发生了错误或损坏。
开启CRC后,使用DMA函数的话,SIZE要加一:
HAL_SPI_TransmitReceive_DMA(&hspi1, sendData, receiveData, 8+1);
主机中断模式发送,从机中断模式接收,不停的收发清空标志,数据就会乱,可能是传的太快了??想当于是全速的在收发? 非得主机用轮询的方式,间隔个1ms什么的来读取,那这SPI速度咋算的?
主机DMA发,从机DMA收,直接死机,DMA中断被刷爆,while里的程序没机会执行,可以屏蔽掉DMA中断,程序不会在死机,但是,数据会乱。
加了CRC好像要好一点,但还是很多乱码,碰运气碰好的。这能行吗?是SPI就不是这么用的吗?还是说这事高速传输的共性问题。
终于解决: