按键外部中断-延时消抖问题及CH452/1驱动

一、CH452DS1用户手册.7z
二、按键小技巧
1、在中断里延时是不好的操作
2、一般情况下按键需要延时10ms进行消抖,若此按键是外部中断,可以使用以下方法避免在中断中延时
首先定义一个全局变量,作为中断标志位。在中断处理函数中改写此标志位;在按键扫描函数中检测标志位,若被置1则延时10ms,接着检测按键所对应IO口的状态,以判断按键是否被按下,并达到消抖的效果。
代码:
//extern uint8_t exti_flag;
uint8_t exti_flag=0; //变量中断标志位

void EXTI0_1_IRQHandler(void) //外部中断处理函数
{ //注意以下这两个标志位不是同一个标志位
  LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0); //清系统中断状态标志
  exti_flag=1; //变量标志位置1
}

void Key_Inter(void) //按键扫描函数
{
  if(exti_flag==1) //判断变量标志位
  {
    LL_mDelay(10); //消抖
    exti_flag=0; //清变量标志位
	if(LL_GPIO_IsInputPinSet(KA0_GPIO_Port,KA0_Pin)) //按键IO口状态
	{	
	  //while(LL_GPIO_IsInputPinSet(KA0_GPIO_Port,KA0_Pin)) {}//松手检测	
	  ...
	}
  }		
}

int main(void)
{
  while (1)
  {
    Key_Inter(); //按键函数扫描
  }
}
三、ch452驱动
.c
#include	"ch452.h"	

/* ***************************
 CH452的4线接口子程序
****************************
 CH45X的4线接口,不含按键中断为3个I/O引脚,含按键中断为4个I/O,类似SPI时序,
 四线制方式也可以参照CH451,其中对CH451的选择4线串行接口初始化子函数可以省去
*************************************************************************** */
 
//输出操作命令子程序
//定义一无符号整型变量存储12字节的命令字。
void CH452_Write(unsigned short cmd)
{
	unsigned char i;
	//禁止键盘中断,防止传输过程中被CH452中断而进入中断服务程序中再次传输
	DISABLE_KEY_INTERRUPT;  
	CH452_LOAD_CLR;    //命令开始,LOAD=0
	CH452_LOAD_D_OUT;  // 设置LOAD为输出方向
	CH452_DOUT_D_IN;   // 设置DOUT为输入方向
	CH452_DIN_D_OUT;   // 设置DIN为输出方向
	CH452_DCLK_D_OUT;  // 设置DCLK为输出方向
	for(i=0;i!=12;i++) //送入12位数据,低位在前
	{
		if (cmd&1) {CH452_DIN_SET;}
		else {CH452_DIN_CLR;}  //输出位数据
//		CH452_DIN=cmd&1;
    	CH452_DCLK_CLR;
    	cmd>>=1;
    	CH452_DCLK_SET;  //上升沿有效
	}
    CH452_LOAD_SET;  //加载数据,LOAD上升沿 
    ENABLE_KEY_INTERRUPT;
}

//输入按键代码子程序,从CH452读取
unsigned char CH452_Read( void )
{
   	unsigned char i;
  	unsigned char cmd,keycode;	//定义命令字,和数据存储器
  	//禁止键盘中断,防止传输过程中被CH452中断而进入中断服务程序中再次传输	
  	DISABLE_KEY_INTERRUPT;	    
  	cmd=0x07;	//读按键的命令字
  	CH452_LOAD_CLR;
  	for(i=0;i!=4;i++)  
	{//只需要发出高4位,多发也可以,但应该确保最后留下的4位是该命令码
		if (cmd&1) {CH452_DIN_SET;}
		else {CH452_DIN_CLR;}  //输出位数据
//		CH452_DIN=cmd&1;	//送入最低位
    	CH452_DCLK_CLR;			 
    	cmd>>=1;	        //往右移一位
    	CH452_DCLK_SET;	    //产生时钟上升沿锁通知CH451输入位数据
 	}
  	CH452_LOAD_SET;			//产生加载上升沿通知CH451处理命令数据
  	keycode=0;			    //清除keycode
  	for(i=0;i!=7;i++)
	{
		keycode<<=1;			      //数据移入keycode,高位在前,低位在后
		if (CH452_DOUT) keycode++;    //从高到低读入451的数据
//    	keycode|=CH452_DOUT;
    	CH452_DCLK_CLR;			    //产生时钟下升沿通知CH451输出下一位
    	CH452_DCLK_SET;
 	}
  	CLEAR_KEY_INTER_FLAG;	   //清中断标志
  	ENABLE_KEY_INTERRUPT;
  	return(keycode);		   //反回键值
}

void CH452_Init() //初始化
{	  
    CH452_Write(0x0201);    //复位
	CH452_Write(0x0403);    //开启显示、键盘
	CH452_Write(0x0580);    //译码
	//CH452_Write(0x0500);    //不译码
}

.h
#ifndef _CH452_H_
#define _CH452_H_
/* 常量定义 */

