STM32微控制器因其强大的处理能力和丰富的外设接口,在嵌入式系统设计中扮演着重要角色。高级通信接口如UART、SPI、I2C和CAN等,使得STM32能够与各种外围设备进行高效的数据交换。本文将详细解析这些高级通信接口,并提供STM32的实现代码示例。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇
1. 引言
在嵌入式系统中,通信接口是实现设备间数据交换的关键。STM32微控制器提供了多种高级通信接口,每种接口都有其特定的应用场景和优势。理解这些通信接口的工作原理和如何在STM32中实现它们,对于设计高效、可靠的嵌入式系统至关重要。
2. UART(通用异步接收/传输)
UART是一种常用的串行通信接口,广泛应用于微控制器与计算机、传感器等设备之间的数据传输。
2.1 UART工作原理
UART通信是异步的,数据以字符为单位传输,每个字符包含起始位、数据位、停止位和奇偶校验位(可选)。波特率定义了每秒传输的波特数,是UART通信的关键参数。
2.2 UART在STM32中的实现
以下是STM32中实现UART通信的示例代码:
#include "stm32f10x.h"
void UART_Init(void) {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置USART1的TX和RX引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置USART1
USART_InitStructure.USART_BaudRate = 9600;
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_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void UART_SendData(USART_TypeDef* USARTx, uint8_t* Data, uint16_t DataLength) {
for(uint16_t i = 0; i < DataLength; i++) {
USART_SendData(USARTx, Data[i]);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
}
int main(void) {
UART_Init();
uint8_t data[] = "Hello, UART!";
while(1) {
UART_SendData(USART1, data, sizeof(data));
}
}
3. SPI(串行外围设备接口)
SPI是一种高速、全双工的串行通信协议,常用于微控制器与存储设备、传感器等外围设备之间的数据交换。
3.1 SPI工作原理
SPI通信涉及四个基本信号:SCLK(时钟信号)、MOSI(主设备数据输出)、MISO(主设备数据输入)、CS(片选信号)。SPI支持主设备和从设备模式,数据传输是同步的。
3.2 SPI在STM32中的实现
以下是STM32中实现SPI通信的示例代码:
#include "stm32f10x.h"
void SPI_Init(void) {
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置SPI1的MISO、MOSI和SCK引脚
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);
// 配置SPI1
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_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
uint8_t SPI_SendReceiveData(SPI_TypeDef* SPIx, uint8_t data) {
SPI_I2S_SendData(SPIx, data);
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPIx);
}
int main(void) {
SPI_Init();
while(1) {
uint8_t data = 0xAA;
uint8_t received_data = SPI_SendReceiveData(SPI1, data);
// 处理接收到的数据
}
}
4. I2C(互连集成电路)
I2C是一种多主机、多从设备的串行通信协议,常用于微控制器与传感器、EEPROM等低速外围设备之间的数据交换。
4.1 I2C工作原理
I2C通信涉及两条线:SDA(数据线)和SCL(时钟线)。I2C支持多主机和多从设备,每个从设备都有一个唯一的地址。
4.2 I2C在STM32中的实现
以下是STM32中实现I2C通信的示例代码:
#include "stm32f10x.h"
void I2C_Init(void) {
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_I2C1, ENABLE);
// 配置I2C1的SCL和SDA引脚
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);
// 配置I2C1
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_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
uint8_t I2C_SendReceiveData(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t* pBuffer, uint16_t BufferSize) {
I2C_AcknowledgeConfig(I2Cx, ENABLE);
I2C_Start(I2Cx, Address, I2C_Direction_Transmitter);
for(uint16_t i = 0; i < BufferSize; i++) {
I2C_SendData(I2Cx, pBuffer[i]);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
I2C_GenerateSTOP(I2Cx, ENABLE);
return 0;
}
int main(void) {
I2C_Init();
uint8_t data[] = {0x01, 0x02, 0x03};
while(1) {
I2C_SendReceiveData(I2C1, 0x50, data, sizeof(data));
}
}
5. CAN(控制器局域网络)
CAN是一种多主机、高可靠性的串行通信协议,常用于汽车和工业自动化领域。
5.1 CAN工作原理
CAN通信基于消息传递,每个消息包含一个标识符和一个数据字段。CAN支持多主机,每个主机都可以发送和接收消息。
5.2 CAN在STM32中的实现
以下是STM32中实现CAN通信的示例代码:
#include "stm32f10x.h"
void CAN_Init(void) {
CAN_InitTypeDef CAN_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
// 配置CAN1的TX和RX引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
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_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置CAN1
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 4;
CAN_Init(CAN1, &CAN_InitStructure);
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_Cmd(CAN1, ENABLE);
}
int main(void) {
CAN_Init();
CAN_MsgTypeDef CAN_Msg;
CAN_Msg.IDE = CAN_Id_Standard;
CAN_Msg.RTR = CAN_RTR_Data;
CAN_Msg.StdId = 0x5A5;
CAN_Msg.DLC = 8;
while(1) {
CAN_Msg.Data[0] = 0x01;
CAN_Msg.Data[1] = 0x02;
CAN_Msg.Data[2] = 0x03;
CAN_Msg.Data[3] = 0x04;
CAN_Msg.Data[4] = 0x05;
CAN_Msg.Data[5] = 0x06;
CAN_Msg.Data[6] = 0x07;
CAN_Msg.Data[7] = 0x08;
if(CAN_Transmit(CAN1, &CAN_Msg) == CAN_TxStatus_Ok) {
// 处理发送成功
}
}
}
6. 结论
STM32微控制器提供的高级通信接口如UART、SPI、I2C和CAN,为嵌入式系统设计提供了强大的支持。每种通信接口都有其特定的应用场景和优势。通过合理的硬件选择和高效的软件实现,可以充分发挥STM32微控制器的性能和灵活性。
7. 参考文献
- STMicroelectronics. (2011). STM32F103C8T6 datasheet.
- Wikipedia. (2024). UART, SPI, I2C, CAN.