1:按键不带锁存
不带锁存的意思就是 比如你按下按键灯亮,但是你一旦松手了灯就熄灭了,所以你想这个灯一直亮,那么你就一直按着按键不松手。
1.1例程
key.c
- /*========================key.c=========================*/
- #include "stm32f10x.h"
- #include "key.h"
- /*按键初始化函数*/
- void KEY_Init(void)
- {
- //1.打开控制GPIOA的时钟(APB2)
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
-
- //2.配置结构体
- GPIO_InitTypeDef key_init;
- key_init.GPIO_Pin = GPIO_Pin_5; //GPIOC A5引脚
- key_init.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- //led_init.GPIO_Speed = GPIO_Speed_10MHz; //10MHz
-
- //3.对成员进行初始化
- GPIO_Init(GPIOA, &key_init);
- }
复制代码
led.c
- #include "stm32f10x.h"
- #include "led.h"
- void LED_Init(void)
- {
- //1.打开控制GPIOC的时钟(APB2)
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
-
- //2.配置结构体
- GPIO_InitTypeDef led_init;
- led_init.GPIO_Pin = GPIO_Pin_13; //GPIOC13引脚
- led_init.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- led_init.GPIO_Speed = GPIO_Speed_10MHz; //10MHz
-
- //3.对成员进行初始化
- GPIO_Init(GPIOC, &led_init);
- }
复制代码
main.c
- #include "stm32f10x.h"
- #include "led.h"
- #include "key.h"
- #include "delay.h"
- int main()
- {
- LED_Init(); //LED初始化
- KEY_Init(); //按键初始化
- GPIO_SetBits(GPIOC,LED); //LED设置高电平
- GPIO_SetBits(GPIOA,KEY); //按键设置高电平
-
- while(1)
- {
- #if 0
- /*示例1:无锁存*/
- if(GPIO_ReadInputDataBit(GPIOA, KEY) == 0) //读取按键是否被按下
- {
- GPIO_ResetBits(GPIOC, LED); //LED点亮
- }
- else
- {
- GPIO_SetBits(GPIOC,LED); //LED熄灭
- }
- #endif
-
- /*示例2:无锁存*/
- GPIO_WriteBit(GPIOC, LED, (BitAction)(GPIO_ReadInputDataBit(GPIOA, KEY)));
- }
- }
复制代码
2:按键带锁存
锁存的意思就是 比如你按下按键灯亮,但是你一旦松手了灯还是亮的,跟不带锁存相反。
2.1例程
key.c 和 led.c 和上面的不带锁存是一样的代码
- #include "stm32f10x.h"
- #include "led.h"
- #include "key.h"
- #include "delay.h"
- int main()
- {
- LED_Init(); //LED初始化
- KEY_Init(); //按键初始化
- GPIO_SetBits(GPIOC,LED); //LED设置高电平
- GPIO_SetBits(GPIOA,KEY); //按键设置高电平
-
- while(1)
- {
- /*示例3:有锁存 每按一次 灯取反*/
- if(GPIO_ReadInputDataBit(GPIOA, KEY) == 0) //读取按键是否被按下
- {
- delay_ms(20); //消抖再次判断是否按下
- if(GPIO_ReadInputDataBit(GPIOA, KEY) == 0) //读取按键还是被按下
- {
- GPIO_WriteBit(GPIOC, LED, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOC, LED)));
- }
- while(!GPIO_ReadInputDataBit(GPIOA, KEY)); //等待按键松开
- }
-
- }
- }
复制代码
3:按键用外部中断来做
正常如何程序比较多的话,我们有时候按键是需要及时处理的,如果通过循环检测其实不太理想的,所以我们可以把按键设置为中断来做。这样就可以更有效率,能及时处理。
步骤:
1.配置GPIO(配置结构体的相关东西)
- //1.打开控制GPIOA的时钟(APB2)
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //我们设置复用 用作外部中断
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5); //设置A5引脚为 外部中断引脚
- //2.配置结构体
- GPIO_InitTypeDef key_init;
- key_init.GPIO_Pin = GPIO_Pin_5; //GPIO A5引脚
- key_init.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- //led_init.GPIO_Speed = GPIO_Speed_10MHz; //10MHz
- //3.对成员进行初始化
- GPIO_Init(GPIOA, &key_init);
复制代码
2.设置EXTI (触发方式:上升沿、下降沿、上下都触发)。
EXTI_Line: 中断线(一共20条)
EXTI_Mode: EXTI 中断的模式/产生的事件
EXTI_Trigger: EXTI()触发方式 上升沿 下降沿 上下都触发)
EXTI_LineCmd: 控制是否使能EXTI线,使能EXTI线或禁用
- //4.配置EXTI外部中断结构体
- EXTI_InitTypeDef exti_init;
- exti_init.EXTI_Line = EXTI_Line5; //A5引脚 所以是line5
- exti_init.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- exti_init.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
- exti_init.EXTI_LineCmd = ENABLE; //打开外部中断开关
- //对成员进行初始化
- EXTI_Init(&exti_init);
复制代码
3.设置NVIC(中断优先级)
- //5.配置NVIC优先级结构体
- NVIC_InitTypeDef nvic_init;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //配置第四组
- nvic_init.NVIC_IRQChannel = EXTI9_5_IRQn; //A5引脚嘛 选择通道5
- nvic_init.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级 0级
- nvic_init.NVIC_IRQChannelSubPriority = 0; //设置子优先级 0级
- nvic_init.NVIC_IRQChannelCmd = ENABLE; //打开NVIC优先级开关
- //对成员进行初始化
- NVIC_Init(&nvic_init);
复制代码
4.编写中断服务函数
当按键从高电平变成低电平,也就是下降沿的时候,会触发中断,然后会进入中断服务函数。然后我们在服务函数里面点灯即可。- void EXTI9_5_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line5) != RESET) //如果发生外部中断
- {
- GPIO_ResetBits(GPIOC,GPIO_Pin_13); //开灯 LED设置低电平
- delay_ms(1000); //亮灯1秒
- GPIO_SetBits(GPIOC,GPIO_Pin_13); //关灯 LED设置高电平
- }
-
- EXTI_ClearFlag(EXTI_Line5); //清除标志位
- }
复制代码
代码:
key.c
main.c
- #include "stm32f10x.h"
- #include "led.h"
- #include "key.h"
- #include "delay.h"
- #include "exti.h"
- /*主函数入口*/
- int main()
- {
- LED_Init(); //LED初始化
- KEY_Init(); //按键初始化
- exti_Init(); //外部中断初始化
- GPIO_SetBits(GPIOC,GPIO_Pin_13); //LED设置高电平
- GPIO_SetBits(GPIOA,GPIO_Pin_5); //按键设置高电平
-
- while(1)
- {
- }
- }
- /*外部中断服务函数*/
- void EXTI9_5_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line5) != RESET) //如果发生外部中断
- {
- GPIO_ResetBits(GPIOC,GPIO_Pin_13); //开灯 LED设置低电平
- delay_ms(1000); //亮灯1秒
- GPIO_SetBits(GPIOC,GPIO_Pin_13); //关灯 LED设置高电平
- }
-
- EXTI_ClearFlag(EXTI_Line5); //清除标志位
- }
复制代码- #include "stm32f10x.h"
- #include "key.h"
- /*按键初始化函数*/
- void KEY_Init(void)
- {
- //1.打开控制GPIOA的时钟(APB2)
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用 用作外部中断
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5); //设置A5引脚为 外部中断引脚
-
- //2.配置结构体
- GPIO_InitTypeDef key_init;
- key_init.GPIO_Pin = GPIO_Pin_5; //GPIOC13引脚
- key_init.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- //led_init.GPIO_Speed = GPIO_Speed_10MHz; //10MHz
-
- //3.对成员进行初始化
- GPIO_Init(GPIOA, &key_init);
- }
复制代码
exti.c
- #include "stm32f10x.h"
- #include "exti.h"
- void exti_Init()
- {
- //4.配置EXTI外部中断结构体
- EXTI_InitTypeDef exti_init;
-
- exti_init.EXTI_Line = EXTI_Line5; //A5引脚
- exti_init.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- exti_init.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
- exti_init.EXTI_LineCmd = ENABLE; //打开外部中断开关
-
- //对成员进行初始化
- EXTI_Init(&exti_init);
-
-
- //5.配置NVIC优先级结构体
- NVIC_InitTypeDef nvic_init;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //配置第四组
-
-
- nvic_init.NVIC_IRQChannel = EXTI9_5_IRQn; //通道5
- nvic_init.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级 0级
- nvic_init.NVIC_IRQChannelSubPriority = 0; //设置子优先级 0级
- nvic_init.NVIC_IRQChannelCmd = ENABLE; //打开NVIC优先级开关
-
- //对成员进行初始化
- NVIC_Init(&nvic_init);
- }
复制代码
delay.c
- #include "stm32f10x.h"
- #include "delay.h"
- void delay_ms(uint16_t time)
- {
- uint16_t i = 0;
- while(time--)
- {
- i = 10000;
- while(i--);
- }
- }
复制代码
————————————————
转载:皮卡丘吉尔
|