首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

51乘法口诀模拟答题器

51乘法口诀模拟答题器

* 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网
别刻意去编了,虽然方便记忆,其实哪个问题用哪句话,还是要一一对应。我主张让学生形成思维的模式和方法(当然大多数学生只希望死记,而且记不牢。悲哀中)
作为一名教师必须做名副其实的组织者和引导者,让学生灵活恰当的运用自主探究、小组合作、讨论交流等探究性学习的方式,爱上学习,学会学习,通过探究真正提高学生自身素养,培养合格人才。
返回列表