打印
[51单片机]

LCD1602模拟乘法表,4*4

[复制链接]
3101|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hyt_1992|  楼主 | 2014-1-1 17:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
描述:                                                           
* *      A--- 随机生成一道口诀; B--- 判断正误,正确则显示succeed,错误则显示error;                  
* *      C---清楚当前输入的答案;  D---显示正确答案
        (0-9)--- 有效数字输入;                                      
* *  
小女子是新手,不会做啊,求教~~~~(>_<)~~~~        

相关帖子

沙发
airwill| | 2014-1-1 21:14 | 只看该作者
除了 LCD 显示驱动外, 就是个输入串的识别和判断了, 难度不大, 鼓励一下新人.

使用特权

评论回复
板凳
hyt_1992|  楼主 | 2014-1-1 23:37 | 只看该作者
airwill 发表于 2014-1-1 21:14
除了 LCD 显示驱动外, 就是个输入串的识别和判断了, 难度不大, 鼓励一下新人. ...

******************************************************************** *                                                                  
* * 描述:                                                           
* *      A--- 模拟出题控制开关; C--- 输入正确答案;                  
* *      (0-9)--- 有效数字输入;                                      
* *      答题正确,蜂鸣器响4声。                                    
* *                                                                  * *******************************************************************/ #include < reg51.h >
#include < intrins.h >  
#define uchar unsigned char
#define uint  unsigned int  
bit  A_in=0,truer;     
sbit LCD_RS = P2^0;              
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;  
uchar code  cdis1[ ] = {"-----99Table----- "};  
uchar code  cdis2[ ] = {"TABLE:            "};
  
#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;               //比较正确         
A_in=0;                //可以重新出题   
}      
else  truer=0;            //比较错误   
}   
else  truer=0;               //比较错误      
if(truer==0)              
{      
lcd_pos(0x4B);             //清除错误答案      
lcd_wdat(0x20);   
lcd_wdat(0x3f);   
A_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==0x0a)          //A键为模拟出题开关   
{     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;     
A_in=1;                  //出题目完毕标志   }           
while(A_in==1)   {     
key_input();        
datacomp();   
}   
}  
}
这样OK?

使用特权

评论回复
地板
hyt_1992|  楼主 | 2014-1-1 23:42 | 只看该作者
airwill 发表于 2014-1-1 21:14
除了 LCD 显示驱动外, 就是个输入串的识别和判断了, 难度不大, 鼓励一下新人. ...


上面的代码配这个图有错误吗?为什么LCD1602只会亮,什么都不会显示?


使用特权

评论回复
5
airwill| | 2014-1-1 23:50 | 只看该作者
涉及时序部分, 调试还是有点麻烦的, 对这液晶手册先验证一下看吧.

使用特权

评论回复
6
hyt_1992|  楼主 | 2014-1-2 10:17 | 只看该作者
airwill 发表于 2014-1-1 23:50
涉及时序部分, 调试还是有点麻烦的, 对这液晶手册先验证一下看吧.

还是现实不出来,是图错了吗?:'(

使用特权

评论回复
7
ningling_21| | 2014-1-2 12:25 | 只看该作者
hyt_1992 发表于 2014-1-1 23:42
上面的代码配这个图有错误吗?为什么LCD1602只会亮,什么都不会显示?

lcd没接电源,当然不会显示...

使用特权

评论回复
8
as564335sa| | 2014-1-2 12:26 | 只看该作者
hyt_1992 发表于 2014-1-2 10:17
还是现实不出来,是图错了吗?

懂得网络标号的概念么,你这标号一通乱标,液晶都没接对,怎么可能显示

使用特权

评论回复
9
as564335sa| | 2014-1-2 12:45 | 只看该作者
ningling_21 发表于 2014-1-2 12:25
lcd没接电源,当然不会显示...

仿真不需要电源,单片机不接晶振都可以

使用特权

评论回复
10
as564335sa| | 2014-1-2 12:46 | 只看该作者
hyt_1992 发表于 2014-1-1 23:42
上面的代码配这个图有错误吗?为什么LCD1602只会亮,什么都不会显示?

还有你这个液晶好像不是1602

使用特权

评论回复
11
frlop| | 2014-1-2 13:36 | 只看该作者
as564335sa 发表于 2014-1-2 12:46
还有你这个液晶好像不是1602

同感,1602没这么长。

使用特权

评论回复
12
youluo235| | 2014-1-2 17:58 | 只看该作者
记得1602确实没这么长。

使用特权

评论回复
13
youluo235| | 2014-1-2 18:05 | 只看该作者
基于1602的AD多路数据采集.rar (38.71 KB)    把我这程序导进去试试。把引脚改下。可能我的引脚和你的不一样。

使用特权

评论回复
14
hyt_1992|  楼主 | 2014-1-2 18:26 | 只看该作者
youluo235 发表于 2014-1-2 18:05
把我这程序导进去试试。把引脚改下。可能我的引脚和你的不一样。

你给的是我那个图的吗?怎么感觉怪怪的

使用特权

评论回复
15
hyt_1992|  楼主 | 2014-1-2 18:28 | 只看该作者
as564335sa 发表于 2014-1-2 12:46
还有你这个液晶好像不是1602

是我画错了:dizzy:现在把图画好了,程序也改了,不过还是显示不出第二行,题目是我发帖的那个

使用特权

评论回复
16
as564335sa| | 2014-1-2 18:37 | 只看该作者
hyt_1992 发表于 2014-1-2 18:28
是我画错了现在把图画好了,程序也改了,不过还是显示不出第二行,题目是我发帖的那个 ...

lcd_pos(0x40);               //设置显示位置为第二行
这句话,第二行的起始地址是0x80+0x40

使用特权

评论回复
17
hyt_1992|  楼主 | 2014-1-2 18:50 | 只看该作者
as564335sa 发表于 2014-1-2 18:37
lcd_pos(0x40);               //设置显示位置为第二行
这句话,第二行的起始地址是0x80+0x40 ...

我按照那个图,正确的图,然后写了代码,你看看,但是我不会给按键赋值,矩阵键盘,0-9数字键输入你的答案,A键随机出题,B键判断正误,正确显示succeed,错误显示error,C键清楚当前的答案,D键输显示正确的答案。我看了一下午的书都不明白,我按照数码管显示的方法来做,但是不对。。。。。。。不知道哪里做错了


#include<reg51.h>
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define  uint unsigned int
#define DelayNOP() {_nop_();_nop_();_nop_();_nop_();}

//sbit K1=P1^4;
sbit BEEP=P2^7;
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
void beep();
bit LCD_Busy_Check();
void LCD_Initialize();
void LCD_Set_POS(uchar);
void LCD_Write_Command(uchar);
void LCD_Write_Data(uchar);

uchar code titlt_text[]={"---99 table ---"};  //标题字符串
uchar data Multiply_str[]={"               "}; //乘法口诀表达式
uchar code dis_tab[17]= {  
0x30,   //0在1602中的十六进制码  
0x31,   //1在1602中的十六进制码   
0x32,   //2在1602中的十六进制码  
0x33,   //3在1602中的十六进制码  
0x34,   //4在1602中的十六进制码   
0x35,   //5在1602中的十六进制码   
0x36,   //6在1602中的十六进制码  
0x37,   //7在1602中的十六进制码  
0x38,   //8在1602中的十六进制码   
0x39,   //9在1602中的十六进制码   
0x41,   //A在1602中的十六进制码  
0x42,   //B在1602中的十六进制码
0x43,   //C在1602中的十六进制码   
0x44,   //D在1602中的十六进制码   
0x2A,   //*在1602中的十六进制码   
};
//延时
void DelayMS(uint x)
{
  uchar i;
  while(x--)
  for(i=0;i<120;i++);
}

//显示函数,在LCD指定的行上显示字符串
void Display_string(uchar *str,uchar lineno)
{
   uchar k;
   LCD_Set_POS(lineno);
    for(k=0;k<16;k++)
   LCD_Write_Data(str[k]);
}

//随机生成被乘数与乘数,并得到乘积
void Get_random_Num_A_B()
{
   uchar a,b,c1,c2;
   a=rand()%9+1;   //被乘数
   b=rand()%9+1;   //乘数
   c1= a*b/10;
   c2=a*b%10;
    Multiply_str[1]=a+'0';
    Multiply_str[3]='*';
    Multiply_str[5]=b+'0';
    Multiply_str[7]='=';
    /*Multiply_str[9]=c1+'0';
    Multiply_str[10]=c2+'0';
  if( c1==0)  Multiply_str[9]=' ';*///当乘积的十位数(即数组中的第9位)为0时不显示
}

//1602LCD显示控制函数
bit LCD_Busy_Check()
{
  bit Result;
  LCD_RS=0;//寄存选择
   LCD_RW=1;//读的状态选择
   LCD_EN=1;//开始读
  DelayNOP();
  Result=(bit)(P0&0x80);
  LCD_EN=0;
  return Result;
}
void LCD_Write_Command(uchar cmd)
{
    while(LCD_Busy_Check());//忙等待
    LCD_RS=0;LCD_RW=0;LCD_EN=0;
    _nop_();_nop_();
    P0=cmd;DelayNOP();
    LCD_EN=1;DelayNOP();
    LCD_EN=0;

}
//写数据
void LCD_Write_Data(uchar str)
{
   while(LCD_Busy_Check());
   LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=str;DelayNOP();
   LCD_EN=1;DelayNOP();LCD_EN=0;

}

