STM32基础开发入门:串口通信数据发送与接收详解
STM32基础入门开发: 串口数据发送与接收
引言
在嵌入式开发中,串口通信是一种常见的外设接口,广泛应用于数据传输和设备控制。本篇文章将介绍如何在STM32F103C8T6开发板上,通过串口1实现数据的发送和接收,并根据接收到的指令控制LED灯的开关。开发环境使用Keil 5,编程语言为C语言,库使用STM32标准库3.5版本。
硬件连接
功能需求
关键点
开发步骤
1. 硬件初始化
首先,需要对PB0引脚进行初始化,将其设置为推挽输出模式,用于控制LED灯的开关。
2. 串口初始化
串口的初始化涉及到波特率、数据位、停止位、校验位等的配置。对于STM32F103C8T6,使用USART1进行串口通信。
3. 串口发送和接收
使用标准库提供的串口函数来发送和接收数据,通过中断或轮询方式读取接收到的数据并解析。
4. 控制LED灯
根据接收到的数据判断是否是"LED_ON"或"LED_OFF"指令,进而控制LED的点亮或熄灭。
代码实现
以下是基于STM32标准库3.5版本的完整代码,代码中包含详细注释说明。
#include "stm32f10x.h"
#include <string.h>
#define LED_PIN GPIO_Pin_0 // LED连接的引脚:PB0
// 串口1的缓冲区
#define RX_BUFFER_SIZE 64
char RxBuffer[RX_BUFFER_SIZE]; // 接收数据的缓冲区
volatile uint8_t RxIndex = 0; // 接收数据的索引
// 初始化LED引脚
void LED_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置PB0为推挽输出,LED控制引脚
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
// 点亮LED
void LED_On(void) {
GPIO_SetBits(GPIOB, LED_PIN); // 设置PB0为高电平,点亮LED
}
// 熄灭LED
void LED_Off(void) {
GPIO_ResetBits(GPIOB, LED_PIN); // 设置PB0为低电平,熄灭LED
}
// 初始化串口1
void USART1_Init(void) {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能USART1和其对应的GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置USART1的TX (PA9) 和 RX (PA10) 引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX
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; // RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置USART1
USART_InitStructure.USART_BaudRate = 9600; // 波特率9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 数据位8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位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);
// 使能USART1
USART_Cmd(USART1, ENABLE);
// 使能USART1接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
// 串口发送字符
void USART_SendChar(char c) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送缓冲区空
USART_SendData(USART1, c); // 发送数据
}
// 串口接收中断处理函数
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
char received = USART_ReceiveData(USART1); // 接收数据
if (RxIndex < RX_BUFFER_SIZE - 1) {
RxBuffer[RxIndex++] = received; // 存入缓冲区
RxBuffer[RxIndex] = '\0'; // 保证字符串结尾
}
}
}
// 串口接收并处理命令
void Process_Command(void) {
if (strcmp(RxBuffer, "LED_ON") == 0) {
LED_On(); // 点亮LED
} else if (strcmp(RxBuffer, "LED_OFF") == 0) {
LED_Off(); // 熄灭LED
}
}
// 主程序
int main(void) {
// 初始化LED引脚
LED_Init();
// 初始化串口1
USART1_Init();
// 开启全局中断
NVIC_EnableIRQ(USART1_IRQn);
while (1) {
// 在主循环中持续监控接收到的命令
if (RxIndex > 0) {
Process_Command(); // 处理接收到的命令
RxIndex = 0; // 重置接收索引,等待下一个命令
}
}
}
代码解析
-
LED初始化:
LED_Init()
函数配置PB0引脚为推挽输出,用于控制LED的点亮与熄灭。LED_On()
和LED_Off()
函数分别控制LED的开与关。 -
串口初始化:
USART1_Init()
函数配置了USART1的波特率、数据位、停止位等参数,并启用接收中断。PA9为串口1的TX(发送)引脚,PA10为RX(接收)引脚。 -
串口中断处理:
USART1_IRQHandler()
是USART1的中断服务函数,当接收到数据时,数据被存入RxBuffer
缓冲区。 -
命令处理:
Process_Command()
函数根据接收到的字符串判断是否为"LED_ON"或"LED_OFF"命令,分别控制LED的状态。 -
主循环:在
main()
函数中,主循环持续监控串口接收缓冲区,当接收到数据时,调用Process_Command()
处理命令并重置接收索引。
测试
使用串口调试工具(如PuTTY或Tera Term)与STM32开发板进行通信,发送以下命令测试LED灯控制功能:
LED_ON
:LED点亮LED_OFF
:LED熄灭总结
通过本文的学习,可以掌握如何在STM32F103C8T6开发板上实现基本的串口通信功能,完成数据的发送和接收,并通过串口接收控制命令来控制硬件(如LED灯)的状态。该示例代码简单而完整,为嵌入式开发中的串口通信奠定了基础。
作者:开源云端架构师