STM32实现按键控制LED灯闪烁速度调整的高级教程

       STM32是一款由意法半导体(STMicroelectronics)推出的32位ARM Cortex-M内核微控制器系列,专为要求高性能、低成本、低功耗的嵌入式应用而设计。谐振电路主要利用 三极管 特性,让电路持续交替出现高低电平的现象,根据这个特点,可以制作LED交替闪烁的效果。

 以下内容是将在STM32单片机上实现LED灯交替闪烁,并根据按键key1key2的输入来改变闪烁速度。按下key1时,红绿蓝灯的交替闪烁减慢,按下key2时,红绿蓝灯的交替闪烁加快。

目录

1.定义

2. 初始化GPIO

(1)初始化LED

(2)初始化key1、key2 按键

3.配置按键中断

4.宏定义

红灯的引脚为GPIO_Pin_10

绿灯的引脚为GPIO_Pin_11

蓝灯的引脚为GPIO_Pin_12

5.配置延迟函数

6.主循环

完整代码: 

7.烧录


1.定义

2. 初始化GPIO

  1. 配置引脚功能
  2. GPIO引脚通常具有多种功能,如数字输入/输出、模拟输入、PWM(脉宽调制)输出、I2C、SPI等。初始化GPIO时,需要指定引脚的具体功能,以确保它按照预期的方式工作。
  3. 设置输入/输出模式
  4. 对于数字GPIO引脚,需要设置其是输入模式还是输出模式。输入模式用于读取外部信号,而输出模式用于向外部设备发送信号。
  • 初始化GPIO引脚为输出模式(用于LED)。
  • 初始化GPIO引脚为输入模式(用于按键)。
  • (1)初始化LED

    (2)初始化key1、key2 按键

    void key1_init()
    {
        GPIO_InitTypeDef gpio_info;
        EXTI_InitTypeDef exti_info;
        NVIC_InitTypeDef  NVIC_InitStructure;
        //PA0
        //初始化GPIOA的时钟    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
        //初始化中断时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
        
        //配置按键
        gpio_info.GPIO_Mode = GPIO_Mode_IN;
        gpio_info.GPIO_OType = GPIO_OType_PP;
        gpio_info.GPIO_Pin = GPIO_Pin_0;
        gpio_info.GPIO_PuPd = GPIO_PuPd_NOPULL;
        gpio_info.GPIO_Speed = GPIO_Low_Speed;
        GPIO_Init(GPIOA,&gpio_info);
        
    
        //配置按键的外部中断
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
        exti_info.EXTI_Line = EXTI_Line0;
        exti_info.EXTI_LineCmd = ENABLE;
        exti_info.EXTI_Mode = EXTI_Mode_Interrupt;
        exti_info.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_Init(&exti_info);
        
        //配置这个外部中断的优先级
        NVIC_InitStructure.NVIC_IRQChannel =  EXTI0_IRQn;   //PA0 对应的是EXTI0_IRQn
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
        NVIC_Init(&NVIC_InitStructure);
    }
    
    void key2_init()
    {
        GPIO_InitTypeDef gpio_info;
        EXTI_InitTypeDef exti_info;
        NVIC_InitTypeDef  NVIC_InitStructure;
        //PC13
        //初始化GPIOA的时钟    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
        //初始化中断时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
        
        //配置按键
        gpio_info.GPIO_Mode = GPIO_Mode_IN;
        gpio_info.GPIO_OType = GPIO_OType_PP;
        gpio_info.GPIO_Pin = GPIO_Pin_13;
        gpio_info.GPIO_PuPd = GPIO_PuPd_NOPULL;
        gpio_info.GPIO_Speed = GPIO_Low_Speed;
        GPIO_Init(GPIOC,&gpio_info);
        
    
        //配置按键的外部中断
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource13);
        exti_info.EXTI_Line = EXTI_Line13;
        exti_info.EXTI_LineCmd = ENABLE;
        exti_info.EXTI_Mode = EXTI_Mode_Interrupt;
        exti_info.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_Init(&exti_info);
    
        //配置这个外部中断的优先级
        NVIC_InitStructure.NVIC_IRQChannel =  EXTI15_10_IRQn;   //PA0 对应的是EXTI0_IRQn
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
        NVIC_Init(&NVIC_InitStructure);
    }
    

    3.配置按键中断

    确保当按键按下时,能够触发EXTI中断,进而打断CPU正在执行的程序,使程序跳转到EXTI中断服务程序中执行。配置按键中断可以提高系统的实时性、CPU使用效率和编程便利性。

  • 如果key1被按下,减少LED闪烁的延迟时间,从而减慢闪烁速度。
  • 如果key2被按下,增加LED闪烁的延迟时间,从而加快闪烁速度。 
  • 并配置中断函数
  • //编写中断服务函数 key1
    void EXTI0_IRQHandler()
    {    
    	if(EXTI_GetITStatus(EXTI_Line0) != RESET)//证明
    	{	
    		//100ms = 100 000us
    
    		delay_time+=10000;
    
    		EXTI_ClearITPendingBit(EXTI_Line0);		
    	}
    }
    
    //编写中断服务函数 key2
    void EXTI15_10_IRQHandler()
    {    
    	if(EXTI_GetITStatus(EXTI_Line13) != RESET)//证明
    	{		
    		delay_time-=10000;
    		EXTI_ClearITPendingBit(EXTI_Line13);		
    	}
    }

    4.宏定义

    宏定义是一种预处理指令,可以在编译时将它们替换为常量或表达式,以提高程序的可读性和灵活性。(一般在头文件中写)

    红灯的引脚为GPIO_Pin_10

    绿灯的引脚为GPIO_Pin_11

    蓝灯的引脚为GPIO_Pin_12

    5.配置延迟函数

    c语言的单片机delay延时函数详解-腾讯云开发者社区-腾讯云 (tencent.com)

    通过循环执行空操作或简单指令来消耗时间,从而实现延时。

    在main函数中调用初始化延时函数的函数,以确保延时函数能够正常工作。

    配置延迟函数是为了实现精确的时间控制、确保IO口状态稳定、以及根据应用需求选择合适的延时方法。

    __IO uint32_t TimingDelay =0;
    
    void TimingDelay_Decrement()
    {
    	if(TimingDelay!=0)
    		TimingDelay--;
    }
    void Delay_10us(__IO uint32_t value)
    {
    	TimingDelay = value;
    	
    	while(TimingDelay!=0);
    }

    6.主循环

  • 在主循环中,编写代码使LED按照预设的速度交替闪烁。
  • 这通常涉及到切换LED的状态(开/关),并在每次切换之间加入一个延迟。
  • //红灯
    GPIO_ResetBits(GPIOH,LED_RED);
    GPIO_SetBits(GPIOH,LED_GREEN);
    GPIO_SetBits(GPIOH,LED_BLUE); 						
    Delay_10us(delay_time);		
    //绿灯
    GPIO_ResetBits(GPIOH,LED_BLUE);
    GPIO_SetBits(GPIOH,LED_RED); 
    GPIO_SetBits(GPIOH,LED_GREEN);  
    Delay_10us(delay_time);
    //蓝灯
    GPIO_ResetBits(GPIOH,LED_GREEN); 
    GPIO_SetBits(GPIOH,LED_RED); 
    GPIO_SetBits(GPIOH,LED_BLUE); 
    Delay_10us(delay_time);

    以下是此次的 

    完整代码: 

    #include "stm32F4xx.h"
    #include "stm32f4xx_conf.h"
    #include "stdio.h"
    
    int couter = 0;
    uint8_t key1;
    uint8_t key2;
    
    uint32_t delay_time =10000;
    
    void delay(__IO uint32_t ms)
    {
        for(;ms!=0;ms--);
    }
    
    void LED_init()
    {
        GPIO_InitTypeDef gpio_info;
        //PH0
        //初始化GPIOH时钟
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);
        
        gpio_info.GPIO_Mode = GPIO_Mode_OUT;
        gpio_info.GPIO_OType = GPIO_OType_PP;
        gpio_info.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
        gpio_info.GPIO_PuPd = GPIO_PuPd_UP;
        gpio_info.GPIO_Speed = GPIO_Low_Speed;
        
        GPIO_Init(GPIOH,&gpio_info);
    }
    
    void key1_init()
    {
        GPIO_InitTypeDef gpio_info;
        EXTI_InitTypeDef exti_info;
        NVIC_InitTypeDef  NVIC_InitStructure;
        //PA0
        //初始化GPIOA的时钟    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
        //初始化中断时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
        
        //配置按键
        gpio_info.GPIO_Mode = GPIO_Mode_IN;
        gpio_info.GPIO_OType = GPIO_OType_PP;
        gpio_info.GPIO_Pin = GPIO_Pin_0;
        gpio_info.GPIO_PuPd = GPIO_PuPd_NOPULL;
        gpio_info.GPIO_Speed = GPIO_Low_Speed;
        GPIO_Init(GPIOA,&gpio_info);
        
    
        //配置按键的外部中断
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
        exti_info.EXTI_Line = EXTI_Line0;
        exti_info.EXTI_LineCmd = ENABLE;
        exti_info.EXTI_Mode = EXTI_Mode_Interrupt;
        exti_info.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_Init(&exti_info);
        
        //配置这个外部中断的优先级
        NVIC_InitStructure.NVIC_IRQChannel =  EXTI0_IRQn;   //PA0 对应的是EXTI0_IRQn
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
        NVIC_Init(&NVIC_InitStructure);
    }
    
    void key2_init()
    {
        GPIO_InitTypeDef gpio_info;
        EXTI_InitTypeDef exti_info;
        NVIC_InitTypeDef  NVIC_InitStructure;
        //PC13
        //初始化GPIOA的时钟    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
        //初始化中断时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
        
        //配置按键
        gpio_info.GPIO_Mode = GPIO_Mode_IN;
        gpio_info.GPIO_OType = GPIO_OType_PP;
        gpio_info.GPIO_Pin = GPIO_Pin_13;
        gpio_info.GPIO_PuPd = GPIO_PuPd_NOPULL;
        gpio_info.GPIO_Speed = GPIO_Low_Speed;
        GPIO_Init(GPIOC,&gpio_info);
        
    
        //配置按键的外部中断
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource13);
        exti_info.EXTI_Line = EXTI_Line13;
        exti_info.EXTI_LineCmd = ENABLE;
        exti_info.EXTI_Mode = EXTI_Mode_Interrupt;
        exti_info.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_Init(&exti_info);
    
        //配置这个外部中断的优先级
        NVIC_InitStructure.NVIC_IRQChannel =  EXTI15_10_IRQn;   //PA0 对应的是EXTI0_IRQn
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
        NVIC_Init(&NVIC_InitStructure);
    }
    //编写中断服务函数 key1
    void EXTI0_IRQHandler()
    {    
    	if(EXTI_GetITStatus(EXTI_Line0) != RESET)//证明
    	{	
    		//100ms = 100 000us
    
    		delay_time+=10000;
    
    		EXTI_ClearITPendingBit(EXTI_Line0);		
    	}
    }
    
    //编写中断服务函数 key2
    void EXTI15_10_IRQHandler()
    {    
    	if(EXTI_GetITStatus(EXTI_Line13) != RESET)//证明
    	{		
    		delay_time-=10000;
    		EXTI_ClearITPendingBit(EXTI_Line13);		
    	}
    }
    
    #define LED_RED   GPIO_Pin_10//红
    #define LED_GREEN GPIO_Pin_11//绿
    #define LED_BLUE  GPIO_Pin_12//蓝
    
    __IO uint32_t TimingDelay =0;
    
    //每10us执行一次
    void TimingDelay_Decrement()
    {
    	if(TimingDelay!=0)
    		TimingDelay--;
    }
    void Delay_10us(__IO uint32_t value)
    {
    	TimingDelay = value;
    	
    	while(TimingDelay!=0);
    }
    
    
    int main(void)
    {
        
        LED_init();
        key1_init(); 	
    	key2_init();
     
    	//配置systick定时器每10us
    		SysTick_Config(SystemCoreClock /100000);
        //关闭11、12
        GPIO_SetBits(GPIOH,GPIO_Pin_11|GPIO_Pin_12);
         
        while(1)				
    		{
    				//红灯
    				GPIO_ResetBits(GPIOH,LED_RED);
    				GPIO_SetBits(GPIOH,LED_GREEN);
    				GPIO_SetBits(GPIOH,LED_BLUE); 						
    				Delay_10us(delay_time);		
    				//绿灯
    				GPIO_ResetBits(GPIOH,LED_BLUE);
    				GPIO_SetBits(GPIOH,LED_RED); 
    				GPIO_SetBits(GPIOH,LED_GREEN);  
    				Delay_10us(delay_time);
    				//蓝灯
    				GPIO_ResetBits(GPIOH,LED_GREEN); 
    				GPIO_SetBits(GPIOH,LED_RED); 
    				GPIO_SetBits(GPIOH,LED_BLUE); 
    				Delay_10us(delay_time);
    			}
    }			
    			
    

    7.烧录

    将固件程序烧录到芯片内部,实现芯片的编程和调试,查看效果是否符合要求。

    以上就是此次的 使用stm32实现按键控制LED灯交替闪烁的速度

    作者:Akaashi墨洋

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32实现按键控制LED灯闪烁速度调整的高级教程

    发表回复