基于51单片机设计的乘法口诀模拟答题器

发布者:BlissfulCharm最新更新时间:2012-10-24 来源: 21ic 关键字: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();
  }
   } 
}

/*********************************************************/
关键字:51单片机  乘法口诀  模拟答题器 引用地址:基于51单片机设计的乘法口诀模拟答题器

上一篇:基于51单片机的ds18B20温度程序
下一篇:基于STC12C5A32S2单片机设计的交通灯

推荐阅读最新更新时间:2024-03-16 13:11

基于89c51单片机的数字电压表设计
  0引言   数字电压表是诸多数字化仪表的核心与基础,电压表的数字化是将连续的模拟量如直流电压转换成不连续的离散的数字形式并加以显示,这有别于传统的以指针加刻度盘进行读数的方法,避免了读数的视差和视觉疲劳。目前数字万用表的内部核心部件是A/D转换器,转换器的精度很大程度上影响着数字万用表的准确度,本文AID转换器采用ADC0809对输入模拟信号进行转换,控制核心AT89c51N对转换的结果进行运算和处理,最后驱动输出装置显示数字电压信号。   1数字电压表硬件电路设计   硬件电路设计主要包括:89C51单片机系统,~D转换电路,显示电路。测量最大电压为5V,显示最大值为5.00V.图l是数字电压表硬件电路原理图。   
[单片机]
基于89c<font color='red'>51单片机</font>的数字电压表设计
51单片机控制步进电机和直流减速电机
51单片机控制步进电机和直流减速电机。 用这个电路图可以实现多个电机的联动,易于写程序控制。 使用多个L298驱动芯片,安全高效。 以下是正文: L298驱动芯片介绍: L298工作电压高达46V 总DC电流达4A 低饱和电压 L298具有过温保护功能 file:///C:/Users/HUAWEI/AppData/Local/Temp/msohtmlclip1/01/clip_image005.png 接下来看看protues的仿真图。 按图示接法,驱动芯片的in口和out口电平状态完全对应一致。但不会有过大电流流过单片机。因此安全可靠。 驱动方法: 直流电机,直接电机的连线上,给予一高一低的两个电平即
[单片机]
<font color='red'>51单片机</font>控制步进电机和直流减速电机
基于51单片机的定时
在这里,小编带你一起 从零开始学51 单片机 定时器。基于单片机的定时器 电路 原理图如下所示:   我们学单片机是首先学的就是 LED 闪烁,那是用延时程序做的,现在回想起来,这样做不很恰当,为什么呢?我们的主程序做了灯的闪烁,就不能再干其它的事了,难道单片机只能这样工作吗?当然不是,我们能用定时器来实现灯的闪烁的功能。   例 1:查询方式   ORG 0000H   AJMP START   ORG 30H   START:   MOV P1,#0FFH ;关所 灯   MOV TMOD,#00000001B ;定时/计数器 0 工作于方式 1   MOV TH0,#15H  
[单片机]
基于<font color='red'>51单片机</font>的定时<font color='red'>器</font>
51单片机控制12864液晶显示屏显示图片
#include reg52.h #include intrins.h #define unchar unsigned char #define BOOL bit sbit rs = P2^5; sbit rw = P2^6; sbit ep = P2^4; BOOL lcd_bz(); void ddd(); void tupian(unsigned char *tab); code unsigned int MaskTab ={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, 0x0100,0x02
[单片机]
AT89C2051单片机在无线门铃报警的应用
  门铃在中国古代较少听说,有钱的大户人家是在大门上装有装饰性的门环,叫门的人可用门环拍击环下的门钉发出较大的响声,有现代"门铃"的作用。   当今,无线门铃与无线 门铃 报警器比比皆是,但同时按照门铃与报警器还是给家庭带来了些许麻烦。而无线门铃报警器就是将门铃与报警器集于一身。它的体积小,性价比高等特点得到了人们的好评。而现在市场上许多产品的遥控器与接收器件的数据传输都是采用非编码式,因而互相的影响较大,一旦一个院子两户人家同时安装时,就很容易出现错误响应。而基于单片机的无线门铃报警器,将发射器发送的数据进行编码,只有收到与接收机相配套的遥控器发射出的信号时,接收机才会做出反应。从而在降低成本的同时达到了方便实用的目的。  
[单片机]
AT89C20<font color='red'>51单片机</font>在无线门铃报警<font color='red'>器</font>的应用
51单片机」收发一体超声波测距模块分析+代码
我用的超声波型号是US-020,四个接口的超声波用法基本相同。 一、概述 US-020超声波模块测距范围:2cm~7m 供电电压5V,静态功耗低于3mA 二、实物图 尺寸:45mm*20mm*1.6mm 三、接口 1.VCC 电源,直流5V 2.Trig 向此管脚输入10us以上高电平,可触发模块测距 3.Echo 测距结束时会输出高电平,电平时长为超声波信号往返时间之和 4.GND 接地 四、测距工作原理 只要在Trig管脚输入10us以上高电平,系统会自动发出8个40KHz的超声波脉冲,然后检测回波信号。检测到后通过Echo管脚输出。 计算方式:(Echo高电平时间*340m/s)/2 :利用计数器
[单片机]
「<font color='red'>51单片机</font>」收发一体超声波测距模块分析+代码
51单片机的工作寄存R0~R7位于内部RAM什么位置
51单片机的工作寄存器一共有32个,为RAM中的00H--1FH单元,分为4组,分别是 0组:00H--07H单元、 1组:08H--0FH单元、 2组:10H--17H单元、 3组:18H--1FH单元, 每组的8个单元分别对应R0--R7。这四组中只有一组是当前工作寄存器,程序中使用的就是当前工作寄存器中的8个单元。当前工作寄存器是由程序状态字PSW中的第三第四位决定的。在PSW中,的PSW4、PSW3两位组合的00、01、10、11四个状态,分别指定工作寄存器的0组、1组、2组、3组,只需要用指令改变PSW的这两位状态,就可以改变当前工作寄存器组。这样,实际上就是有32个工作寄存器可以选用。
[单片机]
以80C51单片机为例讲述单片机如何运行
前言 要想理解单片机是如何运行程序的,首先需要了解单片机的组成。本文以80C51单片机为例,给大家讲一讲程序在单片机中是如何运行的。 单片机的组成 8051单片机的内部硬件结构包括: 中央处理器CPU:它是单片机内部的核心部件,决定了单片机的主要功能特性,由运算器和控制器两大部分组成。 存储器:8051单片机在系统结构上采用了哈佛型,将程序和数据分别存放在两个存储器内,一个称为程序存储器,另一个为数据存储器在物理结构上分程序存储器和数据存储器,有四个物理上相互独立的存储空间,即片内ROM和片外ROM,片内RAM和片外RAM。 定时器/计数器(T/C):8051单片机内有两个16位的定时器/计数器,每个T/C既可以设置成计数方式
[单片机]
以80C<font color='red'>51单片机</font>为例讲述单片机如何运行
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved