[应用相关] 两片STM32使用HAL完成SPI全双工主从通信

[复制链接]
 楼主| xiyaoko2365 发表于 2021-6-23 23:16 | 显示全部楼层 |阅读模式

SPI是一种非常简单易用的全双工主从式通信协议。

本文使用两片STM32F429,一个作为主机,一个作为从机完成SPI的全双工通信测试。


 楼主| xiyaoko2365 发表于 2021-6-23 23:19 | 显示全部楼层
在STM32的HAL库中简化了SPI主机端的发送接收,但是HAL库没有提供一个简单的SPI从机代码接口,这样就需要自己拼接接口来完成全双工的通信。以下都以实现全双工通信为目的进行配置和编写:
 楼主| xiyaoko2365 发表于 2021-6-23 23:20 | 显示全部楼层
一 主机端: 9604360d350f26f558.png
 楼主| xiyaoko2365 发表于 2021-6-25 23:50 | 显示全部楼层
禁止使用SPI的硬件片选信号,因为这个信号是SPI使能了之后就一直为低,直到禁止了SPI之后才为高。可以使用某一个普通IO来充当片选信号。

 楼主| xiyaoko2365 发表于 2021-6-25 23:51 | 显示全部楼层
 楼主| xiyaoko2365 发表于 2021-6-25 23:52 | 显示全部楼层
这里选用一个较低的速率来通信,在HAL库的spi头文件中有说明各个模式下SPI的最大速度。
 楼主| xiyaoko2365 发表于 2021-6-25 23:52 | 显示全部楼层
二 从机端:
1966560d5fbc0d557b.png
2776460d5fbcaeba4e.png
 楼主| xiyaoko2365 发表于 2021-6-25 23:53 | 显示全部楼层
 楼主| xiyaoko2365 发表于 2021-6-25 23:54 | 显示全部楼层
 楼主| xiyaoko2365 发表于 2021-6-25 23:54 | 显示全部楼层
主从的速率要一样,从机打开SPI中断



三 硬件连接:

主机                        从机



CS                          CS



CLK                        CLK



MISO                      MISO



MOSI                      MOSI



接收和发送都是直连不需要交叉。
 楼主| xiyaoko2365 发表于 2021-6-25 23:55 | 显示全部楼层
四 主机代码:
  1. /* USER CODE BEGIN 3 */

  2. HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);



  3. HAL_SPI_TransmitReceive(&hspi1, txbuf, rxbuf, 1, 0xFF);

  4. HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

  5. HAL_Delay(500);

  6.   }

  7.   /* USER CODE END 3 */
 楼主| xiyaoko2365 发表于 2021-6-25 23:56 | 显示全部楼层
五 从机代码:
  1. 现在while之前打开spi接收中断:



  2.   /* USER CODE BEGIN 2 */

  3. HAL_SPI_Receive_IT(&hspi1, rxbuf, 1);

  4.   /* USER CODE END 2 */

  5. 在中断中使用阻塞函数把数据发送出去:



  6. /* USER CODE BEGIN 4 */

  7. void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)

  8. {

  9. if (hspi == &hspi1)

  10. {

  11. HAL_SPI_Transmit(&hspi1, txbuf, 1, 0xFFFF);

  12. HAL_SPI_Receive_IT(&hspi1, rxbuf, 1);

  13. }

  14. }

  15. /* USER CODE END 4 */
 楼主| xiyaoko2365 发表于 2021-6-25 23:57 | 显示全部楼层
使用逻辑分析仪可以看到主机在发送的同时也收到了从机返回的数据。



可能在中断里调用阻塞发送不是很好,如果有更好的方法欢迎指正。

 楼主| xiyaoko2365 发表于 2021-6-25 23:57 | 显示全部楼层
另外在一片stm32上使用两个SPI接口模拟主从机通信好像不能正常工作。





最后需要注意的是如果你使用了以上方法,能测试spi通信成功,但是当主程序有其他任务的时候就会非常卡顿,因为在中断中调用了阻塞发送的函数。为了让程序更加流畅一种方法是减小HAL_SPI_Transmit的等待时间,另外一种方法就是使用DMA.



因为这里我只需要用DMA回复SPI master数据,所以我只开启了从机的SPI发送DMA,而且没有使能DMA中断。
 楼主| xiyaoko2365 发表于 2021-6-25 23:58 | 显示全部楼层
将spi.c中的代码更改如下:
  1. /* USER CODE BEGIN 1 */

  2. void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)

  3. {

  4. if (hspi == &hspi1)

  5. {

  6. HAL_SPI_Transmit_DMA(&hspi1, p_phase_buf, 1);

  7. //HAL_SPI_Transmit(&hspi1, p_phase_buf, 1, 0xFFF);

  8. HAL_SPI_Receive_IT(&hspi1, p_pwm_freq, 1);

  9. }

  10. }

  11. /* USER CODE END 1 */
 楼主| xiyaoko2365 发表于 2021-6-25 23:59 | 显示全部楼层
添加DMA就是这么简单,由此就看到HAL库高效的地方了,使用起来确实能大幅提高工作效率

菜鸟的第一步 发表于 2021-6-30 16:48 | 显示全部楼层
使用cube是真的简单,这个工具大大简化了原始工程构建,就是代码太冗杂,执行效率太低。
skyred 发表于 2021-7-1 15:21 | 显示全部楼层
这是cube的应用啊~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

511

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部