STM32嵌入式系统使用串口通讯控制LED灯实战指南
引言
随着物联网和智能硬件的发展,嵌入式系统的应用越来越广泛。STM32作为一款性能强大、资源丰富的微控制器,在嵌入式开发领域得到了广泛的应用。串口通讯作为最基础的通信方式之一,常用于设备间或设备与计算机之间的数据交换。本文将详细介绍如何使用STM32嵌入式系统通过串口通讯控制LED灯,实现远程控制的功能。
目录
引言
一、硬件准备
二、软件环境
1、Keil MDK:
2、ST-Link/V2:
3、串口调试助手:
三、硬件连接
四、软件配置
五、编写程序
六、测试
总结
一、硬件准备
在进行实战之前,我们需要准备以下硬件:
- STM32开发板:选择一款适合的STM32开发板,如STM32F103C8T6。
- USB转TTL模块:用于与电脑进行串口通讯。
- LED灯:一个或多个LED灯。
- 电阻:限流电阻,保护LED灯不被过大的电流损坏。
- 杜邦线:用于连接各个组件。
本实验采用STM32F429的野火开发板。
二、软件环境
1、Keil MDK:
用于编写和编译STM32的程序。
2、ST-Link/V2:
用于将编译好的程序下载到STM32开发板。
3、串口调试助手:
用于在电脑端发送串口指令。
三、硬件连接
首先,我们需要将STM32开发板、USB转TTL模块和LED灯通过杜邦线连接起来。以下是一个基本的连接示例:
四、软件配置
1. 在Keil MDK或STM32CubeIDE中创建一个新项目。然后配置串口的波特率、数据位、停止位和校验位等参数。通常,我们设置波特率为9600,数据位为8,停止位为1,无校验位。
2. 配置USART模块,设置波特率、数据位、停止位和校验位。
3. 初始化GPIO引脚,将连接LED的引脚设置为输出模式。
下列代码为串口及GPIO引脚初始化:
//初始化串口 USART1
//因为要用PA9 和PA10所以先初始化
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef gpio_info;
NVIC_InitTypeDef NVIC_InitStructure;
//PH0
//初始化GPIOH时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
gpio_info.GPIO_Mode = GPIO_Mode_AF;
gpio_info.GPIO_OType = GPIO_OType_PP;
gpio_info.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
gpio_info.GPIO_PuPd = GPIO_PuPd_UP;
gpio_info.GPIO_Speed = GPIO_Low_Speed;
GPIO_Init(GPIOA,&gpio_info);
//将复用引脚连接到串口1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
//初始化串口外设
//1.使能串口1的时钟...............................................
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//2.配置串口参数
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
//3.使能接收中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//4.配置中断优先级
//配置这个外部中断的优先级
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //PA0 对应的是EXTI0_IRQn
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级
NVIC_Init(&NVIC_InitStructure);
//5.使能串口
USART_Cmd(USART1,ENABLE);
五、编写程序
1. 编写USART中断服务程序或轮询接收函数,用于接收来自PC的命令。
2. 解析接收到的命令,如果是控制LED的命令,则相应地改变LED的GPIO引脚状态。不断检查串口是否有新的数据到达,如果有,就读取并解析数据。
//编写中断服务函数
void EXTI0_IRQHandler()//中断服务函数名称
{
if(EXTI_GetITStatus(EXTI_Line0)!=RESET )//证明触发中断
{
delay_time += 10000;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI15_10_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line13)!=RESET )//证明触发中断
{
delay_time-=10000;
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
int fputc(int ch,FILE *p)
{
USART_SendData(USART1,(u8)ch);
//等待发送完成
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
return ch;
}
void SendString(char *str)
{
//如果当前字符不等于'\0',表明字符串还没有到末尾
while(*str !='\0')
{
//发送当前字符
USART_SendData(USART1,*str );
//等待当前字符发送完成
//当标准位变为SET的时候,表明发送完成
while (USART_GetFlagStatus(USART1,USART_FLAG_TXE)== RESET );
//指针指向下一个字符
str ++;
}
}
void USART1_IRQHandler()
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)!= RESET)
{
rec_data = USART_ReceiveData(USART1);
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
3. 编写主循环,持续监听串口输入。根据接收到的串口数据,我们可以控制LED灯的状态。例如,如果接收到字符'01',则点亮红灯,如果接收到字符'02',点亮蓝灯。
int main(void)
{
//初始化串口 USART1
//因为要用PA9 和PA10所以先初始化
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef gpio_info;
NVIC_InitTypeDef NVIC_InitStructure;
LED_init();
key1_init();
key2_init();
Delay_init();
//PH0
//初始化GPIOH时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
gpio_info.GPIO_Mode = GPIO_Mode_AF;
gpio_info.GPIO_OType = GPIO_OType_PP;
gpio_info.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
gpio_info.GPIO_PuPd = GPIO_PuPd_UP;
gpio_info.GPIO_Speed = GPIO_Low_Speed;
GPIO_Init(GPIOA,&gpio_info);
//将复用引脚连接到串口1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
//初始化串口外设
//1.使能串口1的时钟...............................................
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//2.配置串口参数
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
//3.使能接收中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//4.配置中断优先级
//配置这个外部中断的优先级
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //PA0 对应的是EXTI0_IRQn
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级
NVIC_Init(&NVIC_InitStructure);
//5.使能串口
USART_Cmd(USART1,ENABLE);
while(1)
//以下串口通讯协议可自行定义
{
if(rec_data == 0x01)
{
LED_Red_Ctrl(LED_ON);//开红灯
LED_Blue_Ctrl(LED_OFF);
LED_Green_Ctrl(LED_OFF);
}
else if(rec_data == 0x02)
{
LED_Red_Ctrl(LED_OFF);
LED_Blue_Ctrl(LED_ON);//开蓝灯
LED_Green_Ctrl(LED_OFF);
}
if(rec_data == 0x03)
{
LED_Red_Ctrl(LED_OFF);
LED_Blue_Ctrl(LED_OFF);
LED_Green_Ctrl(LED_ON); //开绿灯
}
if(rec_data == 0x04)
{
LED_Blue_Ctrl(LED_OFF);//全关
LED_Red_Ctrl(LED_OFF);
LED_Green_Ctrl(LED_OFF);
}
}
}
在此USART未进行模块化处理,有需要可自行进行模块化创建,使代码更为简短美观。
六、测试
1. 编译代码并烧录到STM32开发板。
2. 打开PC上的串口调试助手,设置相同的波特率,并尝试发送设置的命令。
3. 观察LED是否按照命令正确地亮起或熄灭
总结
通过上述步骤,我们成功实现了使用STM32嵌入式系统通过串口通讯控制LED灯的功能。这个简单的实战项目不仅可以帮助初学者理解串口通讯的基本原理,也为后续更复杂的项目打下了坚实的基础。在实际应用中,我们可以根据需要扩展更多的功能、添加定时功能等,从而实现更加丰富和智能的控制效果。
注意事项
– 确保所有电源和接线的连接正确无误。
– 选择合适的电阻值以保护LED和STM32的GPIO引脚。
– 在编写代码时,注意错误处理和异常情况的处理。
希望这篇博客能帮助你成功地在STM32上实现串口通信控制LED灯的功能。如果你遇到任何问题,可以查阅STM32的官方文档或在线论坛寻求帮助。
作者:Willinnn_