『 Jack_a_Lent_Notes』---按键状态机[ATmega128]

来源:互联网 发布:windows me u盘安装 编辑:程序博客网 时间:2024/05/21 07:42

修改于:《安富莱_STM32-V5开发板_用户手册(V2.1) 》第20章 按键 FIFO 教程

按键状态机(单按键或者组合按键)支持:短按,弹起,长按,连发。


/**  ******************************************************************************  * 文       件: main.c  * 版       本: v1  * 编 译 环 境: Atmel Studio 6.0  * 目 标 芯 片: ATmega128  * 晶       振: 4MHz  * 创 建 时 间: 2017-2-2  * 描       述:按键1 短按、连发 :DISbuf++ ;按键1 长按      :DISbuf+=10;按键2 弹起      :DISbuf++;组合按键    连发 :DISbuf--;  ******************************************************************************  */#define  F_CPU 4000000UL#include <avr/io.h>#include<util/delay.h>#include <avr/interrupt.h>#include "LCD1602.h"#include "bsp_key.h"unsigned char DISbuf=0;  void Test_Key(void);/******************************************************************************** * 函  数  名: main * 功      能:  * 形      参:  * 返  回  值:  * 说      明: *******************************************************************************/int main(void){       PORTB=0B00000000;DDRB=0XFF;    PORTC=0B00000000;DDRC=0XFF;PORTF=0B11111111;DDRF=0X00;TCCR0=0b00000111;//1024分频TCNT0=61;//初值=256-晶振/预分频*定时长度(s) 256-4000000/1024*0.05s=256-195=61//OCR0=0x00;TIMSK|=(1<<TOIE0);//溢出中断使能TIFR |=(1<<TOV0);//写 1 来清零溢出标志位sei(); //全局中断使能使能    LCD1602_init();    LCD1602_prints(0,0,"Jack_a_Lent");    while(1)    {LCD1602_Display(7,1,(DISbuf%1000)/100+0x30);//百位LCD1602_Display(8,1,(DISbuf%100)/10+0x30);//十位LCD1602_Display(9,1,(DISbuf%10)+'0');//个位Test_Key();    }}/******************************************************************************** * 函  数  名: T0中断函数  50ms * 功      能:  * 形      参:  * 返  回  值:  * 说      明: *******************************************************************************/ISR(TIMER0_OVF_vect){TCNT0=61;// 256-4000000/1024*0.05s=256-195=61bsp_KeyScan();}/******************************************************************************** * 函  数  名: Test_Key * 功      能: 按键测试 * 形      参: None * 返  回  值: None * 说      明: *******************************************************************************/void Test_Key(void){switch ( bsp_GetKey())/* 读取键值, 无键按下时返回 KEY_NONE = 0 */{/**********************************************************/case 0xA1://按键1按下case 0xD1://按键1连发DISbuf++;break;/**********************************************************/case 0xC1://按键1长按DISbuf+=10;break;/**********************************************************/case 0xB2://按键2弹起DISbuf++;break;/**********************************************************/case 0xD3://(组合键) 连发DISbuf--;break;/**********************************************************/default:break;/**********************************************************/}}
/************************************************************************************************************模块名称 : 按键驱动模块*文件名称 : bsp_key.h*版    本 : V1.0*说    明 : 头文件************************************************************************************************************/#ifndef __BSP_KEY_H#define __BSP_KEY_H#include <avr/io.h>#include <stdint.h>#defineKEY_DOWN0xA0 /* 按键按下 */ #defineKEY_UP  0xB0 /* 按键弹起 */#defineKEY_LONG0xC0 /* 按键长按 */#defineKEY_LIAN0xD0 /* 按键连发 */#define  KEY_LONG_FLAG     20   /* 长按时间 */#define  KEY_SERIES_DELAY  5    /* 连发速度 *//* 按键FIFO用到变量 */#define KEY_FIFO_SIZE10typedef struct{uint8_t Buf[KEY_FIFO_SIZE];/* 键值缓冲区 */uint8_t Read;/* 缓冲区读指针1 */uint8_t Write;/* 缓冲区写指针 */}KEY_FIFO_T;/* 供外部调用的函数声明 */void bsp_InitKey(void);void bsp_KeyScan(void);uint8_t bsp_GetKey(void);#endif/*********************************************************************************************************/
/************************************************************************************************************模块名称 : 独立按键驱动模块*文件名称 : bsp_key.c*版    本 : V1.0*说    明 : 扫描独立按键,具有软件滤波机制,具有按键FIFO。可以检测如下事件:*(1) 按键按下*(2) 按键弹起*(3) 长按键*(4) 长按时自动连发************************************************************************************************************/#include "bsp_key.h"#defineKEY_PORTPINF#define NO_KEY_DOWN0b11111111static KEY_FIFO_T s_tKey;/* 按键FIFO变量,结构体 *//***********************************************************************************************************函 数 名: bsp_InitKeyHard*功能说明: 配置按键对应的GPIO*形    参:  无*返 回 值: 无**********************************************************************************************************/static void bsp_InitKeyHard(void){PORTF=0b11111111;DDRF=0X00;//上拉输入}/***********************************************************************************************************函 数 名: bsp_InitKey*功能说明: 初始化按键. 该函数被 bsp_Init() 调用。*形    参:  无*返 回 值: 无**********************************************************************************************************/void bsp_InitKey(void){/* 对按键FIFO读写指针清零 */s_tKey.Read = 0;s_tKey.Write = 0;bsp_InitKeyHard();/* 初始化按键硬件 */}/***********************************************************************************************************函 数 名: bsp_PutKey*功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。*形    参:  _KeyCode : 按键代码*返 回 值: 无**********************************************************************************************************/void bsp_PutKey(uint8_t _KeyCode){s_tKey.Buf[s_tKey.Write] = _KeyCode;if (++s_tKey.Write  >= KEY_FIFO_SIZE){s_tKey.Write = 0;}}/***********************************************************************************************************函 数 名: bsp_GetKey*功能说明: 从按键FIFO缓冲区读取一个键值。*形    参:  无*返 回 值: 按键代码**********************************************************************************************************/uint8_t bsp_GetKey(void){uint8_t ret;if (s_tKey.Read == s_tKey.Write){return 0;}else{ret = s_tKey.Buf[s_tKey.Read];if (++s_tKey.Read >= KEY_FIFO_SIZE){s_tKey.Read = 0;}return ret;}}/***********************************************************************************************************函 数 名: GetKeyValue*功能说明: 读取按键值,判断按键是否按下*形    参: *返 回 值: 返回值 按键编码 **********************************************************************************************************/static uint8_t GetKeyValue(void){switch(KEY_PORT & NO_KEY_DOWN)//保证只是读取与按键相关的IO口{case 0b11111111: return 0x00;//无按键按下case 0b11111110: return 0x01;//按键1case 0b11111101: return 0x02;//按键2case 0b11111100: return 0x03;//按键1和按键2default  : return 0x00;}  }/***********************************************************************************************************函 数 名: bsp_KeyScan*功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用*形    参:  无*返 回 值: 无**********************************************************************************************************/void bsp_KeyScan(void){static uint8_t  KeyState = 0;  //按键状态static uint8_t  KeyPrev = 0;  //上一次按键状态static uint16_t KeyDelay = 0; //按键连发计时static uint16_t KeyLong = 0; //按键长按计时uint8_t KeyPressValue = 0x00;    //按键值KeyPressValue = GetKeyValue();  //得到按键值switch(KeyState){case 0:                           /* 按键初始状态 */if(KeyPressValue!=0x00)     /* 有键按下     */{KeyState = 1;          /* 转到下一个状态,确认按键 */KeyPrev = KeyPressValue;  /* 保存按键状态   */}  break;        /*消抖  */case 1: /* 按键确认状态  */if(KeyPressValue==KeyPrev)   /* 确认和上次按键相同,否则重新Scan */{KeyState = 2;              /* 转到下一个状态,判断弹起、长按、连发 */bsp_PutKey((uint8_t)(KEY_DOWN|KeyPrev));/* 发送按钮 按下 的消息 */}  else                          /* 本次按键和上次按键不相同,返回到状态0,重新Scan */KeyState = 0;  break;case 2:/* 判断弹起、长按、连发 */if(KeyPressValue == 0x00)   /* 按键释放 */{KeyState = 0;KeyDelay = 0;KeyLong = 0;bsp_PutKey((uint8_t)(KEY_UP|KeyPrev));/* 发送按钮 弹起 的消息 */break;}if(KeyPressValue==KeyPrev)/* 判断长按、连发 */{KeyDelay++;if((KeyLong==1)&&(KeyDelay>KEY_SERIES_DELAY))   /* 连发      */{KeyDelay = 0;bsp_PutKey((uint8_t)(KEY_LIAN|KeyPrev));/* 发送按钮 连发 的消息 */KeyPrev = KeyPressValue;              /* 记住上次的按键 */break;}if(KeyDelay>KEY_LONG_FLAG)        /* 长按           */{KeyLong = 1;KeyDelay = 0;bsp_PutKey((uint8_t)(KEY_LONG|KeyPrev));/* 发送按钮 长按 的消息 */break;}}else /* 本次按键和上次按键不相同,返回到状态0,重新Scan */{KeyState = 0;KeyDelay = 0;KeyLong = 0;}default:break;}}/*********************************************************************************************************/

本人在此发布的博文(包括但不限于汉字、拼音、阿拉伯字母、图片、影像,以及前述之各种任意组合等等)均为互联网整理而来,仅供学习参考,如果侵犯了你的权益请发送电子邮件联系我,我会尽快处理你的问题。

0 0
原创粉丝点击