day02-流水灯控制、蜂鸣器、按键及外部中断


1、led点灯:

int main(void)
{ 
 
    delay_init(168);          //³õʼ»¯ÑÓʱº¯Êý
    LED_Init();                //³õʼ»¯LED¶Ë¿Ú
    
  /**这里的PF.1是板子上的任意管脚,将原来的PF.9不配置,使用杜邦线连接PF.1和PF.9进行驱动led  **/    
    
    while(1)
    {
    GPIO_ResetBits(GPIOF,GPIO_Pin_1);  //GPIOF.1 =0,LED0 
    GPIO_SetBits(GPIOF,GPIO_Pin_10);   //GPIOF.10 =1,LED1
    delay_ms(500);             //延时
    GPIO_SetBits(GPIOF,GPIO_Pin_1);       //LED0
    GPIO_ResetBits(GPIOF,GPIO_Pin_10);    //LED1
    delay_ms(500);                     
    }
}

// led 管脚初始化
void LED_Init(void)
{         
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//
    
  //GPIOF9,F10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_10;//LED0ºÍLED1
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz   
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//­
  GPIO_Init(GPIOF, &GPIO_InitStructure);//GPIO
    
    GPIO_SetBits(GPIOF,GPIO_Pin_1 | GPIO_Pin_10);//GPIOF1,F10
}
View Code

驱动led需要配置外设的时钟,具体选择外设的哪一个管脚,选择管脚为输出模式,输出模式中管脚驱动能力,管脚最大输出速度,管脚配置上下拉输出;

具体的每种模式详细查看库函数可选项;

2、蜂鸣器驱动:

  蜂鸣器有有源和无源蜂鸣器,有源蜂鸣器只需要高低电平开关便可以蜂鸣器出声。无源蜂鸣器需要管脚产生2~5KHz的方波才可以驱动蜂鸣器;

  板子上用的是有源蜂鸣器。而蜂鸣器与led驱动方式类似,这里使用上面实验中的PF1管脚驱动蜂鸣器,使用杜邦线连接对应的管脚就可以;

  由于蜂鸣器驱动需要至少30mA的电流,而stm32F4单个管脚最大的输出电流有25mA,但是整个芯片最大输出电流也就140mA,因此这里使用三极管驱动蜂鸣器;

3、获取按键输入:

  

   硬件连接如图所示:注意配置按键管脚上下拉,PE2.3,4在按键按下检测低电平,因此需要配置上拉电阻,确保常态下为高电平;WK_UP检测高电平,因此需要配置下拉电阻,确保常态下为低电平,检测高电平;

可以在上面试验基础上修改,KeyInit如下:

/*
key0--->PE4
key1--->PE3
key2--->PE2
WK_UP-->PA0
*/
void  KeyInit(void)   
{
    // ÅäÖÃPA0,   PE2.3.4ΪÊäÈëģʽ
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    // ³õʼ»¯ÍâÉèʱÖÓ
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOA, ENABLE);//ʹÄÜGPIOFʱÖÓ
    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//LED0ºÍLED1¶ÔÓ¦IO¿Ú
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//ÆÕͨÊäÈëģʽ
//  GPIO_InitStructureA.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz   
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;// ÓÉÓڸð´¼üÐèÒª¼ì²â¸ßµçƽ£¬Òò´Ë¹Ü½Å³õʼµçƽӦ¸ÃΪµÍµçƽ
  GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIO
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 |GPIO_Pin_3| GPIO_Pin_4;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;// ÓÉÓڸð´¼üÐèÒª¼ì²âµÍµçƽ£¬Òò´Ë¹Ü½Å³õʼµçƽӦ¸ÃΪ¸ßµçƽ
    GPIO_Init(GPIOE, &GPIO_InitStructure);//³õʼ»¯GPIO    
}
View Code

  检测按键按下:

/*
按键动作捕获
key0.1.2 -->0
WK_UP--->1
*/
u8 KeyScan()
{
    if(KEY0 == 0|| KEY1==0|| KEY2==0)
    {
        delay_ms(30);
        if(KEY0==0) return 1;
        else if(KEY1 == 0) return 2;
        else if(KEY2 == 0) return 3;
    }
    delay_ms(50);
    return 0;
}
View Code
// 读取按键按下值
#define KEY0  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
#define KEY1  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)
#define KEY2  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)
#define WK_UP GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)

#define LED0     PFout(9)   
#define LED1     PFout(10)
View Code

主函数中循环查询是否有按键按下:后面可以使用按键中断方式控制LED

