树莓派与STM32之间的SPI通信
树莓派的SPI模块
树莓派的GPIO引脚支持UART、SPI和I2C三种通信协议。SPI是双向、同步、全双工的串行协议,是三种协议中通信速率最快的。官方文档介绍了树莓派SPI模块的基本情况:
- 硬件引脚分配
- 树莓派SPI硬件在Linux系统中抽象成
/dev/spidev0.0
文件 - 树莓派的SPI只支持主模式(Master Mode)
- 除了通信速率、CPOL、CPHA这三个重要参数外,其他参数一般不修改
- 提供一段回环测试程序,可用于检测SPI模块是否正常工作
看到/dev/spidev0.0
文件,熟悉Linux系统编程的人马上会想起通用I/O模型中的几个函数。的确,可以在该文件上执行open
和close
操作,就跟操作普通文件一样。同样地,read
和write
函数可以读写数据,但只能进行基本的半双工数据传输,片选信号在读写操作之间会失效。使用ioctl()
函数的SPI_IOC_MESSAGE(N)
请求可实现全双工数据传输,而且整个过程中片选信号不会失效。
Linux内核代码的/tools/spi/
目录下有个spidev_test.c文件,是SPI的示例程序。这段代码实现了一个命令行工具,既可以直接使用,也可以借鉴它的代码来实现自己的需求。编译代码生成可执行文件spidev_test
,下面的命令在默认配置下通过SPI发送文件的内容,并把从SPI接收的数据保存到另一个文件中:
1 | $ ./spidev_test -D /dev/spidev0.0 -i send.txt -o receive.txt -v |
通过-s
、-O
和-H
选项可以分别修改通信速率、CPOL和CPHA三个参数,-v
选项可以打印发送和接收的内容。正如上面提到的,这段代码就是使用ioctl()
函数实现全双工数据传输,详情可以阅读源文件中的transfer
函数。
与STM32的通信
首先将树莓派和STM32对应的SPI引脚连接好。为了验证树莓派和STM32之间的SPI通信是正确的,代码将实现如下功能:
- 树莓派发送一个32字节大小的文件给STM32,STM32收完之后用串口发送出去,在PC端的串口助手上查看数据
- STM32同时也给树莓派发送数据,树莓派上可通过
-v
选项查看STM32发送过来的数据
STM32的SPI配置成全双工、从模式(Slave Mode),CPHA和CPOL参数都为0。部分代码如下:
1 | // |
STM32接收和发送数据都在中断中进行。发送缓冲区为空时会触发TXE中断,这时没有可发的数据,调用SendData函数发送数据;接收缓冲区不为空时说明有新的数据到了,此时会触发RXNE中断,调用ReceiveData函数读出数据。
1 |
|
将STM32串口线连接到PC上,打开串口助手,打开对应的COM口,在树莓派上运行命令向STM32发送文件。如果串口助手中接受到的数据和原文件完全相符,而且树莓派上显示的也是STM32发送的数据,就证明双向通信是正确的。