探索嵌入式系统中 STM32 与树莓派的高效通信方式
摘要: 本文深入探讨了在嵌入式系统中实现 STM32 与树莓派高效通信的多种方式。首先对 STM32 和树莓派进行了简要介绍,然后分别阐述了常见的通信接口如串口、SPI、I2C 等在两者之间的应用。通过详细的代码示例和硬件连接说明,展示了如何进行有效的数据传输和交互。同时,对不同通信方式的性能和适用场景进行了分析和比较,为开发者在实际项目中选择合适的通信方案提供了参考。
一、引言
随着嵌入式技术的不断发展,在一个系统中常常需要多个控制器协同工作以实现更复杂的功能。STM32 作为一款高性能、低功耗的微控制器,广泛应用于各种嵌入式终端设备;树莓派则以其强大的计算能力和丰富的接口资源,在嵌入式服务器和智能控制中心等领域发挥着重要作用。实现 STM32 与树莓派之间的高效通信,对于构建功能强大、性能优越的嵌入式系统具有重要意义。
二、STM32 与树莓派简介
(一)STM32
STM32 系列微控制器是意法半导体(STMicroelectronics)基于 ARM Cortex-M 内核推出的产品。它具有丰富的外设资源、较高的运行速度和较低的功耗,适用于工业控制、消费电子、医疗设备等众多领域。
(二)树莓派
树莓派是一款基于 Linux 操作系统的单板计算机,具有强大的处理能力、丰富的接口和开源社区支持。它常用于物联网、智能家居、教育等领域,作为控制中心或数据处理节点。
三、通信接口选择
(一)串口通信
串口通信是一种简单、常用的异步通信方式,只需要两根数据线(TX 和 RX)即可实现数据传输。但串口通信速度相对较慢,适用于数据量较小、对实时性要求不高的场景。
(二)SPI 通信
SPI(Serial Peripheral Interface)是一种同步串行通信接口,具有高速、全双工的特点。需要四根数据线(SCK、MOSI、MISO、CS),适用于高速数据传输,如传感器数据采集、显示驱动等。
(三)I2C 通信
I2C(Inter-Integrated Circuit)是一种两线式串行总线,只需 SDA 和 SCL 两根线即可连接多个设备。但 I2C 通信速度相对较低,适用于连接多个低速设备,如 EEPROM、温度传感器等。
四、串口通信实现
(一)硬件连接
将 STM32 的串口引脚(如 USART1 的 PA9 和 PA10)分别连接到树莓派的串口引脚(如 GPIO14 和 GPIO15)。
(二)STM32 串口配置代码
#include "stm32f10x.h"void USART1_Init(uint32_t baudrate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = baudrate;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);
}void USART1_SendChar(char c)
{while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);USART_SendData(USART1, (uint8_t)c);
}void USART1_SendString(char *str)
{while (*str){USART1_SendChar(*str++);}
}
(三)树莓派串口配置(使用 Python)
import serialser = serial.Serial('/dev/ttyAMA0', 9600) # 波特率 9600def send_data(data):ser.write(data.encode())def receive_data():if ser.in_waiting:return ser.readline().decode()else:return None
五、SPI 通信实现
(一)硬件连接
STM32 的 SPI 引脚(如 SPI1 的 SCK、MISO、MOSI、NSS)分别连接到树莓派对应的 SPI 引脚。
(二)STM32 SPI 配置代码
#include "stm32f10x.h"void SPI1_Init()
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);
}void SPI1_SendData(uint8_t data)
{while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI1, data);
}uint8_t SPI1_ReceiveData()
{while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);return SPI_I2S_ReceiveData(SPI1);
}
(三)树莓派 SPI 配置(使用 Python)
import spidevspi = spidev.SpiDev()
spi.open(0, 0) # 打开 SPI 设备def spi_send_data(data):spi.xfer2(data)def spi_receive_data():return spi.xfer2([0x00])[0]
六、I2C 通信实现
(一)硬件连接
将 STM32 的 I2C 引脚(如 I2C1 的 SCL 和 SDA)连接到树莓派对应的 I2C 引脚。
(二)STM32 I2C 配置代码
#include "stm32f10x.h"void I2C1_Init()
{GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 = 0x00;I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000;I2C_Init(I2C1, &I2C_InitStructure);I2C_Cmd(I2C1, ENABLE);
}void I2C1_WriteData(uint8_t slave_address, uint8_t *data, uint16_t size)
{while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));I2C_GenerateSTART(I2C1, ENABLE);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Transmitter);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));while (size--){I2C_SendData(I2C1, *data++);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));}I2C_GenerateSTOP(I2C1, ENABLE);
}void I2C1_ReadData(uint8_t slave_address, uint8_t *data, uint16_t size)
{while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));I2C_GenerateSTART(I2C1, ENABLE);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Receiver);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));while (size){if (size == 1){I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_GenerateSTOP(I2C1, ENABLE);}while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));*data++ = I2C_ReceiveData(I2C1);size--;}I2C_AcknowledgeConfig(I2C1, ENABLE);
}
(三)树莓派 I2C 配置(使用 Python)
import smbusbus = smbus.SMBus(1) # 选择 I2C 总线 1def i2c_write_data(slave_address, data):bus.write_byte_data(slave_address, 0, data)def i2c_read_data(slave_address):return bus.read_byte_data(slave_address, 0)
七、通信性能比较与应用场景分析
(一)串口通信
性能:速度较慢,一般在几十 kbps 到几 Mbps 之间。
应用场景:适用于简单的数据传输,如调试信息、少量控制指令等。
(二)SPI 通信
性能:速度较高,可达几十 Mbps。
应用场景:高速数据传输,如图像数据、音频数据等。
(三)I2C 通信
性能:速度相对较低,一般在几百 kbps 以下。
应用场景:连接多个低速设备,如传感器、EEPROM 等。
八、结论
通过对 STM32 与树莓派之间串口、SPI 和 I2C 通信方式的详细介绍和实现,我们可以根据具体的项目需求选择合适的通信接口。在实际应用中,还需要考虑通信速度、数据量、实时性要求以及硬件连接的复杂性等因素,以实现高效、稳定的嵌入式系统通信。
希望本文能够为您在嵌入式系统开发中实现 STM32 与树莓派的通信提供有益的参考和帮助。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇
点击领取更多详细资料