int main(void)
{ 
  u8 key;
    delay_init(168);          //  延时函数初始化
    LED_Init();                // led初始化
    KeyInit();    // 按键配置初始化
    
    
    while(1)
    {
        key = KeyScan();
        if(key ){            
            switch(key){
                case 1:
                    LED0 = !LED0;
                    break;
                case 2:
                    LED1 = !LED1;
                    break;
                case 3:
                    LED0 = !LED0;
                    LED1 = !LED1;
                    break;
            }        
            }        
        else{
                delay_ms(100);            
        }
    }
View Code

扩展:

  可以将其他引脚配置与上面引脚配置类似,使用杜邦线连接控制相同的动作;这里配置PE1,可以实现PE2对应的管脚控制动作;

4、使用中断方式处理按键动作

  外部中断线有如下,这里先主要使用EXTI线0-15;

  

 

   其中中断线0-15映射关系:

5、外部中断线的配置步骤:

  1、使能中断源(GPIO)的时钟,外设中断映射器(RCC_APB2Periph_SYSCFG)的时钟;RCC_AHB1PeriphClockCmd()、RCC_APB2PeriphClockCmd()

   2、初始化外设GPIO为输入模式,以及对应的上拉或者下拉电阻;GPIO_Init()

  3、初始化外部中断线控制器,将GPIO与中断线联系起来;SYSCFG_EXTILineConfig()

  4、对外部中断线初始化,配置触发方式;EXTI_Init()

  5、配置外部中断线的中断处理函数;NVIC_Init()

  6、编写中断处理函数,在中断函数中,处理完任务后清除中断标志位;EXTI_ClearITPendingBit(EXTI_Line2);

6、使用按键控制器LED的状态

  1、对按键、LED管脚初始化

 1 // 按键管脚定义
 2 #define KEY0  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
 3 #define KEY1  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)
 4 #define KEY2  GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_1)
 5 #define WK_UP GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
 6 
 7 #define LED0     PFout(9)
 8 #define LED1     PFout(10)
 9             
10 //LED 初始化
11 void LED_Init(void)
12 {         
13   GPIO_InitTypeDef  GPIO_InitStructure;
14 
15   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//
16     
17   //GPIOF9,F10
18   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0  LED1
19   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//
20   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
21   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz   
22   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//­
23   GPIO_Init(GPIOF, &GPIO_InitStructure);// GPIO
24     
25     GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF1
26 }
27 
28 
29 /*
30 key0--->PE4
31 key1--->PE3
32 key2--->PE2
33 WK_UP-->PA0
34 */
35 void  KeyInit(void)   
36 {
37     // PA0,   PE2.3.4
38     GPIO_InitTypeDef  GPIO_InitStructure;
39     
40     // 
41     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOA, ENABLE);//
42     
43   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//LED0
44   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 
45 //  GPIO_InitStructureA.GPIO_OType = GPIO_OType_PP;// 
46   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz   
47   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;// 
48   GPIO_Init(GPIOA, &GPIO_InitStructure);// GPIO
49     
50     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3| GPIO_Pin_4;
51     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
52     GPIO_Init(GPIOE, &GPIO_InitStructure);// GPIO    
53 }
View Code

  2、外部中断线初始化

// ÍⲿÖжÏÏß³õʼ»¯
// KEY0,1,2¼ì²âϽµÑØ
void Exti_Init(void)
{
    EXTI_InitTypeDef EXTI_InitStruct; 
    NVIC_InitTypeDef NVIC_InitStruct;
    
    KeyInit();   // 外设GPIO时钟、输入模式初始化
    
    // 对外设中短线控制器时钟初始化
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    
    // 将中断线与对应的GPIO联系起来
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
    
    //  外部中断线初始化  设置触发方式,中断处理函数关联
    EXTI_InitStruct.EXTI_Line = EXTI_Line2|EXTI_Line3|EXTI_Line4;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStruct);
    
    // 
    NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
    NVIC_Init(&NVIC_InitStruct);
    
    NVIC_InitStruct.NVIC_IRQChannel = EXTI3_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStruct);
    
    NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStruct);

}
View Code

  3、中断处理函数

 1 // KEY2--->PE2--->EXTI2
 2 void EXTI2_IRQHandler(void)
 3 {
 4     delay_ms(10);
 5     LED1 = !LED1;
 6     LED0 = !LED0;        
 7     EXTI_ClearITPendingBit(EXTI_Line2);
 8 }
 9 // KEY1-->PE3--->EXTI3
10 void EXTI3_IRQHandler(void)
11 {
12     delay_ms(10);
13 
14     LED1 = !LED1;        
15     
16     EXTI_ClearITPendingBit(EXTI_Line3);
17 }
18 
19 // KEY0--->PE4--->EXTI4
20 void EXTI4_IRQHandler(void)
21 {
22     delay_ms(10);
23     
24     LED0 = !LED0;
25     EXTI_ClearITPendingBit(EXTI_Line4);
26 
27 }
View Code

  4、主函数:相关初始化,主函数可以大多做其他任务

 1 int main(void)
 2 { 
 3   u8 key;
 4     delay_init(168);         
 5     LED_Init();                
 6     //KeyInit();
 7     Exti_Init();
 8     // 使用中断方式按键动作
 9     LED0 = 0;  // 
10     while(1)
11     {
12         delay_ms(1000);   // 处理其他任务
13     }
14     
15     
16     /*  // 使用查询方式处理按键动作
17     while(1)
18     {
19         key = KeyScan();
20         if(key ){            
21             switch(key){
22                 case 1:
23                     LED0 = !LED0;
24                     break;
25                 case 2:
26                     LED1 = !LED1;
27                     break;
28                 case 3:
29                     LED0 = !LED0;
30                     LED1 = !LED1;
31                     break;
32             }        
33             }        
34         else{
35                 delay_ms(100);            
36         }
37     }
38     
39     */
40     
41 }
View Code

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM