- UID
- 792415
- 性别
- 男
|
* 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 int
bit 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; i<13; i++) {}
}
}
/*************************************************************/
/* */
/* 蜂鸣器响一声 */
/* */
/*************************************************************/
void beep()
{
unsigned char i;
for (i=0;i<180;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)(P0&0x80);
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=temp&0x0F;
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;
else
key=16;
P1=0xF0; //高四位输入
delay(1);
temp=P1; //读P1口
temp=temp&0xF0;
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;
else
key=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~9
testdata[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_buf<10)
{
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_buf<10)
{
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;m<16;m++)
lcd_wdat(cdis1
-);
lcd_pos(0x40); //设置显示位置为第二行
for(m=0;m<16;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();
}
}
}
/本文转自:IC网 |
|