找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2571|回复: 0
打印 上一主题 下一主题
收起左侧

单片机计算器源程序 1602液晶显示

[复制链接]
跳转到指定楼层
楼主
ID:270093 发表于 2018-4-9 21:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可以用语音来实现加减乘除之类计算 并显示到1602上面

单片机源程序如下:
  1. /*
  2. 接盘按键说明:
  3. --------------------------------------------------
  4.             |  1  |  2  |  3  |  +  |  
  5.             - - - - - - - - - - - - -
  6.             |  4  |  5  |  6  |  -  |
  7.             - - - - - - - - - - - - -
  8.             |  7  |  8  |  9  |  *  |
  9.             - - - - - - - - - - - - -
  10.                               | C   |  0  |  =  |  /  |
  11. --------------------------------------------------*/
  12. #include<reg51.h>
  13. #define uint unsigned int
  14. #define uchar unsigned char
  15. #define XTAL 12000000 //CPU晶振频率
  16. #define baudrate 9600 //通信波特率
  17. //--------LCD1602-------------------
  18. //P00-07==== D0-7
  19. sbit rs=P1^5;        //指令or数据   2.6
  20. sbit wela=P1^4;      //读or写   2.5
  21. sbit lcden=P1^6;         //使能信号    2.7
  22. sbit feng=P1^0;    //蜂鸣器
  23. //--------LCD1602-------------------
  24. //--------KEY-----------------------
  25. //P1口
  26. //--------KEY-----------------------
  27. uchar code table[]= "                ";

  28. unsigned char data_a,data_b; //计算结果
  29. unsigned char data_c;       
  30. unsigned char num1;  //第一个数
  31. unsigned char num2;  //第二个数
  32. unsigned char count;  //一个起识别作用的变量
  33. unsigned char yusuanfu; //加减乘除等运算符

  34. uchar dispaly[10];         //显示缓冲

  35. //************************************************************************/
  36. // 描述: 延时t us函数
  37. //************************************************************************/
  38. void LCD_Delay_us(unsigned int t)
  39. {
  40.         while(t--);           //t=0,退出
  41. }
  42. //************************************************************************/
  43. // 描述: 延时t ms函数
  44. //************************************************************************/
  45. void LCD_Delay_ms(unsigned int t)
  46. {
  47.         unsigned int i,j;
  48.         for(i=0;i<t;i++)                       //执行t次循环
  49.         for(j=0;j<113;j++)                     //执行113次循环
  50.         ;
  51. }
  52. //************************************************************************/
  53. // 描述: 1602液晶写指令
  54. //************************************************************************/
  55. void write_com(uchar com)            //1602液晶写指令
  56. {
  57.         rs=0;                       //写指令
  58.         lcden=0;                    //使能1602
  59.         P2=com;                     //写入指令com
  60.         LCD_Delay_ms(1);            //延时1ms
  61.         lcden=1;                    //使能1602
  62.         LCD_Delay_ms(2);            //延时2ms  
  63.         lcden=0;                        //使能1602
  64. }
  65. //************************************************************************/
  66. // 描述:1602液晶写数据
  67. //************************************************************************/
  68. void write_date(uchar date) //1602液晶写数据
  69. {
  70.         rs=1;                        //写数据
  71.         lcden=0;                     //使能1602
  72.         P2=date;                     //写入数据date
  73.         LCD_Delay_ms(1);             //延时1ms
  74.         lcden=1;                     //使能1602
  75.         LCD_Delay_ms(2);             //延时2ms
  76.         lcden=0;                         //使能1602
  77. }
  78. //************************************************************************/
  79. // 描述:指定x,y写入字符函数
  80. //************************************************************************/
  81. void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
  82. {     
  83.          if (y == 0){write_com(0x80 + x);}   //第一行  
  84.          else{write_com(0xc0 + x);}          //第二行
  85.          write_date( Data);                  //写入数据
  86. }
  87. //指定x,y写入字符串函数
  88. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
  89. {     
  90. if (y == 0){write_com(0x80 + x);}                 //第一行
  91. else{write_com(0xC0 + x);}                        //第二行
  92. while (*s)                                        //
  93.         {write_date( *s); s++;}                      //写入数据
  94. }
  95. //************************************************************************/
  96. // 描述:初始化液晶,及画面初始化
  97. //************************************************************************/
  98. void init_lcd(void)            //初始化液晶,及画面初始化
  99. {
  100.         wela=0;                      //写液晶
  101.         lcden=0;                     //使能1602
  102.         write_com(0x38);             //8 位总线,双行显示,5X7 的点阵字符
  103.         LCD_Delay_us(100);           //延时100us
  104.         write_com(0x0c);             //开显示,无光标,光标不闪烁
  105.         write_com(0x06);             //光标右移动
  106.         write_com(0x01);             //清屏
  107.         write_com(0x80);             //DDRAM 地址归0
  108. }
  109. //************************************************************************/
  110. // 描述: 反转法键盘扫描
  111. //************************************************************************/
  112. short keycheckdown()                                /* 反转法键盘扫描 */
  113. {

  114.         short temp1,temp2,temp,a=0xff;
  115.         P1=0xf0;                                                /* 输入行值(或列值) */
  116.         LCD_Delay_ms(20);                                /* 延时 */
  117.         temp1=P1;                                                /* 读列值(或行值) */
  118.         P1=0xff;
  119.         LCD_Delay_ms(20);                                /* 延时 */
  120.         P1=0x0f;                                                /* 输入列值(或行值) */
  121.         LCD_Delay_ms(20);                                /* 延时 */       
  122.         temp2=P1;                                                /* 读行值(或列值) */
  123.         P1=0xff;
  124.         temp=(temp1&0xf0)|(temp2&0xf);        /* 将两次读入数据组合 */
  125.         switch(temp)                                        /* 通过读入数据组合判断按键位置 */
  126.         {


  127.                 case 0x77 :a=0x0d;break; //  按键/   77
  128.                 case 0xb7 :a=0x0e; break;// 按键=          7b
  129.                 case 0xd7 :a=0;           break;// 按键0    7d
  130.                 case 0xe7 :a=0x0f; break;// 按键CE   7e

  131.                 case 0x7b :a=0x0c;break;//         按键*    b7
  132.                 case 0xbb :a=0x9;break; //  按键9    bb
  133.                 case 0xdb :a=0x8;break; //  按键8    bd
  134.                 case 0xeb :a=0x7;break; //         按键7    be

  135.                 case 0x7d :a=0x0b;break;//  按键-    d7
  136.                 case 0xbd :a=0x6;break; //         按键6    db
  137.                 case 0xdd :a=0x5;break; //         按键5    dd
  138.                 case 0xed :a=0x4;break; //         按键4    de

  139.                 case 0x7e :a=0x0a; break;// 按键+    e7
  140.                 case 0xbe :a=3;break;//  按键3      eb
  141.                 case 0xde :a=2;break;//  按键2      ed
  142.                 case 0xee :a=1;break;//  按键1      ee

  143.                 default :a=0xff;
  144.         }
  145.         return a;                                                /* 返回按键值 */
  146. }
  147. void display_a() //显示运算结果
  148. {
  149.         dispaly[3]=data_a%10000/1000;    //千
  150.         dispaly[2]=data_a%1000/100;      //百
  151.         dispaly[1]=data_a%100/10;        //十
  152.         dispaly[0]=data_a%10;            //个

  153.         write_com(0x80+7);               //显示运算结果在7的位置上
  154.         if(data_a>999){        write_date('0'+dispaly[3]);}      //显示千位
  155.         if(data_a>99){        write_date('0'+dispaly[2]);}                 //显示百位
  156.         if(data_a>9){        write_date('0'+dispaly[1]);}     //显示十位
  157.                               write_date('0'+dispaly[0]);      //显示个位
  158. }

  159. void display_num1()   //显示数据a
  160. {
  161.   dispaly[3]=num1%10000/1000;    //千
  162.         dispaly[2]=num1%1000/100;      //百
  163.         dispaly[1]=num1%100/10;        //十
  164.         dispaly[0]=num1%10;            //个

  165.         write_com(0x80+0);               //显示第一个数在0的位置上
  166.         if(num1>999){        write_date('0'+dispaly[3]);}      //显示千位
  167.         if(num1>99){        write_date('0'+dispaly[2]);}                 //显示百位
  168.         if(num1>9){        write_date('0'+dispaly[1]);}     //显示十位
  169.                               write_date('0'+dispaly[0]);      //显示个位
  170. }
  171. void display_yusuanfu()   //显示运算符
  172. {
  173.          switch(yusuanfu)
  174.             {
  175.                 case 219: write_com(0x80+1); write_date('+'); break;      //写屏“+?     在1的位置上
  176.                 case 221: write_com(0x80+1); write_date('-');  break;     //写屏“-”     在1的位置上
  177.                 case 136: write_com(0x80+1); write_date('*');  break;     //写屏“*”     在1的位置上
  178.                 case 223: write_com(0x80+1); write_date('/');  break;     //写屏“/”     在1的位置上
  179.                                                 }
  180. }
  181. void display_num2()    //显示第二个数
  182. {
  183.         dispaly[3]=num2%10000/1000;    //千
  184.         dispaly[2]=num2%1000/100;      //百
  185.         dispaly[1]=num2%100/10;        //十
  186.         dispaly[0]=num2%10;            //个

  187.         write_com(0x80+2);               //显示第二个数在2的位置上
  188.         if(num1>999){        write_date('0'+dispaly[3]);}      //显示千位
  189.         if(num1>99){        write_date('0'+dispaly[2]);}                 //显示百位
  190.         if(num1>9){        write_date('0'+dispaly[1]);}     //显示十位
  191.                               write_date('0'+dispaly[0]);      //显示个位
  192. }
  193.        

  194. void display_c(x)  //此函数在此工程中没有用到,仅提供一个思路
  195. {

  196.         if(data_c<100000000&&data_c>-1)//溢出时显示错误
  197.         {       

  198.                 dispaly[8]=data_c%1000000000/100000000;            //万万
  199.                 dispaly[7]=data_c%100000000/10000000;            //千万
  200.                 dispaly[6]=data_c%10000000/1000000;                    //百万
  201.                 dispaly[5]=data_c%1000000/100000;                    //十万
  202.                 dispaly[4]=data_c%100000/10000;                            //万
  203.                 dispaly[3]=data_c%10000/1000;                            //千
  204.                 dispaly[2]=data_c%1000/100;                              //百
  205.                 dispaly[1]=data_c%100/10;                                //十
  206.                 dispaly[0]=data_c%10;                                    //个
  207.                 write_com(0x80+6+0x40); //第一行
  208.                 if(x==4)
  209.                 {   
  210.                         if(data_c>99999999)        {        write_date('0'+dispaly[8]);}    //显示万万
  211.                         if(data_c>9999999)        {        write_date('0'+dispaly[7]);}   //千万
  212.                         if(data_c>999999)        {        write_date('0'+dispaly[6]);}    //百万
  213.                         if(data_c>99999)        {        write_date('0'+dispaly[5]);}    //十万
  214.                         if(data_b!=0)                {
  215.                                                                         write_date('0'+dispaly[4]);    //万
  216.                                                                         write_date('.');
  217.                                                                         write_date('0'+dispaly[3]);    //千
  218.                                                                         write_date('0'+dispaly[2]);    //百
  219.                                                                         write_date('0'+dispaly[1]);    //十
  220.                                                                         write_date('0'+dispaly[0]);    //个
  221.                                                                 }
  222.                 }
  223.         else{
  224.                 if(data_c>99999999)        {        write_date('0'+dispaly[8]);}    //显示万万
  225.                 if(data_c>9999999)        {        write_date('0'+dispaly[7]);}    //千万
  226.                 if(data_c>999999)        {        write_date('0'+dispaly[6]);}    //百万
  227.                 if(data_c>99999)        {        write_date('0'+dispaly[5]);}    //十万
  228.                 if(data_c>9999)                {        write_date('0'+dispaly[4]);}    //万
  229.                 if(data_c>999)                {        write_date('0'+dispaly[3]);}    //千
  230.                 if(data_c>99)                {        write_date('0'+dispaly[2]);}    //百
  231.                 if(data_c>9)                {        write_date('0'+dispaly[1]);}    //十
  232.                                                                 write_date('0'+dispaly[0]);    //个
  233.                 }
  234.         }
  235.         else  //溢出时显示错误
  236.         {
  237.                 write_com(0x80+11+0x40); //第一行
  238.                 write_date('E');         //显示 E
  239.                 write_date('r');         //显示R
  240.                 write_date('r');                 //显示R
  241.                 write_date('o');                 //显示O
  242.                 write_date('r');                 //显示E
  243.         }
  244. }
  245. //加减乘除运算
  246. void eql(uchar x)  //此函数在此工程中没有用到  提供一个思路
  247. {
  248.         switch(x)                /*功能键选择*/
  249.                         {   
  250.                                 case 1:data_c=data_a+data_b;break;                   //加  /* + S=1 */ /* 数值转换函数 */                                                                       
  251.                                 case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///减
  252.                        else{data_c=data_b-data_a;W_lcd(5,1,'-');} //负数符号
  253.                                            break;           
  254.                                 case 3:data_c=(data_a*data_b);break;                  /* * S=3 *///乘
  255.                                 case 4:if(data_b==0){LCD_Write_String(0,1,"Error !         ");}else{data_c=(data_a*10000)/data_b;}break;                  /* / S=4 *///除//溢出时显示错误
  256.                                 case 0:break;
  257.                         }          

  258. }
  259. void UART_Init(void)  //  串口初始化
  260. {
  261.    SCON = 0x50;     
  262.    TMOD = 0x20;     
  263.    TH1  = 0xfd;     
  264.    TL1  = 0xfd;
  265.    EA   = 1;        
  266.    ES   = 1;        
  267.    TR1  = 1;
  268. }
  269. void INT_UartRcv(void) interrupt 4   //串口中断函数
  270. {
  271.     unsigned char Rcv = 0;
  272.     if(RI)                    
  273.       {

  274.          RI  = 0;        
  275.          Rcv = SBUF;    //串口读数据
  276.          if((Rcv>9||Rcv<0)&&(count==1))  //count=1,表明输入的是运算符
  277.          {
  278.              yusuanfu = Rcv;    //将读回的数据存入yunsuanfu这个变量
  279.              switch(yusuanfu)   //判断读回的运算符,并将他们显示在屏上1的位置
  280.             {
  281.                 case 75 : write_com(0x80+1); write_date('+'); LCD_Delay_ms(1000); break;                                         
  282.                 case 77 : write_com(0x80+1); write_date('-');  break;
  283.                 case 248 : write_com(0x80+1); write_date('*');  break;
  284.                 case 79 : write_com(0x80+1); write_date('/');  break;
  285.                                                 }
  286.                                                 count++;
  287.           }
  288.          else if(count==2)  //count=2表明第二个数据来了
  289.          {
  290.                                           num2= Rcv-2;
  291.                                           display_num2();
  292.                                           count++;
  293.                                  }
  294.             
  295.                                  else if(count==3)   //count=3表明该计算结果了
  296.                                  {
  297.                                   switch(yusuanfu)  //判断运算符是哪个,并执行相应的计算
  298.             {
  299.                                                           case  75:  data_a = num1 +num2-110;   break;   //检测到”+“号,让两个数据相加
  300.                 case  77:  data_a = num1 -num2-146;  break;     //检测到”-“号,让两个数据相减
  301.                 case 248:  data_a = ((num2-110) *num1);  break;  //检测到”x“号,让两个数据相乘
  302.                 case  79:  data_a = num1 /(num2-110);  break;    //检测到”/“号,让两个数据相除
  303.             }
  304.                                                     display_a();  //显示运算结果
  305.                                                                 LCD_Delay_ms(1000);  //延时,让显示的结果延时一下
  306.                 count=0;  //计算完一遍,让变量清0
  307.                                                           LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0'); //清屏,让屏显示0,表示已准备好计算下一次
  308.          }
  309.          else if (count==0)  //count=0,表示一次计算刚刚开始
  310.          {
  311.             num1 = Rcv-112;        // 第一个数据发回来的码值减去112就是想要得到的数据               
  312.                                           display_num1();        // 显示第一个数                             
  313.            count++;                //变量加1
  314.                                          feng=1;                 //蜂鸣器响一下,此语句是调试阶段用到的
  315.                                          LCD_Delay_ms(1000);
  316.                                          feng=0;      //关掉蜂鸣器
  317.          }

  318.       }
  319. }
  320. void main()
  321. {
  322.   UART_Init();          //串口初始化
  323.         init_lcd();                                          //1602液晶初始化
  324.         while(1)      //什么也不做,等待执行中断函数
  325. {
  326.         ;
  327. }
  328. }




复制代码

所有资料51hei提供下载:
1-计算器程序.rar (51.11 KB, 下载次数: 10)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表