STM32 按键扫描的方式实现,用队列传递参数

◇◆丶佛笑我妖孽 提交于 2020-03-25 13:29:21

3 月,跳不动了?>>>

开发环境是keil4.70a

实验板为神舟三号 STM32F103ZET6

软件上使用到了固件库了ucosii

纯粹为了学习,分享一下学习心得

首先上队列初始化的代码

OS_EVENT* KEY_Q;		//按键记录的OS队列
void *key_list[80];		//队列定义时要求定义指针数组
/* 推荐在main中或者main.c类似的文件和位置创建这两个变量 */

KEY_Q = OSQCreate(key_list,80);
/* 推荐在OSInit之后立马创建这个队列 */

//对了别忘了配置
//这些OS的功能使能
#define OS_Q_EN                   1    /* Enable (1) or Disable (0) code generation for QUEUES         */
#define OS_Q_ACCEPT_EN            1    /*     Include code for OSQAccept()                             */
#define OS_Q_DEL_EN               1    /*     Include code for OSQDel()                                */
#define OS_Q_FLUSH_EN             1    /*     Include code for OSQFlush()                              */
#define OS_Q_PEND_ABORT_EN        1    /*     Include code for OSQPendAbort()                          */
#define OS_Q_POST_EN              1    /*     Include code for OSQPost()                               */
#define OS_Q_POST_FRONT_EN        1    /*     Include code for OSQPostFront()                          */
#define OS_Q_POST_OPT_EN          1    /*     Include code for OSQPostOpt()                            */
#define OS_Q_QUERY_EN             1    /*     Include code for OSQQuery()                              */

//以上的文件默认在os_cfg.h中

接下来贴上的按键扫描的任务

void key_task(void *p_arg) //该任务只实现按键的跟踪功能	//高四位是上一个状态,低四位是当前状态
{
	u32 bsp_key_scaned;  	//每四位记录一个状态,一共可以记录8个状态
							//在后续优化中可以考虑改成结构体 分出8位或者16位记录按键时长
	u8 key_rem1 = 0x00;		//第一次缓冲	//用于消抖
	u8 key_rem2 = 0x00;		//第二次缓冲	//用于判断按键状态是否改变
	u8 key_t = 0x00;		//第一次记录   

	bsp_key_scaned = 0x00000000;	//清空按键状态 32位的数字
	while(1) 
	{ 
			OSTimeDlyHMSM(0,0,0,10);	//短暂的消抖
		if(!(GPIO_ReadInputDataBit(GPIO_KEY1_PORT, GPIO_KEY1))){
			key_t = key_t | 0x01;}
		if(!(GPIO_ReadInputDataBit(GPIO_KEY2_PORT, GPIO_KEY2))){
			key_t = key_t | 0x02;} 
//		if(!(GPIO_ReadInputDataBit(GPIO_KEY3_PORT, GPIO_KEY3))){
//			key_t = key_t | 0x04;} 		//这个按键在神舟三号开发板上不怎么好用
		if(!(GPIO_ReadInputDataBit(GPIO_KEY4_PORT, GPIO_KEY4))){
			key_t = key_t | 0x08;}		//这里看起来挺繁琐的,所以 挤挤←_←
		//以上实现扫描后一个简单的编码
		
		if((key_rem1 == key_t)&&(key_rem1 != key_rem2))	//没有抖动,并且按键状态发生了改变,则Qpost
		{
			key_rem2 = key_rem1;	//记录即将post的变量,用于下一次判断
			bsp_key_scaned = ((bsp_key_scaned<<4)&0xfffffff0)|(key_t&0x0f);	//传递参数	//注意是位操作
			OSQPost(KEY_Q,(void*)bsp_key_scaned);	//发送队列内容
		}

		key_rem1 = key_t;   	//记录一个状态
		key_t = 0x00;			//下一次记录,判断是否抖动
	} 
}
最后一个是队列中内容的提取 也做成了一个任务
void key_solve_task(void *p_arg)
{
	u32 key_value;	//获取实际数据
	void* pKEY_Q;	//获取队列中的指针
	while(1) 
	{
			OSTimeDlyHMSM(0,0,1,0);	//延时 1m处理一次
		pKEY_Q = OSQPend(KEY_Q,0,&err);	//不过期,一直请求Q
		if(pKEY_Q == (void*)0)		//如果返回数据为空
		{	
			switch(err)		//目前没有加入错误处理
			{	
				case OS_ERR_NONE: break;
				default:continue;//break;	//如果不是OS_NO_ERR则继续等待1秒
			}
		} else 
		{
			key_value = (int)pKEY_Q;
			key_value = key_value &0x000000ff;
			
			if(GPIO_ReadOutputDataBit(GPIOF,GPIO_Pin_7) == 1){ //翻转LED2	//表示得到数据
				GPIO_ResetBits(GPIOF,GPIO_Pin_7);
			} else {
				GPIO_SetBits(GPIOF,GPIO_Pin_7);
			}
			
			if(key_value == 0x00000013)	 //说明是先按下第一个键,再按下第二个键
			{	
				if(GPIO_ReadOutputDataBit(GPIOF,GPIO_Pin_9) == 1) { //翻转LED4						
					GPIO_ResetBits(GPIOF,GPIO_Pin_9);	
				} else {
					GPIO_SetBits(GPIOF,GPIO_Pin_9);
				}
			} /*else if(key_value == 0x00000057)	//按键有问题,第三个按键不加入扫描
			{
				if(GPIO_ReadOutputDataBit(GPIOF,GPIO_Pin_9)==1) {//LED按键有问题ADC1 第三个按键默认经常是按下的状态
					GPIO_ResetBits(GPIOF,GPIO_Pin_9);
				} else {
					GPIO_SetBits(GPIOF,GPIO_Pin_9);
				}				
			}		*/		
		}
	}
}
我应用的时候 优先级按键扫描任务给得比按键处理要高,亲测连续按下很多次之后LED2会每过1秒闪烁一下,如果满足要求LED4也会闪烁

原文地址http://my.oschina.net/mummy108/blog/126476

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!