/*
program name : keyboard ;
功能描述 : 掃描16個(gè)按鍵(4X4),并把鍵值顯示在數(shù)碼管上(兩位);
要點(diǎn) : 在掃描按鍵時(shí)運(yùn)用了比較復(fù)雜的兩個(gè)for()循環(huán)嵌套式
掃描方案,大大減少了程序量,循環(huán)嵌套方案讓我糾結(jié)了好久,
鍵值有0~9,上,下,左,右,確認(rèn),清零;
體會(huì): 又一個(gè)里程碑,淚奔啊...我似乎成了 代碼男神 啊...;
實(shí)驗(yàn)用時(shí): 約等于14小時(shí)(每天2小時(shí)X7天);
完成時(shí)間: 2013-11-19 23:58:22
*/
#include <iom16v.h>
#include <macros.h>
#define uint8 unsigned char //宏定義8位數(shù)據(jù)類(lèi)型;
#define uint16 unsigned int //宏定義16位數(shù)據(jù)類(lèi)型;
// 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) //數(shù)碼管位選使能函數(shù);
{
PORTB|=0X02; //數(shù)碼管位選置1(透明狀態(tài));
if(h==0)
{
PORTB&=0XFD; //清零(鎖存狀態(tài));
}
}
void dat(uint8 u) //數(shù)碼管數(shù)據(jù)使能函數(shù);
{
PORTB|=0X01;
if(u==0)
{
PORTB&=0XFE;
}
}
void buzz(uint8 k) //蜂鳴器函數(shù);
{
if(k==0)
{
PORTC&=~(0X80);
}
else PORTC|=0X80;
}
void delay(uint8 j) //1=1000個(gè)計(jì)數(shù)周期;
{
uint16 h=0;
while(j--)
{
for(h=0;h<1000;h++);
}
}
void mega16() //初始化各個(gè)IO口;
{
DDRA=0XFF; //PA輸出;
DDRB=0XFF; //PB輸出;
PORTA=0X00; //PA 輸出全0;
delay(1); //延時(shí)一下,1000個(gè)計(jì)數(shù)周期;
bit(0); //數(shù)碼管共陰極全零;
PORTA=0X3F; //數(shù)碼管數(shù)據(jù)口裝載數(shù)據(jù)顯示0;
PORTB=1<<2; //打開(kāi)led流水燈燈;
dat(0); //鎖存數(shù)碼管數(shù)據(jù)口數(shù)據(jù),八個(gè)數(shù)碼管顯示0;
delay(30); //延時(shí)一下;
DDRD=0X0F; //PD口高四位輸入,第四位輸出;
PORTD=0XFF; //PD輸入口內(nèi)部上拉,輸出口輸出全1;
DDRC=0XFF; //PC口全部輸出模式;
PORTC=0X00; //PC口輸出全零;
}
void led()
{
static uint8 g=0;
PORTA=0Xff; //向數(shù)碼管輸入顯示數(shù)據(jù)時(shí),必先將共陰極全部置一,
//否則數(shù)碼管會(huì)出現(xiàn)陰影;
bit(0); //八個(gè)數(shù)碼管共陰極置一(低電平有效);
switch(g)
{ case 0: PORTA=ak[ge] ;dat(0);PORTA=0XFE;break;//數(shù)碼管個(gè)位;
case 1: PORTA=ak[shi];dat(0);PORTA=0XFD;break; //數(shù)碼管十位;
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 確認(rèn); ;
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用于檢測(cè)每一行某個(gè)鍵是否按下; en數(shù)組是四列檢測(cè);
for(v=0;v<4;v++) //v每加一代表檢測(cè)一列;
{
PORTD=en[v]; //檢測(cè)四列;
temp=0x10;
for(y=0;y<4;y++) //y每加一,代表檢測(cè)一列中的一個(gè)按鍵;
{
if((PIND&temp)==0) //如果有鍵被按下,進(jìn)入;
{
for(i=0;i<250;i++){led();} //去抖延時(shí)并且掃描數(shù)碼管;
if((PIND&temp)==0) //再次確認(rèn)有鍵被按下;
{
buzz(1); //蜂鳴器開(kāi);
for(i=0;i<200;i++){led();} //鳴響延時(shí);
for(i=0;i<200;i++){led();} //鳴響延時(shí);
buzz(0); //蜂鳴器關(guān);
//===============生成鍵值部分================
if(v==1)y+=3; //檢測(cè)到第二行; //
else if(v==2)y+=6; //檢測(cè)到第三行; //
else if(v==3)y+=9; //檢測(cè)到第四行; //
else {;} //檢測(cè)到第一行; //
ke=v+y; //生成鍵值; //
//===========================================
shu(ke); // 發(fā)送鍵值;
while((PIND&temp)==0)led(); //等待按鍵彈起;
for(i=0;i<250;i++){led();} //等待一下;
while((PIND&temp)==0)led(); //再次確認(rèn)一下按鍵是否彈起;
return 0; //結(jié)束函數(shù);
}
}
temp=temp<<1; //左移一下代表檢測(cè)下一個(gè)按鍵;
}
}
}
void main(void)
{
mega16(); //初始化各個(gè)IO口;
buzz(1); //蜂鳴器開(kāi);
delay(15); //延時(shí)1.5萬(wàn)計(jì)數(shù)周期;
buzz(0); //蜂鳴器關(guān);
PORTA=0xff; //載入全1;
bit(0); //把全1數(shù)據(jù)鎖存在數(shù)碼管共陰極(數(shù)碼管滅);
delay(15); //延時(shí)1.5萬(wàn)計(jì)數(shù)周期;
while(1)
{
led(); //掃描數(shù)碼管;
key(); //掃描鍵盤(pán);
}
}