




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第五部分基本單片機(jī)C程序分析1、任務(wù):點(diǎn)亮LED燈在Keil軟件編輯窗口輸入以下程序:#include<reg51.h>sbitP3_0=P3^0;voidmain(void){while(1){P3_0=0;}}第五部分基本單片機(jī)C程序分析1、任務(wù):點(diǎn)亮LED燈在Kei2、任務(wù):閃爍燈#include<reg51.h>voiddelay02s(void){unsignedchari,j,k;for(i=20;i>0;i--)for(j=20;j>0;j--)for(k=248;k>0;k--);}voidmain(void){while(1){P3_0=0;delay02s();P3_0=1;delay02s();}}要求:前面例子是讓LED燈亮,現(xiàn)在實(shí)現(xiàn)LED燈的閃爍。2、任務(wù):閃爍燈#include<reg51.h>要求:3、任務(wù):按鍵識別要求:通過按下一次按鍵INT0,使小燈D1亮滅交替變換。實(shí)驗(yàn)原理:只要判斷P3.2的電平就可以知道按鍵是否被按下;而在按鍵按下的過程中,由于機(jī)械抖動,將產(chǎn)生干擾,電平高低變化??梢圆捎密浖V波的方法去除這些干擾信號,在程序設(shè)計時,一旦發(fā)現(xiàn)P3.2為低電平,進(jìn)入按鍵判斷狀態(tài),軟件延時10-20ms,從而避開了干擾信號區(qū)域,再重新檢測P3.2狀態(tài),看按鍵是否真的已經(jīng)按下。3、任務(wù):按鍵識別要求:通過按下一次按鍵INT0,使小燈D1參考程序(傳統(tǒng)的延時消抖按鍵程序)include<AT89X52.H>sbitINT_0=P3^2;//定義按鍵的輸入端sbitD1=P3^0;
//D1小燈定義voiddelay10ms(void)//延時程序{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);}key(
)
//按鍵判斷程序{ if(INT_0==0)//判斷是否按下鍵盤 { delay10ms(
);//延時,軟件去干擾 if(INT_0==0)//確認(rèn)按鍵按下 {
D1=!D1;//D1亮滅交替變化 }
while(INT_0==0);//按鍵鎖定,每按一次D1只變化一次 }參考程序(傳統(tǒng)的延時消抖按鍵程序)續(xù)前頁:}main(){while(1)
//永遠(yuǎn)循環(huán),掃描判斷按鍵是否按下 { key();
//對于此處CPU只按鍵判斷一直掃描; }}
課后請實(shí)踐:1.用兩個按鍵來控制D1的亮滅;2.使用一個按鍵,控制小燈亮的順序D1→D2→D3→D4→┅→D8→D7→→┅D0亮重復(fù)循環(huán);續(xù)前頁:課后請實(shí)踐:4、任務(wù):數(shù)碼管靜態(tài)顯示要求:用數(shù)碼管LED的個位,靜態(tài)顯示數(shù)字“4”字樣;注意:因采用共陰數(shù)碼顯示管,故此圖P0口還應(yīng)接1K或10K的排阻作為上拉電阻。4、任務(wù):數(shù)碼管靜態(tài)顯示要求:用數(shù)碼管LED的個位,靜態(tài)顯參考程序:#include<AT89X52.H>sbitGE=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//顯示段碼main(){ unsignedchardisplay_date=4;//定義并賦值要顯示的數(shù)據(jù) while(1) { P0=seg7code[display_date];
//查表,輸出 GE=0;//P1^3為低電平,相當(dāng)于把數(shù)碼管的4H端接地 }}課后請實(shí)踐:1.讓顯示的數(shù)據(jù)動起來,比如做一個0到9的秒表(用軟件延時);2.和按鍵判斷程序結(jié)合,用按鍵控制數(shù)字變化;參考程序:課后請實(shí)踐:5、任務(wù):數(shù)碼管動態(tài)顯示要求:用數(shù)碼管LED的顯示四位數(shù)據(jù),比如顯示數(shù)字“1234”;參考程序:#include<AT89X52.H>sbitqian=P1^0;sbitbai=P1^1;sbitshi=P1^2;sbitge=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//顯示段碼voidDelay(unsignedinttc)//延時程序{ while(tc!=0) //如果tc為0則終止延時 { unsignedinti; //局部正整數(shù)變量i for(i=0;i<100;i++); //執(zhí)行400次將耗時1毫秒 tc--; //tc計數(shù)減一 }}5、任務(wù):數(shù)碼管動態(tài)顯示要求:用數(shù)碼管LED的顯示四位數(shù)據(jù)續(xù)前頁:voidLed(intdate)//顯示函數(shù){ qian=0;//P1.0輸出低電平,選通千位數(shù) P0=seg7code[date/1000];//取出千位數(shù),查表,輸出。 Delay(10);//延時 qian=1;//銷隱 bai=0;//P1.1輸出低電平,選通百位數(shù) P0=seg7code[date%1000/100];//取出百位數(shù),查表,輸出。 Delay(10);//延時 bai=1;//銷隱 shi=0;//P1.2輸出低電平,選通十位數(shù) P0=seg7code[date%100/10];//取出十位數(shù),查表,輸出。 Delay(10);//延時 shi=1;//銷隱 ge=0; //P1.3輸出低電平,選通十位數(shù) P0=seg7code[date%10];//取出個位數(shù),查表,輸出。 Delay(10); ge=1;}
續(xù)前頁:續(xù)前頁:main(){intdisplay_date=1234;//定義并賦值要顯示的數(shù)據(jù)while(1){Led(display_date);//調(diào)用顯示函數(shù)顯示數(shù)據(jù)display_date}}
續(xù)前頁:上述數(shù)碼管動態(tài)顯示程序的另一種寫法參考程序:#include<AT89X51.H>unsignedchardatebit[]={0xfe,0xfd,0xfb,0xf7};//存儲數(shù)碼管的位選值unsignedchartvdate[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,};unsignedintdisdata;//定義要顯示的數(shù)據(jù)unsignedchardisdat[4];//存儲要顯示的四位數(shù)據(jù)voiddelay(time){unsignedchari,j;for(j=0;j<time;j++)for(i=0;i<250;i++);}display(void){ unsignedchark; disdata=1234;//顯示1234
上述數(shù)碼管動態(tài)顯示程序的另一種寫法參考程序:續(xù)前頁:
disdat[0]=disdat/1000; //取出千位 disdat[1]=disdat%1000/100;
//取出百位 disdat[2]=disdat%100/10; //取出十位 disdat[3]=disdat%10; //取出個位 for(k=0;k<4;k++)
//顯示四位數(shù)據(jù) { P0=tvdate[disdat[k]];
//送出要顯示數(shù)據(jù)的段碼 P1=datebit[k]; //P2位選 delay(10); //延時 }}main(){while(1){display();}}
這種寫法比上一種復(fù)雜,占用空間要多一些.但是使用方便,可以在此基礎(chǔ)上方便的加上比如顯示小數(shù)點(diǎn),指定某位數(shù)碼管閃爍等。課后思考:如何用軟件延時來做一個0到60秒的計數(shù)器嗎?續(xù)前頁:這種寫法比上一種復(fù)雜,占用空間要多一些.但是使6、任務(wù):4X4矩陣鍵盤識別要求:用AT89S51的并行口P2接4×4矩陣鍵盤,以P3.0-P3.3作輸入線,以P3.4-P3.7作輸出線;在每一個數(shù)碼管上顯示每個按鍵的“0-F”序號。[實(shí)驗(yàn)原理]每個按鍵有它的行值和列值,行值和列值的組合就是識別這個按鍵的編碼。矩陣的行線和列線分別通過兩并行接口和CPU通信。鍵盤處理程序的任務(wù)是:確定有無鍵按下,判斷哪一個鍵按下,鍵的功能是什么;還要消除按鍵在閉合或斷開時的抖動。兩個并行口中,一個輸出掃描碼,使按鍵逐行動態(tài)接地,另一個并行口輸入按鍵狀態(tài),由行掃描值和回饋信號共同形成鍵編碼而識別按鍵,通過軟件查表,查出該鍵的功能。6、任務(wù):4X4矩陣鍵盤識別要求:用AT89S51的并行口鍵盤識別的兩種方法逐行掃描法:(1)首先判斷有無鍵按下:令矩陣行線輸出全0信號,檢測列線狀態(tài),若有一列電平為低,則有鍵按下。(2)確定閉合鍵位置:依次將各行線置為低電平,逐行檢測各列線的電平狀態(tài),若某列為低,則該行線和列線交叉處按鍵就是閉合鍵。線反轉(zhuǎn)法:(1)令矩陣鍵盤列線輸出全0信號,行線作為輸入接口接收信號,可判斷按鍵處于哪一行。(2)令矩陣鍵盤行線輸出全0信號,列線作為輸入接口接收信號,可判斷按鍵處于哪一列。(3)將輸入信號相或后形成鍵盤的唯一鍵碼。鍵盤識別的兩種方法逐行掃描法:程序:(線反轉(zhuǎn)法)#include<reg52.h>unsignedcharcodeseg7code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsignedchark;voiddelay10ms(void)//延時程序{ unsignedchari,j; for(i=20;i>0;i--) for(j=248;j>0;j--);}voidGetch(){ unsignedcharX,Y,Z;
P2=0xff;
P2=0x0f;
//先對P2置數(shù)行掃描 if(P2!=0x0f)//判斷是否有鍵按下 {
delay10ms();//延時,軟件去干擾
if(P2!=0x0f)
//確認(rèn)按鍵按下X=P2;
{
程序:(線反轉(zhuǎn)法)續(xù)前頁:
X=P2;//保存行掃描時有鍵按下時狀態(tài) P2=0xf0;//列掃描 Y=P2;//保存列掃描時有鍵按下時狀態(tài) Z=X|Y;//取出鍵值 switch(Z)//判斷鍵值(那一個鍵按下) { case0x77:k=0;break;//對鍵值賦值 case0x7b:k=1;break; case0x7d:k=2;break; case0x7e:k=3;break; case0xb7:k=4;break; case0xbb:k=5;break; case0xbd:k=6;break; case0xbe:k=7;break; case0xd7:k=8;break; case0xdb:k=9;break; case0xdd:k=10;break; case0xde:k=11;break; case0xe7:k=12;break; case0xeb:k=13;break; 續(xù)前頁:續(xù)前頁:
case0xed:k=14;break;
case0xee:
k=15;break; } } }}voidmain(void){while(1){P2=0xff;Getch(
);P0=seg7code[k];//查表LED輸出P1=0xf0;//輸出相同的四位數(shù)據(jù)。}}
續(xù)前頁:該程序的缺陷:1、雖然線反轉(zhuǎn)法識別鍵盤的思路正確,但本程序按鍵掃描中消除按鍵抖動采用了傳統(tǒng)的延時方法,這種辦法會使CPU陷入無謂的等待,在延時的過程中CPU無法并行處理其它事件。采用定時掃描法(比如采用定時中斷每隔100ms掃描1次鍵盤),可以解決這一問題;2、如果要求實(shí)現(xiàn)“短促”按鍵和“長按”按鍵的區(qū)分,使程序能應(yīng)用在功能要求更為復(fù)雜的場合,繼續(xù)編制該程序則有繁瑣和可讀性變差的缺點(diǎn)。因此有必要采用更為便捷和高效的鍵值識別算法以實(shí)現(xiàn)本程序的功能。
該程序的缺陷:新型鍵盤識別程序基本思想:unsignedcharTrg;unsignedcharCont;voidKeyRead(void){unsignedcharReadData=P3^0xff;//1
Trg=ReadData&(ReadData^Cont);//2
Cont=ReadData;//3
}分析:(1)沒有按鍵的時候ReadData=0x00;Trg=0x00;Cont=0x00;(2)第一次按下按鍵的情況
(假設(shè)按鍵接在P3.0上面)ReadData=0x01;Trg=0x01;Cont=0x01;(3)按鍵按著不松(長按鍵)的情況ReadData=0x01;Trg=0x00;Cont=0x01;
(4)按鍵松開的情況ReadData=0x00;Trg=0x00;Cont=0x00;
Trg表示的就是觸發(fā)的意思,也就是跳變,只要有按鍵按下,Trg在對應(yīng)按鍵的位上面會置1;最關(guān)鍵的地方,Trg的值每次按下只會出現(xiàn)一次,然后立刻被清除,完全不需要人工去干預(yù)。所以按鍵功能處理程序不會重復(fù)執(zhí)行,省下了一大堆的條件判斷,所謂精粹即此??!Cont代表的是長按鍵,如果按鍵按著不放,那么Cont的值就為0x01。新型鍵盤識別程序基本思想:Trg表示的就是觸發(fā)的意思,也就應(yīng)用一:一次觸發(fā)的按鍵處理——假設(shè)為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲
#defineKEY_BEEP0x01voidKeyProc(void){if(Trg&KEY_BEEP)//如果按下的是KEY_BEEP
{Beep();//執(zhí)行蜂鳴器處理函數(shù)
}}應(yīng)用一:一次觸發(fā)的按鍵處理——假設(shè)為蜂鳴器按鍵,按一下,蜂鳴應(yīng)用二:長按鍵的處理
#defineKEY_MODE0x01//此模式按鍵也
#defineKEY_PLUS0x02//此加鍵也
voidKeyProc(void){if(Trg&KEY_MODE)//若KEY_MODE鍵按之,雖常按亦無益
{//無執(zhí)行再,必先松再按可矣
Mode++;//模式寄存器加1
}if(Cont&KEY_PLUS)//若“加”鍵按之不放
{cnt_plus++;//則計時
if(cnt_plus>100)//20ms*100=2S若計時到
{Func();//則執(zhí)行所需執(zhí)行之功能程序也
}}}應(yīng)用二:長按鍵的處理#defineKEY_MODE0x延時消抖問題?真正的單片機(jī)入門,是從學(xué)會處理多任務(wù)開始的。
加入延時消抖程序的架構(gòu)如下:volatileunsignedcharIntrcnt;voidInterruptHandle()//中斷服務(wù)程序
{Intrcnt++;}//1ms中斷1次,可變
voidmain(void){SysInit();while(1)//每20ms執(zhí)行一次大循環(huán)
{KeyRead();//將每個子程序都掃描一遍
KeyProc();Func1();Funt2();……while(1){if(Intrcnt>20)//一直在等,直到20ms時間到
{Intrcnt="0";break;}//返回主循環(huán)
}}}延時消抖問題?真正的單片機(jī)入門,是從學(xué)會處理多任務(wù)開始的。怎么判斷按鍵釋放?再增加一個按鍵釋放檢測功能,程序如下:
volatileunsignedcharTrg;volatileunsignedcharCont;volatileunsignedcharRelease;//再增加新功能!
voidKeyRead(void){unsignedcharReadData=PINB^0xff;//1讀鍵值
Trg=ReadData&(ReadData^Cont);//2得到按下觸發(fā)值
Release=(ReadData^Trg^Cont);//3得到釋放觸發(fā)值
Cont=ReadData;//4得到所有未釋放的鍵值
}怎么判斷按鍵釋放?再增加一個按鍵釋放檢測功能,程序如下:v7、任務(wù):按鍵中斷識別要求:采用中斷技術(shù),每按一下按鍵,計數(shù)器加1,并用LED顯示出來,注意只顯示2位十進(jìn)制數(shù)。原理:以上的兩個舊式按鍵識別的實(shí)驗(yàn)的程序都是采用掃描的方式來實(shí)現(xiàn)的,CPU的利用率比較低;按鍵判斷還可以用中斷方式來判斷。中斷方式可以滿足快速響應(yīng)的要求。7、任務(wù):按鍵中斷識別要求:采用中斷技術(shù),每按一下按鍵,計數(shù)程序:#include<AT89X51.H>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsignedchardispcount=0;//計數(shù)sbitgewei=P1^3;//個位選通定義sbitshiwei=P1^2;//十位選通定義voidDelay(unsignedinttc)//延時程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}voidExtInt0()interrupt0//中斷服務(wù)程序{程序:續(xù)前頁:dispcount++;//每按一次中斷按鍵,計數(shù)加一if(dispcount==100)//計數(shù)范圍0-99{dispcount=0;}}voidLED()//LED顯示函數(shù){if(dispcount>=10)//顯示兩位數(shù){shiwei=0;P0=table[dispcount/10];Delay(8);shiwei=1;gewei=0;P0=table[dispcount%10];Delay(5);gewei=1;}else//顯示一位數(shù){
續(xù)前頁:續(xù)前頁:shiwei=1;gewei=0;P0=table[dispcount];Delay(8);}}
voidmain(){TCON=0x01;
//下降沿觸發(fā)
IE=0x81;
//開總中斷和允許外部中斷
while(1)
//循環(huán)執(zhí)行{LED(
);}
//調(diào)用顯示函數(shù)}/*******************************************************************課后思考:在程序在硬件運(yùn)行過程中,有時候按一下鍵會加幾個數(shù),是因?yàn)闆]有去除按鍵干擾請您想一想怎么消除抖動./***************************************************************************************/
續(xù)前頁:8、任務(wù):數(shù)模轉(zhuǎn)換器ADC0804的應(yīng)用(擴(kuò)展)要求:從ADC0804的通道IN+輸入0-5V之間的模擬量,通過ADC0804轉(zhuǎn)換成數(shù)字量在數(shù)碼管上以十進(jìn)制形成顯示出來。8、任務(wù):數(shù)模轉(zhuǎn)換器ADC0804的應(yīng)用(擴(kuò)展)要求:從AD程序:#include<reg52.h>codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//顯示段碼sbitint1=P3^3;//定義管腳功能sbitcs=P3^2;sbitwr=P3^6;sbitrd=P3^7;voidDelay(unsignedinttc)//顯示延時程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}unsignedcharadc0804(void)//讀AD0804子程序{unsignedcharaddata,i;rd=1;wr=1;int1=1;//讀ADC0804前準(zhǔn)備P1=0xff;//P1全部置一準(zhǔn)備cs=0;wr=0;wr=1;//啟動ADC0804開始測電壓while(int1==1);//查詢等待A/D轉(zhuǎn)換完畢產(chǎn)生的INT(低電平有效)信號rd=0;//開始讀轉(zhuǎn)換后數(shù)據(jù)程序:續(xù)前頁:i=i;i=i;//無意義語句,用于延時等待ADC0804讀數(shù)完畢addata=P1;//讀出的數(shù)據(jù)賦與addatard=1;cs=1;//讀數(shù)完畢return(addata);//返回最后讀出的數(shù)據(jù)}unsignedintdatpro(void)
//ADC0804讀出的數(shù)據(jù)處理{unsignedcharx;unsignedintdianyah,dianyal;
//用于存儲讀出數(shù)據(jù)的高字節(jié)和低字節(jié)unsignedintdianya=0;
//存儲最后處理完的結(jié)果注意數(shù)據(jù)類型for(x=0;x<10;x++)
//將10次測得的結(jié)果存儲在dianya中{dianya=adc0804()+dianya;}dianya=dianya/10;
//求平均值dianyah=dianya&0xf0;
//屏蔽低四位dianyah=dianyah>>4;
//右移四位取出高四位dianyal=dianya&0x0f;
//屏蔽高四位取出低四位dianya=dianyal*20+dianyah*320;
//最后的結(jié)果是一個四位數(shù),便于顯示return(dianya);//返回最后處理結(jié)果}換為dianya*=196;續(xù)前頁:換為dianya*=196;續(xù)前頁:voidLed(){unsignedintdate;date=datpro();//調(diào)用數(shù)據(jù)處理最后結(jié)果P2=P2&0xef;P0=seg7code[date/1000]|0x80;//輸出個位數(shù)和小數(shù)點(diǎn)Delay(8);P2=P2|0xf0;P2=P2&0xdf;P0=seg7code[date%1000/100];//輸出小數(shù)點(diǎn)后第一位Delay(8);P2=P2|0xf0;P2=P2&0xbf;P0=seg7code[date%100/10];//輸出小數(shù)點(diǎn)后第二位Delay(8);P2=P2|0xf0;P2=P2&0x7f;P0=seg7code[date%10];//輸出小數(shù)點(diǎn)后第三位Delay(8);P2=P2|0xf0;}main(){while(1){Led();//只需調(diào)用顯示函數(shù)}}續(xù)前頁:第五部分基本單片機(jī)C程序分析1、任務(wù):點(diǎn)亮LED燈在Keil軟件編輯窗口輸入以下程序:#include<reg51.h>sbitP3_0=P3^0;voidmain(void){while(1){P3_0=0;}}第五部分基本單片機(jī)C程序分析1、任務(wù):點(diǎn)亮LED燈在Kei2、任務(wù):閃爍燈#include<reg51.h>voiddelay02s(void){unsignedchari,j,k;for(i=20;i>0;i--)for(j=20;j>0;j--)for(k=248;k>0;k--);}voidmain(void){while(1){P3_0=0;delay02s();P3_0=1;delay02s();}}要求:前面例子是讓LED燈亮,現(xiàn)在實(shí)現(xiàn)LED燈的閃爍。2、任務(wù):閃爍燈#include<reg51.h>要求:3、任務(wù):按鍵識別要求:通過按下一次按鍵INT0,使小燈D1亮滅交替變換。實(shí)驗(yàn)原理:只要判斷P3.2的電平就可以知道按鍵是否被按下;而在按鍵按下的過程中,由于機(jī)械抖動,將產(chǎn)生干擾,電平高低變化??梢圆捎密浖V波的方法去除這些干擾信號,在程序設(shè)計時,一旦發(fā)現(xiàn)P3.2為低電平,進(jìn)入按鍵判斷狀態(tài),軟件延時10-20ms,從而避開了干擾信號區(qū)域,再重新檢測P3.2狀態(tài),看按鍵是否真的已經(jīng)按下。3、任務(wù):按鍵識別要求:通過按下一次按鍵INT0,使小燈D1參考程序(傳統(tǒng)的延時消抖按鍵程序)include<AT89X52.H>sbitINT_0=P3^2;//定義按鍵的輸入端sbitD1=P3^0;
//D1小燈定義voiddelay10ms(void)//延時程序{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);}key(
)
//按鍵判斷程序{ if(INT_0==0)//判斷是否按下鍵盤 { delay10ms(
);//延時,軟件去干擾 if(INT_0==0)//確認(rèn)按鍵按下 {
D1=!D1;//D1亮滅交替變化 }
while(INT_0==0);//按鍵鎖定,每按一次D1只變化一次 }參考程序(傳統(tǒng)的延時消抖按鍵程序)續(xù)前頁:}main(){while(1)
//永遠(yuǎn)循環(huán),掃描判斷按鍵是否按下 { key();
//對于此處CPU只按鍵判斷一直掃描; }}
課后請實(shí)踐:1.用兩個按鍵來控制D1的亮滅;2.使用一個按鍵,控制小燈亮的順序D1→D2→D3→D4→┅→D8→D7→→┅D0亮重復(fù)循環(huán);續(xù)前頁:課后請實(shí)踐:4、任務(wù):數(shù)碼管靜態(tài)顯示要求:用數(shù)碼管LED的個位,靜態(tài)顯示數(shù)字“4”字樣;注意:因采用共陰數(shù)碼顯示管,故此圖P0口還應(yīng)接1K或10K的排阻作為上拉電阻。4、任務(wù):數(shù)碼管靜態(tài)顯示要求:用數(shù)碼管LED的個位,靜態(tài)顯參考程序:#include<AT89X52.H>sbitGE=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//顯示段碼main(){ unsignedchardisplay_date=4;//定義并賦值要顯示的數(shù)據(jù) while(1) { P0=seg7code[display_date];
//查表,輸出 GE=0;//P1^3為低電平,相當(dāng)于把數(shù)碼管的4H端接地 }}課后請實(shí)踐:1.讓顯示的數(shù)據(jù)動起來,比如做一個0到9的秒表(用軟件延時);2.和按鍵判斷程序結(jié)合,用按鍵控制數(shù)字變化;參考程序:課后請實(shí)踐:5、任務(wù):數(shù)碼管動態(tài)顯示要求:用數(shù)碼管LED的顯示四位數(shù)據(jù),比如顯示數(shù)字“1234”;參考程序:#include<AT89X52.H>sbitqian=P1^0;sbitbai=P1^1;sbitshi=P1^2;sbitge=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//顯示段碼voidDelay(unsignedinttc)//延時程序{ while(tc!=0) //如果tc為0則終止延時 { unsignedinti; //局部正整數(shù)變量i for(i=0;i<100;i++); //執(zhí)行400次將耗時1毫秒 tc--; //tc計數(shù)減一 }}5、任務(wù):數(shù)碼管動態(tài)顯示要求:用數(shù)碼管LED的顯示四位數(shù)據(jù)續(xù)前頁:voidLed(intdate)//顯示函數(shù){ qian=0;//P1.0輸出低電平,選通千位數(shù) P0=seg7code[date/1000];//取出千位數(shù),查表,輸出。 Delay(10);//延時 qian=1;//銷隱 bai=0;//P1.1輸出低電平,選通百位數(shù) P0=seg7code[date%1000/100];//取出百位數(shù),查表,輸出。 Delay(10);//延時 bai=1;//銷隱 shi=0;//P1.2輸出低電平,選通十位數(shù) P0=seg7code[date%100/10];//取出十位數(shù),查表,輸出。 Delay(10);//延時 shi=1;//銷隱 ge=0; //P1.3輸出低電平,選通十位數(shù) P0=seg7code[date%10];//取出個位數(shù),查表,輸出。 Delay(10); ge=1;}
續(xù)前頁:續(xù)前頁:main(){intdisplay_date=1234;//定義并賦值要顯示的數(shù)據(jù)while(1){Led(display_date);//調(diào)用顯示函數(shù)顯示數(shù)據(jù)display_date}}
續(xù)前頁:上述數(shù)碼管動態(tài)顯示程序的另一種寫法參考程序:#include<AT89X51.H>unsignedchardatebit[]={0xfe,0xfd,0xfb,0xf7};//存儲數(shù)碼管的位選值unsignedchartvdate[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,};unsignedintdisdata;//定義要顯示的數(shù)據(jù)unsignedchardisdat[4];//存儲要顯示的四位數(shù)據(jù)voiddelay(time){unsignedchari,j;for(j=0;j<time;j++)for(i=0;i<250;i++);}display(void){ unsignedchark; disdata=1234;//顯示1234
上述數(shù)碼管動態(tài)顯示程序的另一種寫法參考程序:續(xù)前頁:
disdat[0]=disdat/1000; //取出千位 disdat[1]=disdat%1000/100;
//取出百位 disdat[2]=disdat%100/10; //取出十位 disdat[3]=disdat%10; //取出個位 for(k=0;k<4;k++)
//顯示四位數(shù)據(jù) { P0=tvdate[disdat[k]];
//送出要顯示數(shù)據(jù)的段碼 P1=datebit[k]; //P2位選 delay(10); //延時 }}main(){while(1){display();}}
這種寫法比上一種復(fù)雜,占用空間要多一些.但是使用方便,可以在此基礎(chǔ)上方便的加上比如顯示小數(shù)點(diǎn),指定某位數(shù)碼管閃爍等。課后思考:如何用軟件延時來做一個0到60秒的計數(shù)器嗎?續(xù)前頁:這種寫法比上一種復(fù)雜,占用空間要多一些.但是使6、任務(wù):4X4矩陣鍵盤識別要求:用AT89S51的并行口P2接4×4矩陣鍵盤,以P3.0-P3.3作輸入線,以P3.4-P3.7作輸出線;在每一個數(shù)碼管上顯示每個按鍵的“0-F”序號。[實(shí)驗(yàn)原理]每個按鍵有它的行值和列值,行值和列值的組合就是識別這個按鍵的編碼。矩陣的行線和列線分別通過兩并行接口和CPU通信。鍵盤處理程序的任務(wù)是:確定有無鍵按下,判斷哪一個鍵按下,鍵的功能是什么;還要消除按鍵在閉合或斷開時的抖動。兩個并行口中,一個輸出掃描碼,使按鍵逐行動態(tài)接地,另一個并行口輸入按鍵狀態(tài),由行掃描值和回饋信號共同形成鍵編碼而識別按鍵,通過軟件查表,查出該鍵的功能。6、任務(wù):4X4矩陣鍵盤識別要求:用AT89S51的并行口鍵盤識別的兩種方法逐行掃描法:(1)首先判斷有無鍵按下:令矩陣行線輸出全0信號,檢測列線狀態(tài),若有一列電平為低,則有鍵按下。(2)確定閉合鍵位置:依次將各行線置為低電平,逐行檢測各列線的電平狀態(tài),若某列為低,則該行線和列線交叉處按鍵就是閉合鍵。線反轉(zhuǎn)法:(1)令矩陣鍵盤列線輸出全0信號,行線作為輸入接口接收信號,可判斷按鍵處于哪一行。(2)令矩陣鍵盤行線輸出全0信號,列線作為輸入接口接收信號,可判斷按鍵處于哪一列。(3)將輸入信號相或后形成鍵盤的唯一鍵碼。鍵盤識別的兩種方法逐行掃描法:程序:(線反轉(zhuǎn)法)#include<reg52.h>unsignedcharcodeseg7code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsignedchark;voiddelay10ms(void)//延時程序{ unsignedchari,j; for(i=20;i>0;i--) for(j=248;j>0;j--);}voidGetch(){ unsignedcharX,Y,Z;
P2=0xff;
P2=0x0f;
//先對P2置數(shù)行掃描 if(P2!=0x0f)//判斷是否有鍵按下 {
delay10ms();//延時,軟件去干擾
if(P2!=0x0f)
//確認(rèn)按鍵按下X=P2;
{
程序:(線反轉(zhuǎn)法)續(xù)前頁:
X=P2;//保存行掃描時有鍵按下時狀態(tài) P2=0xf0;//列掃描 Y=P2;//保存列掃描時有鍵按下時狀態(tài) Z=X|Y;//取出鍵值 switch(Z)//判斷鍵值(那一個鍵按下) { case0x77:k=0;break;//對鍵值賦值 case0x7b:k=1;break; case0x7d:k=2;break; case0x7e:k=3;break; case0xb7:k=4;break; case0xbb:k=5;break; case0xbd:k=6;break; case0xbe:k=7;break; case0xd7:k=8;break; case0xdb:k=9;break; case0xdd:k=10;break; case0xde:k=11;break; case0xe7:k=12;break; case0xeb:k=13;break; 續(xù)前頁:續(xù)前頁:
case0xed:k=14;break;
case0xee:
k=15;break; } } }}voidmain(void){while(1){P2=0xff;Getch(
);P0=seg7code[k];//查表LED輸出P1=0xf0;//輸出相同的四位數(shù)據(jù)。}}
續(xù)前頁:該程序的缺陷:1、雖然線反轉(zhuǎn)法識別鍵盤的思路正確,但本程序按鍵掃描中消除按鍵抖動采用了傳統(tǒng)的延時方法,這種辦法會使CPU陷入無謂的等待,在延時的過程中CPU無法并行處理其它事件。采用定時掃描法(比如采用定時中斷每隔100ms掃描1次鍵盤),可以解決這一問題;2、如果要求實(shí)現(xiàn)“短促”按鍵和“長按”按鍵的區(qū)分,使程序能應(yīng)用在功能要求更為復(fù)雜的場合,繼續(xù)編制該程序則有繁瑣和可讀性變差的缺點(diǎn)。因此有必要采用更為便捷和高效的鍵值識別算法以實(shí)現(xiàn)本程序的功能。
該程序的缺陷:新型鍵盤識別程序基本思想:unsignedcharTrg;unsignedcharCont;voidKeyRead(void){unsignedcharReadData=P3^0xff;//1
Trg=ReadData&(ReadData^Cont);//2
Cont=ReadData;//3
}分析:(1)沒有按鍵的時候ReadData=0x00;Trg=0x00;Cont=0x00;(2)第一次按下按鍵的情況
(假設(shè)按鍵接在P3.0上面)ReadData=0x01;Trg=0x01;Cont=0x01;(3)按鍵按著不松(長按鍵)的情況ReadData=0x01;Trg=0x00;Cont=0x01;
(4)按鍵松開的情況ReadData=0x00;Trg=0x00;Cont=0x00;
Trg表示的就是觸發(fā)的意思,也就是跳變,只要有按鍵按下,Trg在對應(yīng)按鍵的位上面會置1;最關(guān)鍵的地方,Trg的值每次按下只會出現(xiàn)一次,然后立刻被清除,完全不需要人工去干預(yù)。所以按鍵功能處理程序不會重復(fù)執(zhí)行,省下了一大堆的條件判斷,所謂精粹即此??!Cont代表的是長按鍵,如果按鍵按著不放,那么Cont的值就為0x01。新型鍵盤識別程序基本思想:Trg表示的就是觸發(fā)的意思,也就應(yīng)用一:一次觸發(fā)的按鍵處理——假設(shè)為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲
#defineKEY_BEEP0x01voidKeyProc(void){if(Trg&KEY_BEEP)//如果按下的是KEY_BEEP
{Beep();//執(zhí)行蜂鳴器處理函數(shù)
}}應(yīng)用一:一次觸發(fā)的按鍵處理——假設(shè)為蜂鳴器按鍵,按一下,蜂鳴應(yīng)用二:長按鍵的處理
#defineKEY_MODE0x01//此模式按鍵也
#defineKEY_PLUS0x02//此加鍵也
voidKeyProc(void){if(Trg&KEY_MODE)//若KEY_MODE鍵按之,雖常按亦無益
{//無執(zhí)行再,必先松再按可矣
Mode++;//模式寄存器加1
}if(Cont&KEY_PLUS)//若“加”鍵按之不放
{cnt_plus++;//則計時
if(cnt_plus>100)//20ms*100=2S若計時到
{Func();//則執(zhí)行所需執(zhí)行之功能程序也
}}}應(yīng)用二:長按鍵的處理#defineKEY_MODE0x延時消抖問題?真正的單片機(jī)入門,是從學(xué)會處理多任務(wù)開始的。
加入延時消抖程序的架構(gòu)如下:volatileunsignedcharIntrcnt;voidInterruptHandle()//中斷服務(wù)程序
{Intrcnt++;}//1ms中斷1次,可變
voidmain(void){SysInit();while(1)//每20ms執(zhí)行一次大循環(huán)
{KeyRead();//將每個子程序都掃描一遍
KeyProc();Func1();Funt2();……while(1){if(Intrcnt>20)//一直在等,直到20ms時間到
{Intrcnt="0";break;}//返回主循環(huán)
}}}延時消抖問題?真正的單片機(jī)入門,是從學(xué)會處理多任務(wù)開始的。怎么判斷按鍵釋放?再增加一個按鍵釋放檢測功能,程序如下:
volatileunsignedcharTrg;volatileunsignedcharCont;volatileunsignedcharRelease;//再增加新功能!
voidKeyRead(void){unsignedcharReadData=PINB^0xff;//1讀鍵值
Trg=ReadData&(ReadData^Cont);//2得到按下觸發(fā)值
Release=(ReadData^Trg^Cont);//3得到釋放觸發(fā)值
Cont=ReadData;//4得到所有未釋放的鍵值
}怎么判斷按鍵釋放?再增加一個按鍵釋放檢測功能,程序如下:v7、任務(wù):按鍵中斷識別要求:采用中斷技術(shù),每按一下按鍵,計數(shù)器加1,并用LED顯示出來,注意只顯示2位十進(jìn)制數(shù)。原理:以上的兩個舊式按鍵識別的實(shí)驗(yàn)的程序都是采用掃描的方式來實(shí)現(xiàn)的,CPU的利用率比較低;按鍵判斷還可以用中斷方式來判斷。中斷方式可以滿足快速響應(yīng)的要求。7、任務(wù):按鍵中斷識別要求:采用中斷技術(shù),每按一下按鍵,計數(shù)程序:#include<AT89X51.H>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsignedchardispcount=0;//計數(shù)sbitgewei=P1^3;//個位選通定義sbitshiwei=P1^2;//十位選通定義voidDelay(unsignedinttc)//延時程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}voidExtInt0()interrupt0//中斷服務(wù)程序{程序:續(xù)前頁:dispcount++;//每按一次中斷按鍵,計數(shù)加一if(dispcount==100)//計數(shù)范圍0-99{dispcount=0;}}voidLED()//LED顯示函數(shù){if(dispcount>=10)//顯示兩位數(shù){shiwei=0;P0=table[dispcount/10];Delay(8);shiwei=1;gewei=0;P0=table[dispcount%10];Delay(5);gewei=1;}else//顯示一位數(shù){
續(xù)前頁:續(xù)前頁:shiwei=1;gewei=0;P0=table[dispcount];Delay(8);}}
voidmain(){TCON=0x01;
//下降沿觸發(fā)
IE=0x81;
//開總中斷和允許外部中斷
while(1)
//循環(huán)執(zhí)行{LED(
);}
//調(diào)用顯示函數(shù)}/*******************************************************************課后思考:在程序在硬件運(yùn)行過程中,有時候按一下鍵會加幾個數(shù),是因?yàn)闆]有去除按鍵干擾
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件工程教程(微課版)課件 第9章 編碼與測試
- 增強(qiáng)現(xiàn)實(shí)在教育領(lǐng)域的應(yīng)用
- 船舶非常規(guī)動力系統(tǒng)的評估與研究
- 廣州汽車維修技師個人簡歷
- 酒店餐飲服務(wù)培訓(xùn)內(nèi)容
- 腰部疾患循證預(yù)防與康復(fù)
- 餐飲業(yè)新員工安全培訓(xùn)
- 小班不抓咬安全教育
- 2025年《小壁虎借尾巴》 標(biāo)準(zhǔn)課件
- 白樺林中的奇遇:森林描寫技巧教案
- 23J916-1 住宅排氣道(一)
- 《邊緣計算與人工智能應(yīng)用開發(fā)技術(shù)》全套教學(xué)課件
- 三級安全教育試題及答案(自編完整版)
- 幼兒園大班社會《服裝的由來》課件
- 《2024年 《法學(xué)引注手冊》示例》范文
- DB43-T 2142-2021學(xué)校食堂建設(shè)與食品安全管理規(guī)范
- 2024年四川成都農(nóng)業(yè)科技中心管理人員招聘1人歷年(高頻重點(diǎn)復(fù)習(xí)提升訓(xùn)練)共500題附帶答案詳解
- DL∕T 2447-2021 水電站防水淹廠房安全檢查技術(shù)規(guī)程
- 廣東省深圳市2024年高一下學(xué)期期末調(diào)研考試英語試題含解析
- JT∕T 795-2023 事故汽車修復(fù)技術(shù)規(guī)范
- 2024年長沙職業(yè)技術(shù)學(xué)院單招職業(yè)適應(yīng)性測試題庫及答案1套
評論
0/150
提交評論