仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include "led_seg.h"
- #include "key.h"
- #include "mymath.h"
- typedef enum
- {
- OPERATOR_EMPTY,
- OPERATOR_PLUS,
- OPERATOR_MINUS,
- OPERATOR_MULTIPLY,
- OPERATOR_DIVIDE,
- OPERATOR_EQUAL
- } OPERATOR;
- typedef enum
- {
- STATE_INIT,
- STATE_INPUT_FIRST_NUM,
- STATE_INPUT_SECOND_NUM,
- STATE_CALC_SIGN,
- STATE_EQUAL
- } STATE;
- u8 timer = 0;
- double show_number = 0;
- // 用来标记小数点是否按下
- bit is_dot_press = 0;
- // 用来记录小数点按下后键盘按下的数的数量
- u8 after_dot_press_number = 0;
- // (float) 等价于 (double) 6位有效数字
- void Timer0Init(void);
- void Timer0Interrupt(void);
- void update_show_number(u8);
- void update_calc_sign(OPERATOR);
- double first_number = 0;
- double second_number = 0;
- OPERATOR myoperator = OPERATOR_EMPTY;
- STATE state = STATE_INIT;
- void main()
- {
- Timer0Init();
- while(1)
- {
-
- keyscan();
-
- if(NO_KEY_PRESS != key_state)
- {
- switch(key_state)
- {
- // 1
- case 0:
- update_show_number(1);
- break;
- // 2
- case 1:
- update_show_number(2);
- break;
- // 3
- case 2:
- update_show_number(3);
- break;
- // +
- case 3:
- update_calc_sign(OPERATOR_PLUS);
- break;
- // 4
- case 4:
- update_show_number(4);
- break;
- // 5
- case 5:
- update_show_number(5);
- break;
- // 6
- case 6:
- update_show_number(6);
- break;
- // -
- case 7:
- update_calc_sign(OPERATOR_MINUS);
- break;
- // 7
- case 8:
- update_show_number(7);
- break;
- // 8
- case 9:
- update_show_number(8);
- break;
- // 9
- case 10:
- update_show_number(9);
- break;
- // ×
- case 11:
- update_calc_sign(OPERATOR_MULTIPLY);
- break;
- // .
- case 12:
- is_dot_press = 1;
- break;
- // 0
- case 13:
- update_show_number(0);
- break;
- // =
- case 14:
- switch(state)
- {
- case STATE_INIT:
- case STATE_EQUAL:
- case STATE_INPUT_FIRST_NUM:
- first_number = show_number;
- state = STATE_EQUAL;
- myoperator = OPERATOR_EMPTY;
- break;
- case STATE_INPUT_SECOND_NUM:
- second_number = show_number;
- switch(myoperator)
- {
- case OPERATOR_PLUS:
- show_number = first_number + second_number;
- break;
- case OPERATOR_MINUS:
- show_number = first_number - second_number;
- break;
- case OPERATOR_MULTIPLY:
- show_number = first_number * second_number;
- break;
- case OPERATOR_DIVIDE:
-
- if(0.000000 != second_number)
- {
- show_number = first_number / second_number;
- }
- else
- {
- // warning
- show_number = 0;
- }
-
- break;
- default:
- break;
- }
- is_dot_press = 0;
- after_dot_press_number = 0;
- first_number = 0;
- second_number = 0;
- state = STATE_EQUAL;
- myoperator = OPERATOR_EMPTY;
- break;
- case STATE_CALC_SIGN:
- break;
- default:
- break;
- }
- break;
- // ÷
- case 15:
- update_calc_sign(OPERATOR_DIVIDE);
- break;
- //意外情况的处理
- default:
- break;
- }
- key_state = NO_KEY_PRESS;
- }
- }
- }
- void Timer0Init(void) //100微秒@12.000MHz
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x02; //设置定时器模式
- TL0 = 0x9C; //设置定时初值
- TH0 = 0x9C; //设置定时重载值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0 = 1;
- EA = 1;
- }
- void Timer0Interrupt(void) interrupt 1
- {
- timer++;
- if(10 == timer)
- {
- LedShowByNum(show_number);
- timer = 0;
- }
- keyrescan();
- }
- void update_show_number(u8 number)
- {
- switch(state)
- {
- case STATE_INIT:
- case STATE_EQUAL:
- show_number = 0;
- first_number = 0;
- second_number = 0;
- myoperator = OPERATOR_EMPTY;
- state = STATE_INPUT_FIRST_NUM;
- break;
- case STATE_INPUT_FIRST_NUM:
- break;
- case STATE_INPUT_SECOND_NUM:
- break;
- case STATE_CALC_SIGN:
- second_number = show_number = 0;
- state = STATE_INPUT_SECOND_NUM;
- break;
- default:
- break;
- }
- if(is_dot_press)
- {
- after_dot_press_number++;
- show_number += number / ((double)mypow(10,after_dot_press_number));
- }
- else
- {
- show_number *= 10;
- show_number += number;
- }
- switch(state)
- {
- case STATE_INPUT_FIRST_NUM:
- first_number = show_number;
- break;
- case STATE_INPUT_SECOND_NUM:
- second_number = show_number;
- break;
- default:
- break;
- }
-
- }
- void update_calc_sign(OPERATOR opr)
- {
- switch(state)
- {
- case STATE_INIT:
- first_number = 0;
- myoperator = opr;
- state = STATE_CALC_SIGN;
- break;
- case STATE_EQUAL:
- case STATE_INPUT_FIRST_NUM:
- first_number = show_number;
- state = STATE_CALC_SIGN;
- myoperator = opr;
- break;
- case STATE_INPUT_SECOND_NUM:
- second_number = show_number;
- is_dot_press = 0;
- after_dot_press_number = 0;
- switch(myoperator)
- {
- case OPERATOR_PLUS:
- show_number = first_number + second_number;
- break;
- case OPERATOR_MINUS:
- show_number = first_number - second_number;
- break;
- case OPERATOR_MULTIPLY:
- show_number = first_number * second_number;
- break;
- case OPERATOR_DIVIDE:
- if(0.000000 != second_number)
- {
- show_number = first_number / second_number;
- }
- else
- {
- is_dot_press = 0;
- after_dot_press_number = 0;
- // warning
- show_number = 0;
- first_number = 0;
- second_number = 0;
- myoperator = OPERATOR_EMPTY;
- state = STATE_INIT;
- return;
- }
-
- break;
- default:
- break;
- }
- first_number = show_number;
- state = STATE_CALC_SIGN;
- myoperator = opr;
- break;
- case STATE_CALC_SIGN:
- break;
- }
- }
复制代码 全部资料51hei下载地址(仿真+程序):
09-实现一个简便的计算器.7z
(116.72 KB, 下载次数: 47)
|