/* CH451和CH452的常用命令码 */
#define CH452_NOP		0x0000					// 空操作
#define CH452_RESET     0x0201					// 复位
#define CH452_LEVEL		0x0100					// 加载光柱值,需另加7位数据
#define CH452_CLR_BIT	0x0180					// 段位清0,需另加6位数据
#define CH452_SET_BIT	0x01C0					// 段位置1,需另加6位数据
#define CH452_SLEEP		0x0202					// 进入睡眠状态
#define CH452_LEFTMOV   0x0300		            // 设置移动方式-左移
#define CH452_LEFTCYC   0x0301		            // 设置移动方式-左循环
#define CH452_RIGHTMOV  0x0302		            // 设置移动方式-右移
#define CH452_RIGHTCYC  0x0303		            // 设置移动方式-右循环	
#define CH452_SELF_BCD	0x0380					// 自定义BCD码,需另加7位数据
#define CH452_SYSOFF    0x0400					// 关闭显示、关闭键盘
#define CH452_SYSON1    0x0401					// 开启显示
#define CH452_SYSON2    0x0403					// 开启显示、键盘
#define CH452_SYSON2W   0x0423					// 开启显示、键盘, 真正2线接口
#define CH452_NO_BCD    0x0500					// 设置默认显示方式,可另加3位扫描极限
#define CH452_BCD       0x0580					// 设置BCD译码方式,可另加3位扫描极限
#define CH452_TWINKLE   0x0600		            // 设置闪烁控制,需另加8位数据
#define CH452_GET_KEY	0x0700					// 获取按键,返回按键代码
#define CH452_DIG0      0x0800					// 数码管位0显示,需另加8位数据
#define CH452_DIG1      0x0900		            // 数码管位1显示,需另加8位数据
#define CH452_DIG2      0x0a00		            // 数码管位2显示,需另加8位数据
#define CH452_DIG3      0x0b00		            // 数码管位3显示,需另加8位数据
#define CH452_DIG4      0x0c00		            // 数码管位4显示,需另加8位数据
#define CH452_DIG5      0x0d00					// 数码管位5显示,需另加8位数据
#define CH452_DIG6      0x0e00					// 数码管位6显示,需另加8位数据
#define CH452_DIG7      0x0f00		            // 数码管位7显示,需另加8位数据

#define  USE_KEY  1    //如果使用键盘中断请定义

// BCD译码方式下的特殊字符
#define		CH452_BCD_SPACE		0x10
#define		CH452_BCD_PLUS		0x11
#define		CH452_BCD_MINUS		0x12
#define		CH452_BCD_EQU		0x13
#define		CH452_BCD_LEFT		0x14
#define		CH452_BCD_RIGHT		0x15
#define		CH452_BCD_UNDER		0x16
#define		CH452_BCD_CH_H		0x17
#define		CH452_BCD_CH_L		0x18
#define		CH452_BCD_CH_P		0x19
#define		CH452_BCD_DOT		0x1A
#define		CH452_BCD_SELF		0x1E
#define		CH452_BCD_TEST		0x88
#define		CH452_BCD_DOT_X		0x80

// 有效按键代码
#define		CH452_KEY_MIN		0x40
#define		CH452_KEY_MAX		0x7F

// 注意!ch452通信线:对应原理图的实际连线
sbit CH452_DCLK=P4^4; // 串行数据时钟上升延激活
sbit CH452_DIN=P4^3;  //串行数据输出,接CH452的数据输入
sbit CH452_LOAD=P4^2; //串行命令加载,上升延激活
//INT0:P3.2,键盘中断和键值数据输入,接CH452的数据输出
sbit CH452_DOUT=P3^2; 

/* 4线接口的位操作,与单片机有关 */
#define		CH452_DCLK_SET		{CH452_DCLK=1;}
#define		CH452_DCLK_CLR		{CH452_DCLK=0;}
// 设置DCLK为输出方向,对于双向I/O需切换为输出
#define		CH452_DCLK_D_OUT	{}				

#define		CH452_DIN_SET		{CH452_DIN=1;}
#define		CH452_DIN_CLR		{CH452_DIN=0;}
// 设置DIN为输出方向,对于双向I/O需切换为输出
#define		CH452_DIN_D_OUT		{}				

#define		CH452_LOAD_SET		{CH452_LOAD=1;}
#define		CH452_LOAD_CLR		{CH452_LOAD=0;}
// 设置LOAD为输出方向,对于双向I/O需切换为输出
#define		CH452_LOAD_D_OUT	{}				
// 设置DOUT为输入方向,对于双向I/O需切换为输入
#define		CH452_DOUT_D_IN		{CH452_DOUT=1;}	

/* 与单片机有关,与中断连接方式有关 */
#define		DISABLE_KEY_INTERRUPT	{EX0=0;}
#define		ENABLE_KEY_INTERRUPT	{EX0=1;}
#define		CLEAR_KEY_INTER_FLAG	{IE0=0;}

unsigned char CH452_Read(void);		  // 从CH452读取按键代码
void CH452_Write(unsigned short cmd); // 向CH452发出操作命令
void CH452_Init(); //初始化

#endif

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值