/*******************************************************************
* LCD1602顯示 **【版權(quán)】Copyright(C) JAS All Rights Reserved **【聲明】此程序僅用于學(xué)習(xí)與參考,引用請注明版權(quán)和作者信息! ** ********************************************************************** ** 描述: ** F--- 模擬出題控制開關(guān); C--- 輸入正確答案; ** (0-9)--- 有效數(shù)字輸入; ** 答題正確,蜂鳴器響4聲。 ** ********************************************************************/#include reg51.h >#include intrins.h >#define uchar unsigned char#define uint unsigned intbit F_in=0,truer; sbit LCD_RS = P2^0; sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;uchar code cdis1[ ] = {" MULTIPLICATION "}; uchar code cdis2[ ] = {"TABLE: 0*0=00 "};#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};sbit BEEP = P3^7; //蜂鳴器驅(qū)動線uchar key_buf; //顯示緩存uchar temp;uchar key,key_num=0; //鍵順序嗎uchar data testdata[] = {0x00,0x00,0x00,0x00};uchar data in_data[] = {0x01,0x02};uchar shift ;/**********************************************************延時子程序**********************************************************/void delay(uint ms) {uchar t;while(ms--){ for(t = 0; t 120; t++);}}/*************************************************************//* *//* 延時 x*0.14ms *//* *//*************************************************************/void delay0(uchar x) {unsigned char i;while(x--){for (i = 0; i13; i++) {}}}/*************************************************************//* *//* 蜂鳴器響一聲 *//* *//*************************************************************/void beep(){unsigned char i;for (i=0;i180;i++){delay0(6);BEEP=!BEEP; //BEEP取反} BEEP=1; //關(guān)閉蜂鳴器delay(250); //延時 }/*************************************************************//* *//*檢查LCD忙狀態(tài) *//*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數(shù)據(jù) *//* *//*************************************************************/ bit lcd_busy(){ bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;delayNOP();result = (bit)(P00x80);LCD_EN = 0;return(result); }/*******************************************************************//* *//*寫指令數(shù)據(jù)到LCD *//*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 *//* *//*******************************************************************/void lcd_wcmd(uchar cmd){ while(lcd_busy());LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_(); P0 = cmd;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0; }/*******************************************************************//* *//*寫顯示數(shù)據(jù)到LCD *//*RS=H,RW=L,E=高脈沖,D0-D7=數(shù)據(jù)。 *//* *//*******************************************************************/void lcd_wdat(uchar dat){ while(lcd_busy());LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0; }/*************************************************************//* *//* LCD初始化設(shè)定 *//* *//*************************************************************/void lcd_init(){ delay(15); lcd_wcmd(0x38); //16*2顯示,5*7點陣,8位數(shù)據(jù)delay(5);lcd_wcmd(0x38); delay(5);lcd_wcmd(0x38); delay(5);lcd_wcmd(0x0c); //顯示開,關(guān)光標(biāo)delay(5);lcd_wcmd(0x06); //移動光標(biāo)delay(5);lcd_wcmd(0x01); //清除LCD的顯示內(nèi)容delay(5);}/*************************************************************//* *//* 設(shè)定顯示位置 *//* *//*************************************************************/void lcd_pos(uchar pos){ lcd_wcmd(pos | 0x80); //數(shù)據(jù)指針=80+地址變量}/*************************************************************鍵掃描子程序 *************************************************************/void keyscan(void){ P1=0x0F; //低四位輸入 delay(1);temp=P1; //讀P1口 temp=temp0x0F;temp=~(temp|0xF0);if(temp==1)key=0;else if(temp==2)key=1;else if(temp==4)key=2;else if(temp==8)key=3;elsekey=16;P1=0xF0; //高四位輸入delay(1);temp=P1; //讀P1口 temp=temp0xF0;temp=~((temp>>4)|0xF0);if(temp==1)key=key+0;else if(temp==2)key=key+4;else if(temp==4)key=key+8;else if(temp==8)key=key+12;elsekey=16;key_buf = key; //鍵值入顯示緩存key_buf = key_buf 0x0f;}/*************************************************************判斷鍵是否按下 *************************************************************/void keydown(void){ P1=0xF0;while(P1==0xf0);{keyscan();beep();}}/**********************************************************隨機(jī)出題函數(shù)**********************************************************/void rubric(){uchar num1,num2,temp1;TR1=0;temp1=TL1; //取T1當(dāng)前的計數(shù)值temp1=~temp1; //取反得到對應(yīng)的題號num2=temp1/9; //就題目分成9組num2++; //將組號0~8轉(zhuǎn)換為被乘數(shù)1~9testdata[3]=num2+0x30; //保存被乘數(shù)num1=temp1%9; num1++; //將組號0~8轉(zhuǎn)換為乘數(shù)1~9。testdata[2]=num1+0x30; //保存乘數(shù)temp1=num2*num1; //計算乘積testdata[1]=temp1/10+0x30; //乘積的高位testdata[0]=temp1%10+0x30; //乘積的低位TR1=1; } /**********************************************************鍵入正確答案函數(shù)**********************************************************/void right(){if(testdata[1]==0x30){testdata[1]=0x20;}lcd_pos(0x4b);in_data[1]=testdata[1];in_data[0]=testdata[0];lcd_wdat(in_data[1]);lcd_wdat(in_data[0]);}/**********************************************************鍵入答案函數(shù)**********************************************************/void key_input(){ if(testdata[1]==0x30) //先判斷十位數(shù)是否為0{ in_data[1]=0x30; key_num=1;}else{keydown();if(key_buf==0x0c) //C 鍵顯示正確答案{right();key_num=0;}if(key_buf10){ key_buf=key_buf+0x30; //轉(zhuǎn)換為ASCII碼in_data[1]=key_buf; //輸入乘積高位lcd_pos(0x4b);lcd_wdat(in_data[1]); //顯示乘積高位lcd_wdat(0x20);key_num=1;}}if(key_num==1){keydown();if(key_buf==0x0c) //C 鍵顯示正確答案{right();key_num=0;}if(key_buf10){ key_buf=key_buf+0x30; //轉(zhuǎn)換為ASCII碼in_data[0]=key_buf; //輸入乘積低位lcd_pos(0x4c);lcd_wdat(in_data[0]); //顯示乘積低位key_num=0;} }}/**********************************************************數(shù)據(jù)比較函數(shù)**********************************************************/void datacomp(){if(testdata[1]-in_data[1]==0) //比較乘積高位{if(testdata[0]-in_data[0]==0) //比較乘積低位{beep(); //計算正確蜂鳴器響3聲beep();beep();truer=1; //比較正確F_in=0; //可以重新出題}else truer=0; //比較錯誤}else truer=0; //比較錯誤if(truer==0) {lcd_pos(0x4B); //清除錯誤答案lcd_wdat(0x20);lcd_wdat(0x3f);F_in=1; //禁止重新出題}}/**********************************************************主函數(shù)**********************************************************/main(){uchar m;lcd_init(); //初始化LCD lcd_pos(0x00); //設(shè)置顯示位置為第一行for(m=0;m16;m++)lcd_wdat(cdis1-);lcd_pos(0x40); //設(shè)置顯示位置為第二行 for(m=0;m16;m++)lcd_wdat(cdis2-);TMOD=0x21; //將T1設(shè)置為8位自動重裝工作方式。TH1=175; //對T1定時常數(shù)進(jìn)行預(yù)置。TL1=175;TR1=1; //啟動T1。while(1) {keydown();if(key_buf==0x0f) //F 鍵為模擬出題開關(guān){rubric();lcd_pos(0x47); lcd_wdat(testdata[3]); //顯示被乘數(shù)lcd_pos(0x49); lcd_wdat(testdata[2]); //顯示乘數(shù)lcd_pos(0x4B);lcd_wdat(0x20);lcd_wdat(0x3f); //顯示 ?key_buf=0x00;F_in=1; //出題目完畢標(biāo)志}while(F_in==1){key_input();datacomp();}} }/*********************************************************/
評論