- /*直接复制以下代码,实现*/
- #include "stm32f10x.h"
- #include "bitband_cm3.h"
- #include "systick.h"
- #define N_key 0 //无键
- #define S_key 1 //单键
- #define D_key 2 //双键
- #define L_key 3 //长键
- #define KEY_AN (GPIOA->IDR & 1<<0)
- #define BEEF PCout(3)
- /**********************************************************************
- *函数名:delay_us
- *功 能:延迟1us
- *参 数:us最大2^24/9=1864135us
- *返 回:无
- *备 注:无
- **********************************************************************/
- void delay_us(u16 us)
- {
- SysTick->LOAD = us * 9; //装载计数值
- SysTick->VAL = 0; //清空当前值
- SysTick->CTRL |= 1; //使能计数器
- while(!(SysTick->CTRL & (1 << 16)));//等待计数结束
- SysTick->CTRL &=~ 1;//关闭计数
- }
- //LED初始化
- void LED_Init(void)
- {
- #if 0
- RCC->APB2ENR |= 3<<3;//开启PB/PC口时钟
- GPIOB->CRL &=~(0XF<<4*1);//清PB1
- GPIOB->CRL |=(0X3<<4*1);//通用输出 50M
- GPIOC->CRL &=~(0XF<<4*5);//清PC5
- GPIOC->CRL |=(0X3<<4*5);//通用输出 50M
- GPIOB->ODR |=(1<<1);//默认给高电平,关灯,
- GPIOC->ODR |=(5<<1);
- // GPIOB->ODR &=~(1<<1);//点灯
- // GPIOC->ODR &=~(5<<1);
- #else
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB,ENABLE);//开启PB/PC口时钟.
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
- GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽
- GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//50M
- GPIO_Init(GPIOB, &GPIO_InitStruct);//PB1
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
- GPIO_Init(GPIOC, &GPIO_InitStruct);//PC5
- GPIO_SetBits(GPIOB, GPIO_Pin_1);//默认给高电平,关灯,不能少了这步,因为输出数据寄存器默认值给低电平
- GPIO_SetBits(GPIOC, GPIO_Pin_5);
- // GPIO_ResetBits(GPIOB, GPIO_Pin_1);//开灯
- // GPIO_ResetBits(GPIOC, GPIO_Pin_5);
- // PBout(1)=0;
- // PCout(5)=0;
- #endif
- }
- //按键初始化
- void KEY_Iint(void)
- {
- RCC->APB2ENR |= 1<<2;//开启PA口时钟
- }
- //蜂鸣器初始化
- void BEEF_Iint(void)
- {
- RCC->APB2ENR |= 1<<4;//开启PC口时钟
- GPIOC->CRL &=~(0XF<<4*3);//清PC3
- GPIOC->CRL |=(0X3<<4*3);//通用输出 50M
- }
- /*
- 驱动层
- 1.完成按键的消抖,松手检测
- 2.把过程细分为一个个状态
- 3.实现长按与单击功能
- 按键初始态
- 按键确认态
- 按键计时态
- 等待按键释放态
- */
- unsigned char key_driver()
- {
- static u8 key_state = 0, key_time = 0;
- u8 key_return = N_key;
- switch (key_state)
- {
- case 0: // 按键初始态
- if (!KEY_AN) key_state = 1; // 键被按下,状态转换到按键消抖和确认状态
- break;
- case 1: // 按键消抖与确认态
- if (!KEY_AN)
- {
- key_time = 0;
- key_state = 2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
- }
- else
- key_state = 0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
- break;
- case 2: // 按下键时间的计时状态
- if(KEY_AN)
- {
- key_return = S_key; // 此时按键释放,说明是产生一次短操作,回送S_key
- key_state = 0; // 转换到按键初始态
- }
- else if (++key_time >= 100) // 继续按下,计时加10ms(10ms为本函数循环执行间隔)
- {
- key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件
- key_state = 3; // 转换到等待按键释放状态
- }
- break;
- case 3: // 等待按键释放状态,此状态只返回无按键事件
- if (KEY_AN) key_state = 0; // 按键已释放,转换到按键初始态
- break;
- }
- return key_return;
- }
- /*
- 业务逻辑层
- 1.单击、双击、长按的分配
- */
- unsigned char key_read()
- {
- static u8 key_m = 0, key_time_1 = 0;
- u8 key_return = N_key,key_temp;
- key_temp = key_driver();
- switch(key_m)
- {
- case 0:
- if (key_temp == S_key )
- {
- key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击
- key_m = 1;
- }
- else
- key_return = key_temp; // 对于无键、长键,返回原事件
- break;
- case 1:
- if (key_temp == S_key) // 又一次单击(间隔肯定<500ms)
- {
- key_return = D_key; // 返回双击键事件,回初始状态
- key_m = 0;
- }
- else
- { // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键
- if(++key_time_1 >= 30)
- {
- key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件
- key_m = 0; // 返回初始状态
- }
- }
- break;
- }
- return key_return;
- }
- /*
- 单击:300ms~1000ms之间
- 双击:300ms内
- 长按:超过1s
- 单击:控制LED1
- 双击:控制LED2
- 长按:控制蜂鸣器
- */
- int main(void)
- {
- LED_Init();
- KEY_Iint();
- BEEF_Iint();
- while(1)
- {
- switch(key_read())
- {
- case N_key:
- delay_ms(10);
- break;
- case S_key:
- PBout(1)=!PBout(1);
- break;
- case D_key:
- PCout(5)=!PCout(5);
- break;
- case L_key:
- BEEF = !BEEF;
- break;
- }
- }
- return 0;
- }
复制代码
【必读】版权免责声明
1、本主题所有言论和内容纯属会员个人意见,与本论坛立场无关。2、本站对所发内容真实性、客观性、可用性不做任何保证也不负任何责任,网友之间仅出于学习目的进行交流。3、对提供的数字内容不拥有任何权利,其版权归原著者拥有。请勿将该数字内容进行商业交易、转载等行为,该内容只为学习所提供,使用后发生的一切问题与本站无关。 4、本网站不保证本站提供的下载资源的准确性、安全性和完整性;同时本网站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。 5、本网站所有软件和资料均为网友推荐收集整理而来,仅供学习用途使用,请务必下载后两小时内删除,禁止商用。6、如有侵犯你版权的,请及时联系我们(电子邮箱1370723259@qq.com)指出,本站将立即改正。
|