STM32嵌入式系统使用串口通讯控制LED灯实战指南

引言

随着物联网和智能硬件的发展,嵌入式系统的应用越来越广泛。STM32作为一款性能强大、资源丰富的微控制器,在嵌入式开发领域得到了广泛的应用。串口通讯作为最基础的通信方式之一,常用于设备间或设备与计算机之间的数据交换。本文将详细介绍如何使用STM32嵌入式系统通过串口通讯控制LED灯,实现远程控制的功能。

目录

引言

一、硬件准备

二、软件环境

1、Keil MDK:

2、ST-Link/V2:

3、串口调试助手:

三、硬件连接

四、软件配置

五、编写程序

六、测试

总结


一、硬件准备

在进行实战之前,我们需要准备以下硬件:

  1. STM32开发板:选择一款适合的STM32开发板,如STM32F103C8T6。
  2. USB转TTL模块:用于与电脑进行串口通讯。
  3. LED灯:一个或多个LED灯。
  4. 电阻:限流电阻,保护LED灯不被过大的电流损坏。
  5. 杜邦线:用于连接各个组件。

本实验采用STM32F429的野火开发板。

二、软件环境

1、Keil MDK

用于编写和编译STM32的程序。

2、ST-Link/V2

用于将编译好的程序下载到STM32开发板。

3、串口调试助手

用于在电脑端发送串口指令。

三、硬件连接

首先,我们需要将STM32开发板、USB转TTL模块和LED灯通过杜邦线连接起来。以下是一个基本的连接示例:

  • 将STM32的串口TX引脚连接到USB转TTL模块的RX引脚。
  • 将STM32的串口RX引脚连接到USB转TTL模块的TX引脚。
  • 将LED的正极通过限流电阻连接到STM32的一个GPIO引脚,负极连接到GND。
  • 四、软件配置

    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_

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32嵌入式系统使用串口通讯控制LED灯实战指南

    发表回复