zoukankan      html  css  js  c++  java
  • 51单片机 | 实现计算器(中缀表示法)

    ————————————————————————————————————————————

    开发板:畅学51单片机学习板

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    使用元件:

    • STC51单片机芯片
    • 51单片机核心板
    • LCD1602
    • 矩阵键盘
    • 11.0592MHz晶振

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现效果:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现原理:

    中缀表示法实现计算器正常情况下用栈实现,但由于51单片机内存小,无法使用malloc函数,以及一些莫名其妙的原因导致无法给指针赋值,所以在此处使用数组来模拟栈中情况,以两个int类型变量指示组中数量(模拟栈顶指针)

    中缀表示法实现原理见

    http://www.cnblogs.com/hughdong/p/6837247.html

    http://www.cnblogs.com/hughdong/p/7088915.html

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现代码:

      1 /********************************
      2 实验箱实现计算器
      3 *********************************
      4 器件连接:
      5 89C51 P0.0 - LCD D0
      6 89C51 P0.1 - LCD D1
      7 89C51 P0.2 - LCD D2
      8 89C51 P0.3 - LCD D3
      9 89C51 P0.4 - LCD D4
     10 89C51 P0.5 - LCD D5
     11 89C51 P0.6 - LCD D6
     12 89C51 P0.7 - LCD D7
     13 89C51 P2.0 - LCD RS
     14 89C51 P2.1 - LCD RW
     15 89C51 P2.2 - LCD EN
     16 89C51 P3.0 - k1
     17 89C51 P3.1 - k2
     18 89C51 P3.2 - k3
     19 89C51 P1.0 - BUTTON L1
     20 89C51 P1.1 - BUTTON L2
     21 89C51 P1.2 - BUTTON L3
     22 89C51 P1.3 - BUTTON L4
     23 89C51 P1.4 - BUTTON H1
     24 89C51 P1.5 - BUTTON H2
     25 89C51 P1.6 - BUTTON H3
     26 89C51 P1.7 - BUTTON H4
     27 *********************************
     28 按键对应数值
     29 1 2 3 +
     30 4 5 6 -
     31 7 8 9 *
     32 . 0 # /
     33 独立按键
     34 k1: (
     35 k2: )
     36 k3: C
     37 ********************************/
     38 #include <reg52.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <math.h>
     42 #define OK 1
     43 #define ERROR 0
     44 typedef unsigned char uchar;
     45 typedef unsigned int uint;
     46 typedef char Status;
     47 sbit rs = P2 ^ 0; // LCD-RS
     48 sbit rw = P2 ^ 1; // LCD-RW
     49 sbit en = P2 ^ 2; // LCD-EN
     50 sbit leftBracket = P3 ^ 0; // 右括号
     51 sbit rightBracket = P3 ^ 1; // 左括号
     52 sbit reset = P3 ^ 2; // 重置算式按键
     53 /*******************************/
     54 void Delay(uint z); // 延时函数
     55 void UART_Init(); // 串口初始化
     56 void UART_Send_Byte(uchar ucData); // 串口发送单字节
     57 void UART_Send_Str(uchar *string); // 串口发送字符串
     58 void UART_Send_Enter(); // 串口发送回车
     59 void Init_LCD(); // 初始化LCD1602
     60 void WriteData(uchar dat); // LCD写字节
     61 void WriteCom(uchar com); // LCD写指令
     62 void ClearScreen(); // LCD清屏
     63 int InputJudge(char keyValue); // 判断按键是操作符还是操作数
     64 char PriorityJudge(char optr1, char optr2); // 操作数比较
     65 float Calc(char optr, float num1, float num2); // 四则运算
     66 void LCD_Float(float f); // 测试函数,LCD第二行显示float
     67 void LCD_Int(int dat); // 测试函数,LCD第二行显示int
     68 void LCD_Char(char c); // 测试函数,根据指针显示char
     69 /*******************************/
     70 void main()
     71 {
     72     /* 定义运算变量 */
     73     char arrayChar[20]; // 操作数存放数组
     74     float arrayFloat[20]; // 操作数存放数组
     75     int topChar; // 操作符数量
     76     int topFloat; // 操作数数量
     77     char tempChar; // 读取数组顶部存放的操作符
     78     float tempFloat; // 读取数组顶部存放的操作数
     79     char optr; // 四则运算操作符
     80     float num1, num2; // 四则运算操作数
     81     int i; // i作为临时循环使用
     82     int tenPower; // 参与小数点运算时被除数
     83     /* 定义硬件操作变量 */
     84     unsigned char temp; // 按键检索时存放临时值
     85     unsigned char key; // 按键值 16进制
     86     unsigned char keyValue; // 按键值 char类型
     87     unsigned int ipos; // LCD显示指针计数
     88     unsigned int flag; // flag标记,操作数为1 操作符为0 点运算为2
     89 
     90 re: // 按下C键复位,重新输入计算式子
     91 
     92     /* 初始化变量 */
     93     for (i = 0; i < 20; ++i)
     94     {
     95         arrayChar[i] = '0';
     96         arrayFloat[20] = 0;
     97     }
     98     topChar = 0;
     99     topFloat = 0;
    100     tenPower = 1;
    101     ipos = 0;
    102     flag = 0;
    103 
    104     /* 压入# */
    105     arrayChar[topChar] = '#';
    106     topChar++;
    107 
    108     /* 初始化硬件 */
    109     UART_Init();
    110     Init_LCD();
    111     Delay(100);
    112     while(1)
    113     {
    114         P1 = 0xf0;
    115         leftBracket = 1;
    116         rightBracket = 1;
    117         reset = 1;
    118 
    119         /* 按键检测 */
    120         if (P1 != 0xf0 || !leftBracket || !rightBracket || !reset)
    121         {
    122             Delay(20);
    123             if (P1 != 0xf0)
    124             {
    125                 temp = P1;
    126                 P1 = 0x0f;
    127                 key = temp | P1;
    128                 while(P1 != 0x0f);
    129                 ipos++;
    130                 if (ipos == 16)
    131                 {
    132                     ClearScreen();
    133                     ipos = 0;
    134                 }
    135 
    136                 /* 按键赋值 */
    137                 switch(key)
    138                 {
    139                 case 0xEE:keyValue = '1';WriteData(keyValue);break;
    140                 case 0xED:keyValue = '2';WriteData(keyValue);break;
    141                 case 0xEB:keyValue = '3';WriteData(keyValue);break;
    142                 case 0xDE:keyValue = '4';WriteData(keyValue);break;
    143                 case 0xDD:keyValue = '5';WriteData(keyValue);break;
    144                 case 0xDB:keyValue = '6';WriteData(keyValue);break;
    145                 case 0xBE:keyValue = '7';WriteData(keyValue);break;
    146                 case 0xBD:keyValue = '8';WriteData(keyValue);break;
    147                 case 0xBB:keyValue = '9';WriteData(keyValue);break;
    148                 case 0x7D:keyValue = '0';WriteData(keyValue);break;
    149                 case 0xE7:keyValue = '+';WriteData(keyValue);break;
    150                 case 0xD7:keyValue = '-';WriteData(keyValue);break;
    151                 case 0xB7:keyValue = '*';WriteData(keyValue);break;
    152                 case 0x77:keyValue = '/';WriteData(keyValue);break;
    153                 case 0x7E:keyValue = '.';WriteData(keyValue);break;
    154                 case 0x7B:keyValue = '#';WriteData('=');break;
    155                 }
    156             }
    157             else if(!leftBracket)
    158             {
    159                 Delay(20);
    160                 if (!leftBracket)
    161                 {
    162                     while(!leftBracket);
    163                     keyValue = '(';
    164                     WriteData(keyValue);
    165                 }
    166             }
    167             else if(!rightBracket)
    168             {
    169                 Delay(20);
    170                 if (!rightBracket)
    171                 {
    172                     while(!rightBracket);
    173                     keyValue = ')';
    174                     WriteData(keyValue);
    175                 }
    176             }
    177             else if(!reset) // 当按下复位C键时,清屏并回到初始状态
    178             {
    179                 Delay(20);
    180                 if (!reset)
    181                 {
    182                     while(!reset);
    183                     ClearScreen();
    184                     goto re;
    185                 }
    186             }
    187 
    188             /* 运算过程 */
    189             if (keyValue == '.') // 当为点运算时,flag标识为2,后续输入的数字进行小数运算
    190             {
    191                 flag = 2;
    192                 tenPower = 1;
    193                 continue;
    194             }
    195             if (InputJudge(keyValue)) //判断输入是否为数字
    196             {
    197                 if (flag == 0) // <上次是操作符,本次是操作数> 压栈
    198                 {
    199                     arrayFloat[topFloat] = (float)(keyValue - '0');
    200                     topFloat++;
    201                     flag = 1;
    202                     continue;
    203                 }
    204                 else if(flag == 1) // <输入10位以上数字> 弹栈值*10+本次值
    205                 {
    206                     topFloat--;
    207                     tempFloat = arrayFloat[topFloat];
    208                     arrayFloat[topFloat] = (float)(tempFloat * 10 + (keyValue - '0'));
    209                     topFloat++;
    210                     flag = 1;
    211                     continue;
    212                 }
    213                 else if (flag == 2) // <输入小数> 弹栈值+本次值/(10的n次方)
    214                 {
    215                     topFloat--;
    216                     tempFloat = arrayFloat[topFloat];
    217                     tenPower = tenPower * 10;
    218                     tempFloat = tempFloat + ((float)(keyValue - '0') / tenPower);
    219                     arrayFloat[topFloat] = tempFloat;
    220                     topFloat++;
    221                     flag = 2;
    222                     continue;
    223                 }
    224             }
    225             /****************************************************
    226             当按键值为符号时,进行计算或压入运算符组
    227             优先级为 > 时,重复对比并计算
    228             ****************************************************/
    229             else
    230             {
    231 reCalc:
    232                 tempChar = arrayChar[topChar - 1];
    233                 switch(PriorityJudge(tempChar, keyValue)) // 判断本次输入符号与操作符数组顶部元素优先级
    234                 {
    235                 /****************************************************
    236                 本次输入压入操作符组顶部,完毕后重新获取按键
    237                 ****************************************************/
    238                 case '<':
    239                     arrayChar[topChar] = keyValue;
    240                     topChar++;
    241                     flag = 0;
    242                     continue;
    243                 /****************************************************
    244                 ()或#闭合时,弹出顶部元素
    245                 ()闭合后重新获取按键
    246                 #弹出说明公式计算完毕,LCD显示结果并进入死循环
    247                 计算结束后,按下复位键代码回到Line 90,程序重置
    248                 ****************************************************/
    249                 case '=':
    250                     topChar--;
    251                     tempChar = arrayChar[topChar];
    252                     if (tempChar == '#')
    253                     {
    254                         LCD_Float(arrayFloat[topFloat - 1]);
    255                         /*
    256                         LCD_Int(topFloat);
    257                         UART_Send_Enter();
    258                         UART_Send_Str("End");
    259                         */
    260                         while(1)
    261                         {
    262                             if(!reset)
    263                             {
    264                                 Delay(20);
    265                                 if (!reset)
    266                                 {
    267                                     while(!reset);
    268                                     ClearScreen();
    269                                     goto re; // line 90
    270                                 }
    271                             }
    272                         }
    273                     }
    274                     flag = 0;
    275                     continue;
    276                 /****************************************************
    277                 弹出两个操作数和一个操作符进行四则运算
    278                 运算结束后将结果操作数压入
    279                 程序回到 reCalc处 Line231,继续弹出操作符对比
    280                 ****************************************************/
    281                 case '>':
    282                     topChar--;
    283                     optr = arrayChar[topChar];
    284                     topFloat--;
    285                     num2 = arrayFloat[topFloat];
    286                     topFloat--;
    287                     num1 = arrayFloat[topFloat];
    288                     arrayFloat[topFloat] = Calc(optr, num1, num2);
    289                     topFloat++;
    290                     flag = 0;
    291                     goto reCalc;
    292                 }
    293             }
    294         }
    295         /*
    296         char串口打印测试 
    297         UART_Send_Enter();
    298         UART_Send_Str("optr:");
    299         UART_Send_Byte(optr);
    300         int串口打印测试 
    301         UART_Send_Enter();
    302         UART_Send_Byte(topFloat + '0');
    303         */
    304     }
    305 }
    306 void UART_Init()
    307 {
    308     SCON = 0x50;
    309     TMOD = 0x20;
    310     PCON = 0x00;
    311     TH1 = 0xFD;
    312     TL1 = 0xFD;
    313     TR1 = 1;
    314     ES = 1;
    315     EA = 1;
    316     ET1 = 0;
    317 }
    318 void UART_Send_Byte(uchar ucData)
    319 {
    320     SBUF = ucData;
    321     while(!TI);
    322     TI = 0;
    323 }
    324 void UART_Send_Str(uchar *string)
    325 {
    326     while(*string)
    327         UART_Send_Byte(*string++);
    328 }
    329 void UART_Send_Enter()
    330 {
    331     UART_Send_Byte(0x0d);
    332     UART_Send_Byte(0x0a);
    333 }
    334 void Init_LCD()
    335 {
    336     en = 0;
    337     WriteCom(0x38);
    338     WriteCom(0x0e);
    339     WriteCom(0x06);
    340     WriteCom(0x01);
    341     WriteCom(0x80 + 0x1);
    342 }
    343 void WriteData(uchar dat)
    344 {
    345     rs = 1;
    346     rw = 0;
    347     P0 = dat;
    348     Delay(5);
    349     en = 1;
    350     Delay(5);
    351     en = 0;
    352 }
    353 void WriteCom(uchar com)
    354 {
    355     rs = 0;
    356     rw = 0;
    357     P0 = com;
    358     Delay(5);
    359     en = 1;
    360     Delay(5);
    361     en = 0;
    362 }
    363 void ClearScreen()
    364 {
    365     WriteCom(0x01);
    366 }
    367 void Delay(uint z)
    368 {
    369     uint x, y;
    370     for(x = z; x > 0; x--)
    371         for(y = 110; y > 0; y--);
    372 }
    373 int InputJudge(char keyValue)
    374 {
    375     switch(keyValue)
    376     {
    377     case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':return OK;break;
    378     case '+':case '-':case '*':case '/':case '(':case ')':case '#':return ERROR;break;
    379     default:break;
    380     }
    381 }
    382 char PriorityJudge(char optr1, char optr2)
    383 {
    384     int i, j;
    385     char priorityTable[7][7] =
    386     {
    387         // +   -    *    /    (    )    #
    388         {'>', '>', '<', '<', '<', '>', '>'}, // +
    389         {'>', '>', '<', '<', '<', '>', '>'}, // -
    390         {'>', '>', '>', '>', '<', '>', '>'}, // *
    391         {'>', '>', '>', '>', '<', '>', '>'}, // /
    392         {'<', '<', '<', '<', '<', '=', '0'}, // (
    393         {'>', '>', '>', '>', '0', '>', '>'}, // )
    394         {'<', '<', '<', '<', '<', '0', '='}  // #
    395     };
    396     switch(optr1)
    397     {
    398     case '+':i = 0;break;
    399     case '-':i = 1;break;
    400     case '*':i = 2;break;
    401     case '/':i = 3;break;
    402     case '(':i = 4;break;
    403     case ')':i = 5;break;
    404     case '#':i = 6;break;
    405     }
    406     switch(optr2)
    407     {
    408     case '+':j = 0;break;
    409     case '-':j = 1;break;
    410     case '*':j = 2;break;
    411     case '/':j = 3;break;
    412     case '(':j = 4;break;
    413     case ')':j = 5;break;
    414     case '#':j = 6;break;
    415     }
    416     return priorityTable[i][j];
    417 }
    418 float Calc(char optr, float num1, float num2)
    419 {
    420     switch(optr)
    421     {
    422     case '+':return (num1 + num2);break;
    423     case '-':return (num1 - num2);break;
    424     case '*':return (num1 * num2);break;
    425     case '/':return (num1 / num2);break;
    426     }
    427 }
    428 void LCD_Float(float f)
    429 {
    430     char str[7];
    431     int i, length;
    432     for (i = 0; i < 7; ++i)
    433         str[i] = '0';
    434     length = sprintf(str, "%g", f);
    435     WriteCom(0x80 + 0x40);
    436     Delay(20);
    437     for (i = 0; i < length; ++i)
    438     {
    439         WriteData(str[i]);
    440         Delay(20);
    441     }
    442 }
    443 void LCD_Int(int dat)
    444 {
    445     char str[7];
    446     int i, length;
    447     for (i = 0; i < 7; ++i)
    448         str[i] = '0';
    449     length = sprintf(str, "%d", dat);
    450     WriteCom(0x80 + 0x48);
    451     Delay(20);
    452     for (i = 0; i < length; ++i)
    453     {
    454         WriteData(str[i]);
    455         Delay(20);
    456     }
    457 }
    458 void LCD_Char(char c)
    459 {
    460     WriteData(c);
    461     Delay(20);
    462 }

       

  • 相关阅读:
    自定义函数
    内置函数
    炸裂函数explode
    -bash:ls:command not found,执行命令总是报找不到
    函数
    C#的lock用法
    获取客户端Ip地址方法
    Grunt基础
    常用Sql
    HandleBars
  • 原文地址:https://www.cnblogs.com/hughdong/p/7096080.html
Copyright © 2011-2022 走看看