单片机按键扫描数码管显示C语言程序.docx
- 文档编号:25752951
- 上传时间:2023-06-12
- 格式:DOCX
- 页数:18
- 大小:19.34KB
单片机按键扫描数码管显示C语言程序.docx
《单片机按键扫描数码管显示C语言程序.docx》由会员分享,可在线阅读,更多相关《单片机按键扫描数码管显示C语言程序.docx(18页珍藏版)》请在冰豆网上搜索。
单片机按键扫描数码管显示C语言程序
单片机按键扫描数码管显示C语言程序
按键扫描数码管显示程序共定义了6个键的功能:
K1、K
2、K
3、K4以及K
5、K8组成的一对复合键,其中K2,K3为连击键,K5为上档键。
在正常工作模式下按K1则切换至状态,在设定模式下按K1键循环选择4个数码管中的某个,被选中的数码管闪烁,此时单按K2键显示数值加1;常按K2显示数值以一定速度递增,同时数码管停止闪烁,当K2松开,数码管恢复闪烁,显示数值停留在K2松开前的值上。
K3完成的功能和K2类似。
其完成减操作。
这2个键只有在设定状态才有效,可以有效防止误操作。
K4为确认键,按下该键回到正常显示状态,所有指示灯熄灭,数码管显示刚刚设定的数值。
K5+K8这对复合键执行复位操作,任何情况下同时按下K5和K8或先按下K5再按下K8,所有数码管的显示全为0,指示灯全灭,进入正常显示状态。
同时程序还对如下几个异常操作进行了处理:
1.2个或多个功能键同时按下
2.一个功能键按下未释放,又按另一个功能键,然后再松开其中一个功能键
3.先按下功能键再按下上档键
4.多个上档键和一个功能键同时按下,此时不做处理。
等到松开其他上档键,只剩下一个上
5.档键和一个功能键时才执行这对复合键;或松开所有上档键,处理单一功能键。
/*******************************************************************************/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineRCtrl0x20//定义上挡键第5键
#defineRConti0xfe//定义连击键第6键
#defineN2//去抖年龄下限
#defineMaxRate50//重复前的延迟值600ms
#defineMinRate20//重复速度240ms
#defineleddark83//闪烁时灭时间1s
#defineledshow83//闪烁时亮时间1s
#definedecimal0x80//小数点的段数
#defineKEY_DDRDDRC
#defineKEY_PORTOPORTC
#defineKEY_PORTIPINC
#defineOUT0x3f
#defineIN0xc0
#defineKeyValue0x3f
#defineLEDD_DDRDDRB
#defineLEDD_PORTOPORTB
#defineLEDS_DDRDDRD
#defineLEDS_PORTOPORTD
#defineLEDS_MASK0xfc
#defineLEDS_NUM0x06
#defineTRUE1
#defineFALSE0
/*定义键盘扫描程序返回数据类型*/
ucharshiftval;//最后扫描到的上档键的值
ucharfunval;//最后扫描到的功能键的值
}keyret;
/*定义显示字符段码*/
ucharconstled_stroke[19]={//0,1,2,3,4,5,6,7,8,9
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
//a,b,C,d,e,F,P,
0x77,0x7C,0x39,0x5E,0x79,0x71,0x73,
//allonalloff
0xff,0x00
};
/*定义位选码*/
ucharconstled_cs[LEDS_NUM]={0xfb,//111011
0xf7,//110111
0xef,//111011
0xdf,//110111
0xbf,//10111
0x7f//01111
};
ucharled_buf[LEDS_NUM]={0x73,0x81,0x82,0x83,0x84,0x85
};
uchar*pb=&led_buf[1];//定义指向数码管数据缓冲区的指针
/*定义全局变量*/
uchartask,state;//task:
按键状态,0:
去抖1,重复的延迟2,重复
//state:
显示位置变量
ucharkeydone,keyprocess;//keydone:
按键任务完成标志,为1表示已完成//keyprocess:
按键有效标志,为1时表示对按键执行
ucharkeypre[2]={0x00,0x00
};//存放上次功能键和上档键的键值
//keypre0存放功能键
ucharblink,ledtime;//blink:
闪烁控制寄存器,某位为1时闪烁
//d7d6d5d4d3d2d1d0
//xx11
//ledtime:
累计闪烁时已点亮和已熄灭的时间
ucharledtask;//ledtask:
当前的闪烁状态,0代表亮
ucharkeymark;//keymark:
只是当前工作状态,为1时处于设定状态,为0时正常工作ucharenflash;//enflash:
闪烁使能标志,1闪烁
#defineshut_dis()LEDS_PORTO|=LEDS_MASK;//shutdisplay
/*******************************************************************************
*函数原型:
uchar_crol_(uchardata,ucharshiftbit);
*功能:
字节左移shiftbit
*参数:
*说明:
*******************************************************************************/
uchar_crol_(uchardata,ucharshiftbit){data&=0xff;
if(shiftbit>8)return0;
return((~data)< *函数原型: uchar_cror_(uchardata,ucharshiftbit); *功能: 字节右移shiftbit *参数: *说明: *******************************************************************************/ uchar_cror_(uchardata,ucharshiftbit){data&=0xff; if(shiftbit>8)return0; return((~data)>>shiftbit);}/******************************************************************************* *函数原型: voidsend_shift(uchard); *功能: 将显示数据由B口送出 *******************************************************************************/ voidsend_shift(uchardata){LEDD_PORTO=data;}/******************************************************************************* *函数原型: voidlflash(); *功能: 闪烁处理。 ledtask指示当前的显示状态: 亮或灭,ledtask为0时亮 *参数: *说明: *******************************************************************************/ voidlflash(){if(enflash&&(blink&0x3f)){if(ledtime--==0){if(! ledtask) ledtime=leddark; else ledtime=ledshow; ledtask=~ledtask;//显示状态翻转}} else ledtask=0;}/******************************************************************************* *函数原型: voiddisplay(ucharpos); *功能: 将pos对应的显示缓冲区的内容显示在第pos位数码管上 *参数: *说明: *******************************************************************************/ voiddisplay(ucharpos){ucharsflag; shut_dis();//关显示 sflag=(blink>>(6-pos))&0x01;//取出pos对应的数码管的闪烁控制位if(pos==0) send_shift(led_buf[0]);//指示灯显示时直接将显示内容送显示端口elseif(! sflag||(sflag&! ledtask))//不闪烁或正处于闪烁的亮阶段 if((led_buf[pos]&0x80)==0)//不显示小数点,查表得到段码送显示端口send_shift(led_stroke[led_buf[pos]&0x7f]|decimal);//显示小数点,把查表得到段码与小数点的段码与的结果送显示端口 else send_shift(led_stroke[led_buf[pos]&0x7f]); else send_shift(0xff);//pos位数码管不显示 LEDS_PORTO&=led_cs[pos];//送出位选码}/******************************************************************************* *函数原型: voidscankey(keyret*kpd); *功能: 键盘扫描,返回上档键个数,上档键值,功能键个数,功能键值 *参数: *说明: *******************************************************************************/ voidscankey(keyret*kpd){uchari,j; shut_dis();//关显示 KEY_DDR=OUT;//定义数据端口为输出 KEY_PORTO|=KeyValue;//输出数据(输出检测码) KEY_DDR=IN;//定义数据端口为输入 i=(KEY_PORTI&KeyValue);//取出键盘位 if(i! =KeyValue) //检测是否有键按下{i|=~KeyValue;//组成完整的字节 if(~i&RCtrl) //这里不对 for(j=0;j<6;j++){if((0x01< ? }}} kpd->funval=j+1;//上档键值存入上档键值缓冲? ? }}}} KEY_DDR=OUT;//数据端口还原为输出}/******************************************************************************* *函数原型: voidkey(); *功能: 键盘扫描,返回上档键个数,上档键值,功能键个数,功能键值 *参数: *说明: *******************************************************************************/ voidkey(){ucharkrpt=RConti; staticucharkeyesc; keyretkeytemp={0x00,0x00,0x00,0x00 }; if(keydone)//上次按键任务已完成{scankey(&keytemp);//扫描键盘 keypre[0]=0x00;//清零上次功能键和上档键缓冲keypre[1]=0x00; //清零 keyesc=0x00;//键释放标志清零 //本次功能键值和上次不同或本次上档键值和上次不同且上次有上档键elseif(keytemp.funval! =keypre[0]||keytemp.shiftval! =keypre[1]&&keypre[1]){keypre[0]=keytemp.funval;//用本次键值更新上次键值keypre[1]=keytemp.shiftval; switch(task){case0: keyprocess=1;//键值处理 keyesc=1;//是一对复合键或该键不允许连击 else{task++;//按键状态转入重复的延缓阶段 break; case1: //重复的延缓阶段 keyprocess=1;//进行键值处理 task++;//按键转入重复状态}break; case2: //重复阶段 keyprocess=1;//进行键值处理 *函数原型: voidkey1_handler(); *功能: 按键1处理 *参数: *说明: 正常工作模式下,按下按键1即进入设定状态,此时第一个数码管闪烁,同时对应led1 *的指示灯亮。 设定模式下,按下按键1,在led1和led4之间循环切换选择被选中的数码 *管闪烁,相应的指示灯亮 *******************************************************************************/ voidkey1_handler(){if(! keymark)//进入设定状态{led_buf[0]=0xfe;//点亮第一个led pb=&led_buf[1];//pb指向第一个数码管 //blink=0x80;//第一个数码管闪烁 blink=0x20;//第一个数码管闪烁 keymark=1; enflash=1;//允许闪烁}else{pb++;//pb指向下一个数码管 blink>>=1;//该数码管闪烁 //led_buf[0]=_crol_(led_buf[0],2);//调整指示灯 if(pb>=(uchar*)(led_buf+6))//pb指针越限,重新初始化{pb=&led_buf[1]; //blink=0x80;//第一个数码管闪烁 blink=0x20;//第一个数码管闪烁}}}/******************************************************************************* *函数原型: voidkey2_handler(); *功能: 按键2处理 *参数: *说明: 正常工作模式下,按下按键2无效。 设定模式下,按下按键2,每执行一次选中的数码 *管值加一,常按,数值以一定速度连续递增,但数值大于9时又回到0,*******************************************************************************/ voidkey2_handler(){if(keymark){*pb+=1; if(*pb>=10) *pb=0;}} /******************************************************************************* *函数原型: voidkey3_handler(); *功能: 按键3处理 *参数: *说明: 正常工作模式下,按下按键3无效。 设定模式下,按下按键2,每执行一次选中的数码 *管值减一,常按,数值以一定速度连续递减,但数值大于0时又回到9,*******************************************************************************/ voidkey3_handler(){if(keymark){if(*pb<=0) *pb=9; else *pb-=1;}} /******************************************************************************* *函数原型: voidkey4_handler(); *功能: 按键4处理 *参数: *说明: 此键为确认键,按下后熄灭指示灯,不闪烁,进入工作状态 *******************************************************************************/ voidkey4_handler(){blink=0x00; led_buf[0]=0x73; keymark=0;}/******************************************************************************* *函数原型: voidkeymix_handler(); *功能: 复合按键(上档键5和功能键8)处理 *参数: *说明: 执行复位功能,4个数码管全显示0,不闪烁。 8个指示灯全灭,进入正常工作状态*******************************************************************************/ voidkeymix_handler(){led_buf[0]=0x73; led_buf[1]=0; led_buf[2]=0; led_buf[3]=0; led_buf[4]=0; led_buf[5]=0; keymark=0; blink=0;}/******************************************************************************* *函数原型: voidkey_processing(); *功能: 键值处理 *参数: keyprocess,keypre[1],keypre[0], *说明: 根据键值执行相应的按键功能 *******************************************************************************/ voidkey_processing(){if(keyprocess){keydone=0; keyprocess=0; switch(keypre[1]){case0x00: switch(keypre[0]){case0x01: key1_handler(); break; case0x02: key2_handler(); break; case0x03: key3_handler(); break; case0x04: key4_handler(); break;}break; case0x05: if(keypre[0]==8) keymix_handler(); break;}keydone=1;}} //TIMER0initialize-prescale: 256 //desiredvalue: 2mSec //actualvalue: 1.991mSec( 0.5%) voidtimer0_init(void){TCCR0=0x00;//stop TCNT0=0xAA;//setcount TCCR0=0x04;//starttimer}/******************************************************************************* *函数原型: voidtimer0_ovf_isr(void); *功能: 定时器0中断服务程序 *参数: *说明: 键盘和led一起构成1/6扫描,每6次中断进行一次键盘处理 *******************************************************************************/ #pragmainterrupt_handlertimer0_ovf_isr: 10 voidtimer0_ovf_isr(void){TCNT0=0xAA;//setcount if(state<=5){lflash(); display(state); state++;}else{key(); state=0;}} voidUSART0_Init(void){UCSRB=0x00;//disablewhilesettingbaudrate UCSRA=0x00; UCSRC=BIT(URSEL)|0x06; UBRRL=0x47;//setbaudratelo UBRRH=0x00;//setbaudratehi UCSRB=0x18;}//-------------------------------------------------------------------------voidUSART0_Transmit(unsignedchardata){while(! (UCSRA&(1< USART0_Transmit(*data++);}//------------
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 按键 扫描 数码管 显示 语言 程序