当前位置: 首页 > Linux

树莓派与STM32的SPI通信

时间:2023-04-06 05:35:11 Linux

原文地址:树莓派与STM32的SPI通信|鑫未央的网络日志树莓派SPI模块树莓派的GPIO引脚支持UART、SPI和I2C三种通信协议。SPI是一种双向、同步、全双工的串行协议,在三种协议中通信速率最快。树莓派官方文档从以下几个方面详细介绍了SPI模块的基本特性:硬件管脚分配在树莓派的Linux系统中,SPI硬件被抽象到/dev/spidev0.0文件。树莓派的SPI只支持主控模式(MasterMode)配置参数:除通信速率、CPOL、CPHA这三个参数外,其他参数一般不用修改。提供环回测试程序,可用于检测SPI模块是否正常工作。接下来介绍树莓派SPI模块的使用方法。看到/dev/spidev0.0这个文件,熟悉Linux系统编程的人会立刻想到通用I/O模型中的几个函数。实际上,可以像普通文件一样对文件执行打开和关闭操作。同样,读写函数可以读写数据,但只能进行基本的半双工数据传输,读写操作之间片选信号会失效。使用ioctl()函数的SPI_IOC_MESSAGE(N)请求可以实现全双工数据传输,整个过程片选信号不会失效。Linux内核代码/tools/spi/目录下有一个spidev_test.c文件,是SPI的一个示例程序。这段代码实现了一个命令行工具,可以直接使用,也可以借鉴其代码实现自己的需求。编译代码生成可执行文件spidev_test。以下命令使用默认配置通过SPI发送一个文件的内容,并将从SPI接收到的数据保存到另一个文件:$./spidev_test-D/dev/spidev0.0-isend.txt-oreceive.txt-v通过-s、-O、-H选项可以分别修改通信速率、CPOL、CPHA三个参数,-v选项可以打印发送和接收的内容。如上所述,这段代码使用ioctl()函数来实现全双工数据传输。详情请阅读源文件中的传递函数。STM32代码先将树莓派和STM32对应的SPI引脚连接起来。为了验证树莓派与STM32的SPI通信是否正确,我将实现如下功能:树莓派向STM32发送一个32字节的文件,STM32接收后通过串口发送出去。PC端串口助手查看STM32上的数据,同时向树莓派发送数据。在树莓派上可以使用-v选项查看STM32发送的数据。.部分代码如下:////省略GPIO配置,其他初始化和NVIC配置代码////双线全双工通信,从机模式,软件控制片选信号SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;SPI_InitStructure。SPI_Mode=SPI_Mode_Slave;SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;//CPOL=0SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;//CPHA=0SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//使能TXE和RXNE中断SPI_I2S_ITConfig(SPI_MASTER,SPI_I2S_IT_TXE,ENABLE);SPI_I2S_ITConfig(SPI_MASTER,SPI_I2S_IT_RXNE,ENABLE);STM32在中断中接收和发送数据。当发送缓冲区为空时,TXE中断将被触发。此时没有数据发送,调用SendData函数发送数据;当接收缓冲区不为空时,表示有新数据到达。此时触发RXNE中断,调用ReceiveData函数读出数据。#defineTX_SIZE32#defineRX_SIZE32//发送给树莓派的数据uint8_tspi_tx[TX_SIZE]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0fe,0x10、0x11、0x12、0x13、0x14、0x15、0x16、0x18、0x19、0x1a、0x1b、0x1c、0x1d、0x1F、0x20};uINT32_TTX_IDX=0;uint32_trx_idx=0;voidSPI1_IRQHandler(void){inti;如果(SPI_I2S_GetITStatus(SPI1,SPI_I2S_IT_TXE)!=RESET){SPI_I2S_SendData(SPI1,spi_tx[tx_idx++]);//发送32个数据后禁用TXE中断if(tx_idx==TX_SIZE){SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE,DISABLE);}}//从SPI读取数据32字节后,将接收到的内容通过串口发送if(rx_idx==RX_SIZE){for(i=0;i