基于51单片机设计的乘法口诀模拟答题器
时间:10-24
来源:互联网
点击:
/*******************************************************************
* LCD1602显示 **Copyright(C) JAS All Rights Reserved **此程序仅用于学习与参考,引用请注明版权和作者信息! ** ********************************************************************** ** 描述: ** F--- 模拟出题控制开关; C--- 输入正确答案; ** (0-9)--- 有效数字输入; ** 答题正确,蜂鸣器响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; //蜂鸣器驱动线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; //关闭蜂鸣器delay(250); //延时 }/*************************************************************//* *//*检查LCD忙状态 *//*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据 *//* *//*************************************************************/ bit lcd_busy(){ bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;delayNOP();result = (bit)(P00x80);LCD_EN = 0;return(result); }/*******************************************************************//* *//*写指令数据到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; }/*******************************************************************//* *//*写显示数据到LCD *//*RS=H,RW=L,E=高脉冲,D0-D7=数据。 *//* *//*******************************************************************/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初始化设定 *//* *//*************************************************************/void lcd_init(){ delay(15); lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据delay(5);lcd_wcmd(0x38); delay(5);lcd_wcmd(0x38); delay(5);lcd_wcmd(0x0c); //显示开,关光标delay(5);lcd_wcmd(0x06); //移动光标delay(5);lcd_wcmd(0x01); //清除LCD的显示内容delay(5);}/*************************************************************//* *//* 设定显示位置 *//* *//*************************************************************/void lcd_pos(uchar pos){ lcd_wcmd(pos | 0x80); //数据指针=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();}}/**********************************************************随机出题函数**********************************************************/void rubric(){uchar num1,num2,temp1;TR1=0;temp1=TL1; //取T1当前的计数值temp1=~temp1; //取反得到对应的题号num2=temp1/9; //就题目分成9组num2++; //将组号0~8转换为被乘数1~9testdata[3]=num2+0x30; //保存被乘数num1=temp1%9; num1++; //将组号0~8转换为乘数1~9。testdata[2]=num1+0x30; //保存乘数temp1=num2*num1; //计算乘积testdata[1]=temp1/10+0x30; //乘积的高位testdata[0]=temp1%10+0x30; //乘积的低位TR1=1; } /**********************************************************键入正确答案函数**********************************************************/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]);}/**********************************************************键入答案函数**********************************************************/void key_input(){ if(testdata[1]==0x30) //先判断十位数是否为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; //转换为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; //转换为ASCII码in_data[0]=key_buf; //输入乘积低位lcd_pos(0x4c);lcd_wdat(in_data[0]); //显示乘积低位key_num=0;} }}/**********************************************************数据比较函数**********************************************************/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; //禁止重新出题}}/**********************************************************主函数**********************************************************/main(){uchar m;lcd_init(); //初始化LCD lcd_pos(0x00); //设置显示位置为第一行for(m=0;m16;m++)lcd_wdat(cdis1-);lcd_pos(0x40); //设置显示位置为第二行 for(m=0;m16;m++)lcd_wdat(cdis2-);TMOD=0x21; //将T1设置为8位自动重装工作方式。TH1=175; //对T1定时常数进行预置。TL1=175;TR1=1; //启动T1。while(1) {keydown();if(key_buf==0x0f) //F 键为模拟出题开关{rubric();lcd_pos(0x47); lcd_wdat(testdata[3]); //显示被乘数lcd_pos(0x49); lcd_wdat(testdata[2]); //显示乘数lcd_pos(0x4B);lcd_wdat(0x20);lcd_wdat(0x3f); //显示 ?key_buf=0x00;F_in=1; //出题目完毕标志}while(F_in==1){key_input();datacomp();}} }/*********************************************************/
- 关于RTX51 TINY的分析与探讨(05-30)
- 浅析8051模块化编程技巧(05-28)
- 基于DSP和单片机通信的液晶显示设计方案(07-20)
- 锁相环控制及初始化简析(08-27)
- 基于MSP430自动胀管控制器的研究(09-07)
- 嵌入式C实现延时程序的不同变量的区别(03-01)