找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机计算器程序状态图与Proteus仿真

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include "led_seg.h"
  2. #include "key.h"
  3. #include "mymath.h"

  4. typedef enum
  5. {
  6.         OPERATOR_EMPTY,
  7.         OPERATOR_PLUS,
  8.         OPERATOR_MINUS,
  9.         OPERATOR_MULTIPLY,
  10.         OPERATOR_DIVIDE,
  11.         OPERATOR_EQUAL
  12. } OPERATOR;


  13. typedef enum
  14. {
  15.         STATE_INIT,
  16.         STATE_INPUT_FIRST_NUM,
  17.         STATE_INPUT_SECOND_NUM,
  18.         STATE_CALC_SIGN,
  19.         STATE_EQUAL
  20. } STATE;

  21. u8 timer = 0;
  22. double show_number = 0;

  23. // 用来标记小数点是否按下
  24. bit is_dot_press = 0;
  25. // 用来记录小数点按下后键盘按下的数的数量
  26. u8 after_dot_press_number = 0;


  27. // (float) 等价于 (double) 6位有效数字
  28. void Timer0Init(void);
  29. void Timer0Interrupt(void);
  30. void update_show_number(u8);
  31. void update_calc_sign(OPERATOR);

  32. double first_number = 0;
  33. double second_number = 0;



  34. OPERATOR myoperator = OPERATOR_EMPTY;
  35. STATE state = STATE_INIT;
  36. void main()
  37. {
  38.         Timer0Init();
  39.         while(1)
  40.         {
  41.                
  42.                 keyscan();
  43.                
  44.                 if(NO_KEY_PRESS != key_state)
  45.                 {
  46.                         switch(key_state)
  47.                         {
  48.                                 // 1
  49.                                 case 0:
  50.                                         update_show_number(1);
  51.                                         break;
  52.                                 // 2
  53.                                 case 1:
  54.                                         update_show_number(2);
  55.                                         break;
  56.                                 // 3
  57.                                 case 2:
  58.                                         update_show_number(3);
  59.                                         break;
  60.                                 // +
  61.                                 case 3:
  62.                                         update_calc_sign(OPERATOR_PLUS);
  63.                                         break;
  64.                                 // 4
  65.                                 case 4:
  66.                                         update_show_number(4);
  67.                                         break;
  68.                                 // 5
  69.                                 case 5:
  70.                                         update_show_number(5);
  71.                                         break;
  72.                                 // 6
  73.                                 case 6:
  74.                                         update_show_number(6);
  75.                                         break;
  76.                                 // -
  77.                                 case 7:
  78.                                         update_calc_sign(OPERATOR_MINUS);
  79.                                         break;
  80.                                 // 7
  81.                                 case 8:
  82.                                         update_show_number(7);
  83.                                         break;
  84.                                 // 8
  85.                                 case 9:
  86.                                         update_show_number(8);
  87.                                         break;
  88.                                 // 9
  89.                                 case 10:
  90.                                         update_show_number(9);
  91.                                         break;
  92.                                 // ×
  93.                                 case 11:
  94.                                         update_calc_sign(OPERATOR_MULTIPLY);
  95.                                         break;
  96.                                 // .
  97.                                 case 12:
  98.                                         is_dot_press = 1;
  99.                                         break;
  100.                                 // 0
  101.                                 case 13:
  102.                                         update_show_number(0);
  103.                                         break;
  104.                                 // =
  105.                                 case 14:
  106.                                                 switch(state)
  107.                                                 {
  108.                                                         case STATE_INIT:
  109.                                                         case STATE_EQUAL:
  110.                                                         case STATE_INPUT_FIRST_NUM:
  111.                                                                 first_number = show_number;
  112.                                                                 state = STATE_EQUAL;
  113.                                                                 myoperator = OPERATOR_EMPTY;                                
  114.                                                                 break;
  115.                                                         case STATE_INPUT_SECOND_NUM:
  116.                                                                 second_number = show_number;
  117.                                                                 switch(myoperator)
  118.                                                                 {
  119.                                                                         case OPERATOR_PLUS:
  120.                                                                                 show_number = first_number + second_number;
  121.                                                                                 break;
  122.                                                                         case OPERATOR_MINUS:
  123.                                                                                 show_number = first_number - second_number;
  124.                                                                                 break;
  125.                                                                         case OPERATOR_MULTIPLY:
  126.                                                                                 show_number = first_number * second_number;
  127.                                                                                 break;
  128.                                                                         case OPERATOR_DIVIDE:
  129.                                                                                 
  130.                                                                                 if(0.000000 != second_number)
  131.                                                                                 {
  132.                                                                                         show_number = first_number / second_number;
  133.                                                                                 }
  134.                                                                                 else
  135.                                                                                 {
  136.                                                                                         // warning
  137.                                                                                         show_number = 0;

  138.                                                                                 }
  139.                                                                                        
  140.                                                                                 break;
  141.                                                                         default:
  142.                                                                                 break;
  143.                                                                 }
  144.                                                                 is_dot_press = 0;
  145.                                                                 after_dot_press_number = 0;
  146.                                                                 first_number = 0;
  147.                                                                 second_number = 0;
  148.                                                                 state = STATE_EQUAL;
  149.                                                                 myoperator = OPERATOR_EMPTY;
  150.                                                                 break;
  151.                                                         case STATE_CALC_SIGN:
  152.                                                                 break;
  153.                                                         default:
  154.                                                                 break;
  155.                                                 }
  156.                                         break;
  157.                                 // ÷
  158.                                 case 15:
  159.                                         update_calc_sign(OPERATOR_DIVIDE);
  160.                                         break;
  161.                                 //意外情况的处理
  162.                                 default:
  163.                                         break;
  164.                         }
  165.                         key_state = NO_KEY_PRESS;
  166.                 }
  167.         }
  168. }


  169. void Timer0Init(void)                //100微秒@12.000MHz
  170. {
  171.         TMOD &= 0xF0;                //设置定时器模式
  172.         TMOD |= 0x02;                //设置定时器模式
  173.         TL0 = 0x9C;                //设置定时初值
  174.         TH0 = 0x9C;                //设置定时重载值
  175.         TF0 = 0;                //清除TF0标志
  176.         TR0 = 1;                //定时器0开始计时
  177.         ET0 = 1;
  178.         EA = 1;
  179. }

  180. void Timer0Interrupt(void) interrupt 1
  181. {
  182.         timer++;
  183.         if(10 == timer)
  184.         {
  185.                 LedShowByNum(show_number);
  186.                 timer = 0;
  187.         }
  188.         keyrescan();
  189. }


  190. void update_show_number(u8 number)
  191. {

  192.         switch(state)
  193.         {
  194.                 case STATE_INIT:
  195.                 case STATE_EQUAL:
  196.                         show_number = 0;
  197.                         first_number = 0;
  198.                         second_number = 0;
  199.                         myoperator = OPERATOR_EMPTY;
  200.                         state = STATE_INPUT_FIRST_NUM;
  201.                         break;
  202.                 case STATE_INPUT_FIRST_NUM:
  203.                         break;
  204.                 case STATE_INPUT_SECOND_NUM:
  205.                         break;
  206.                 case STATE_CALC_SIGN:
  207.                         second_number = show_number = 0;
  208.                         state = STATE_INPUT_SECOND_NUM;
  209.                         break;
  210.                 default:
  211.                         break;
  212.         }
  213.         if(is_dot_press)
  214.         {
  215.                 after_dot_press_number++;
  216.                 show_number += number / ((double)mypow(10,after_dot_press_number));
  217.         }
  218.         else
  219.         {
  220.                 show_number *= 10;
  221.                 show_number += number;
  222.         }
  223.         switch(state)
  224.         {
  225.                 case STATE_INPUT_FIRST_NUM:
  226.                         first_number = show_number;
  227.                         break;
  228.                 case STATE_INPUT_SECOND_NUM:
  229.                         second_number = show_number;
  230.                         break;
  231.                 default:
  232.                         break;
  233.         }
  234.         
  235. }

  236. void update_calc_sign(OPERATOR opr)
  237. {
  238.         switch(state)
  239.         {
  240.                 case STATE_INIT:
  241.                         first_number = 0;
  242.                         myoperator = opr;
  243.                         state = STATE_CALC_SIGN;
  244.                         break;
  245.                 case STATE_EQUAL:
  246.                 case STATE_INPUT_FIRST_NUM:
  247.                         first_number = show_number;
  248.                         state = STATE_CALC_SIGN;
  249.                         myoperator = opr;
  250.                         break;
  251.                 case STATE_INPUT_SECOND_NUM:
  252.                         second_number = show_number;
  253.                         is_dot_press = 0;
  254.                         after_dot_press_number = 0;
  255.                         switch(myoperator)
  256.                         {
  257.                                 case OPERATOR_PLUS:
  258.                                         show_number = first_number + second_number;
  259.                                         break;
  260.                                 case OPERATOR_MINUS:
  261.                                         show_number = first_number - second_number;
  262.                                         break;
  263.                                 case OPERATOR_MULTIPLY:
  264.                                         show_number = first_number * second_number;
  265.                                         break;
  266.                                 case OPERATOR_DIVIDE:
  267.                                         if(0.000000 != second_number)
  268.                                         {
  269.                                                 show_number = first_number / second_number;
  270.                                         }
  271.                                         else
  272.                                         {
  273.                                                 is_dot_press = 0;
  274.                                                 after_dot_press_number = 0;
  275.                                                 // warning
  276.                                                 show_number = 0;
  277.                                                 first_number = 0;
  278.                                                 second_number = 0;
  279.                                                 myoperator = OPERATOR_EMPTY;
  280.                                                 state = STATE_INIT;
  281.                                                 return;
  282.                                         }
  283.                                                 
  284.                                         break;
  285.                                 default:
  286.                                         break;
  287.                         }
  288.                         first_number = show_number;
  289.                         state = STATE_CALC_SIGN;
  290.                         myoperator = opr;
  291.                         break;
  292.                 case STATE_CALC_SIGN:
  293.                         break;
  294.         }
  295. }
复制代码
全部资料51hei下载地址(仿真+程序):
09-实现一个简便的计算器.7z (116.72 KB, 下载次数: 41)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:1048675 发表于 2023-4-9 16:29 | 只看该作者
第一次输入数不能带小数,否则运算符后的第二次输入数出错。比如7.1+2=9.2 。但是显示为7.1+0.02=7.12 。不知什么原因?楼主能不能查一下,更正后我再来下载一下。
回复

使用道具 举报

板凳
ID:1048675 发表于 2023-4-13 15:57 | 只看该作者
已解决了第一次输入不能是小数的问题。但是出现了第二个问题,就是不能及时显示小数点及小数点后面的零,只有小数点后面是除零外的数才能及时显示。一直没有找到原因,楼主帮一下,谢谢!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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