4x4矩阵键盘工作原理及扫描程序_AVR单片机扫描4X4矩阵键盘并数码管显示程序
/*
program name :?? keyboard ;
功能描述 :? 掃描16個按鍵(4X4),并把鍵值顯示在數碼管上(兩位);
要點 :? 在掃描按鍵時運用了比較復雜的兩個for()循環嵌套式
掃描方案,大大減少了程序量,循環嵌套方案讓我糾結了好久,
鍵值有0~9,上,下,左,右,確認,清零;
體會:? 又一個里程碑,淚奔啊...我似乎成了 代碼男神? 啊...;
實驗用時:? 約等于14小時(每天2小時X7天);
完成時間: 2013-11-19 23:58:22
*/
#include
#include
#define uint8? unsigned char????? //宏定義8位數據類型;
#define uint16 unsigned int?????? //宏定義16位數據類型;
//? 0 , 1? ,? 2? , 3? , 4? , 5? , 6? ,
uint8 ak[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
//??? 7? , 8? , 9 , 上? , 下?? 左 , 右? ;
0x07,0x7f,0x6f,0x62 ,0x54,0x21,0x0c};
uint8? ge=8,shi=8 ,si=0;
void bit(uint8 h)??? //數碼管位選使能函數;
{
PORTB|=0X02;?? //數碼管位選置1(透明狀態);
if(h==0)
{
PORTB&=0XFD;?? //清零(鎖存狀態);
}
}
void dat(uint8 u)?? //數碼管數據使能函數;
{
PORTB|=0X01;
if(u==0)
{
PORTB&=0XFE;
}
}
void buzz(uint8 k)??? //蜂鳴器函數;
{
if(k==0)
{
PORTC&=~(0X80);
}
else? PORTC|=0X80;
}
void delay(uint8 j)????????? //1=1000個計數周期;
{
uint16? h=0;
while(j--)
{
for(h=0;h<1000;h++);
}
}
void mega16()?????? //初始化各個IO口;
{
DDRA=0XFF;??? //PA輸出;
DDRB=0XFF;??? //PB輸出;
PORTA=0X00;?? //PA 輸出全0;
delay(1);???? //延時一下,1000個計數周期;
bit(0);????????? //數碼管共陰極全零;
PORTA=0X3F;??? //數碼管數據口裝載數據顯示0;
PORTB=1<<2;??? //打開led流水燈燈;
dat(0);??????? //鎖存數碼管數據口數據,八個數碼管顯示0;
delay(30);??? //延時一下;
DDRD=0X0F;?? //PD口高四位輸入,第四位輸出;
PORTD=0XFF;? //PD輸入口內部上拉,輸出口輸出全1;
DDRC=0XFF;?? //PC口全部輸出模式;
PORTC=0X00;?? //PC口輸出全零;
}
void led()
{
static uint8 g=0;
PORTA=0Xff;? //向數碼管輸入顯示數據時,必先將共陰極全部置一,
//否則數碼管會出現陰影;
bit(0);???? //八個數碼管共陰極置一(低電平有效);
switch(g)
{? case 0:? PORTA=ak[ge] ;dat(0);PORTA=0XFE;break;//數碼管個位;
case 1:? PORTA=ak[shi];dat(0);PORTA=0XFD;break; //數碼管十位;
default: break;?? //否則...
}
bit(0);
g++;
if(g==2)
{
g=0;
}
}
shu(uint8 c)
{
if(c<=2) {c++;}? //1~3;
else if(c==3) {ge=10;shi=10; return 0;}?? //上;
else if(c==11){ge=c ; shi=c; return 0;}?? //下;
else if(c==7) {ge=12,shi=12; return 0;}?? //左;
else if(c==15) {ge=13,shi=13; return 0;}?? //右;
else if(c==13){return 0;}????? //enter 確認;? ;
else if(c==14){ge=0; shi=0;? return 0;}? //清零;
else if((c>=8)&&(c<=10)){c-=1;}? //7~9;
else if(c==12){ge=0;return 0;}
else { ;}??? //4~6;
ge=c; shi=0;
}
key()
{
uint8? i=0 ,y=0,temp=0x10 ,v=0,ke=0 ,en[]={0xfe,0xfd,0xfb,0xf7};
//? temp用于檢測每一行某個鍵是否按下; en數組是四列檢測;
for(v=0;v<4;v++)???? //v每加一代表檢測一列;
{
PORTD=en[v];???? //檢測四列;
temp=0x10;
for(y=0;y<4;y++)??? //y每加一,代表檢測一列中的一個按鍵;
{
if((PIND&temp)==0)??? //如果有鍵被按下,進入;
{
for(i=0;i<250;i++){led();}?? //去抖延時并且掃描數碼管;
if((PIND&temp)==0)??????? //再次確認有鍵被按下;
{
buzz(1);????? //蜂鳴器開;
for(i=0;i<200;i++){led();}?? //鳴響延時;
for(i=0;i<200;i++){led();}?? //鳴響延時;
buzz(0);????? //蜂鳴器關;
//===============生成鍵值部分================
if(v==1)y+=3;?????? //檢測到第二行;??????? //
else if(v==2)y+=6;? //檢測到第三行;??????? //
else if(v==3)y+=9;? //檢測到第四行;??????? //
else {;}????????? //檢測到第一行;??????? //
ke=v+y;??? //生成鍵值;???????????????????? //
//===========================================
shu(ke);??? // 發送鍵值;
while((PIND&temp)==0)led();?? //等待按鍵彈起;
for(i=0;i<250;i++){led();}??? //等待一下;
while((PIND&temp)==0)led();?? //再次確認一下按鍵是否彈起;
return 0;??? //結束函數;
}
}
temp=temp<<1;? //左移一下代表檢測下一個按鍵;
}
}
}
void main(void)
{
mega16();? //初始化各個IO口;
buzz(1);?? //蜂鳴器開;
delay(15); //延時1.5萬計數周期;
buzz(0);?? //蜂鳴器關;
PORTA=0xff;?? //載入全1;
bit(0);?????? //把全1數據鎖存在數碼管共陰極(數碼管滅);
delay(15);?? //延時1.5萬計數周期;
while(1)
{
led();? //掃描數碼管;
key();? //掃描鍵盤;
}
}
總結
以上是生活随笔為你收集整理的4x4矩阵键盘工作原理及扫描程序_AVR单片机扫描4X4矩阵键盘并数码管显示程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 芦荟水的功效与作用、禁忌和食用方法
- 下一篇: 综艺节目php灭灯_非诚勿扰php程序员