void LCD_Initialize()
{
    DelayMS(5);LCD_Write_Command(0x38);
        DelayMS(5);LCD_Write_Command(0x0c);
            DelayMS(5);LCD_Write_Command(0x06);
                DelayMS(5);LCD_Write_Command(0x01);
                    DelayMS(5);

}

void LCD_Set_POS(uchar Position)
{
        LCD_Write_Command(Position | 0x80);
}

//蜂鸣器
void beep()
{
   uchar i,j;
   for(i=0;i<180;i++)
   {
      for(j=0;j<50;j++); BEEP=!BEEP;
    }
     DelayMS(300);BEEP=0;
}


   

void keyscan()
{
        uchar temp;
        //按键0~3
        P3=0xfe;                  
        temp=P3;
        temp=temp&0xf0;
        if(temp!=0xf0)
        {
                DelayMS(10);
                temp=P3;
                temp=temp&0xf0;
                if(temp!=0xf0)
                {
                        temp=P3;
                        switch(temp)
                        {
                                case 0xee:
                                                P0=dis_tab[0];           //显示数字
                                                break;
                                case 0xde:
                                                P0=dis_tab[1];
                                                break;
                                case 0xbe:
                                                P0=dis_tab[2];
                                                break;
                                case 0x7e:
                                                P0=dis_tab[3];
                                                break;
                        }
                        while(temp!=0xf0)   //等待按键释放
                        {
                                temp=P3;
                                temp=temp&0xf0;
                        }
                }
        }
        //按键4~7
        P3=0xfd;                               
        temp=P3;
        temp=temp&0xf0;
        if(temp!=0xf0)
        {
                DelayMS(10);
                temp=P3;
                temp=temp&0xf0;
                if(temp!=0xf0)
                {
                        temp=P3;
                        switch(temp)
                        {
                                case 0xed:
                                                P0=dis_tab[4];           //显示数字
                                                break;
                                case 0xdd:
                                                P0=dis_tab[5];
                                                break;
                                case 0xbd:
                                                P0=dis_tab[6];
                                                break;
                                case 0x7d:
                                                P0=dis_tab[7];
                                                break;
                        }
                        while(temp!=0xf0)   //等待按键释放
                        {
                                temp=P3;
                                temp=temp&0xf0;
                        }
                }
        }
        //按键8~b
        P3=0xfb;
        temp=P3;
        temp=temp&0xf0;
        if(temp!=0xf0)
        {
                DelayMS(10);
                temp=P3;
                temp=temp&0xf0;
                if(temp!=0xf0)
                {
                        temp=P3;
                        switch(temp)
                        {
                                case 0xeb:
                                                P0=dis_tab[8];           //显示数字
                                                break;
                                case 0xdb:
                                                P0=dis_tab[9];
                                                break;
                                case 0xbb:
                                                P0=dis_tab[10];
                                                Get_random_Num_A_B();
                                                break;
                                case 0x7b:
                                                P0=dis_tab[11];
                                                break;
                        }
                        while(temp!=0xf0)   //等待按键释放
                        {
                                temp=P3;
                                temp=temp&0xf0;
                        }
                }
        }
        //按键c~f
        P3=0xf7;
        temp=P3;
        temp=temp&0xf0;
        if(temp!=0xf0)
        {
                DelayMS(10);
                temp=P3;
                temp=temp&0xf0;
                if(temp!=0xf0)
                {
                        temp=P3;
                        switch(temp)
                        {
                                case 0xe7:
                                                P0=dis_tab[12];           //显示数字
                                                break;
                                case 0xd7:
                                                P0=dis_tab[13];
                                                break;
                                case 0xb7:
                                                P0=dis_tab[14];
                                                break;
                                case 0x77:
                                                P0=dis_tab[15];
                                                break;
                        }
                        while(temp!=0xf0)   //等待按键释放
                        {
                                temp=P3;
                                temp=temp&0xf0;
                        }
                }
        }

}

使用特权

评论回复
18
lirunze| | 2014-1-2 19:06 | 只看该作者
路过 啊

使用特权

评论回复
19
as564335sa| | 2014-1-2 19:59 | 只看该作者
hyt_1992 发表于 2014-1-2 18:50
我按照那个图,正确的图,然后写了代码,你看看,但是我不会给按键赋值,矩阵键盘,0-9数字键输入你的答 ...

P0=dis_tab[12];这是什么语句,把这东西都直接搬过来了……看来你不懂用1602显示字符数字……

使用特权

评论回复
20
hyt_1992|  楼主 | 2014-1-2 21:57 | 只看该作者
as564335sa 发表于 2014-1-2 19:59
P0=dis_tab[12];这是什么语句,把这东西都直接搬过来了……看来你不懂用1602显示字符数字…… ...

确实不会,因为我才刚学,而且没人教

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

8

帖子

0

粉丝