標(biāo)題:
51單片機(jī)計(jì)算器程序狀態(tài)圖與Proteus仿真
[打印本頁]
作者:
wmj123
時(shí)間:
2020-12-4 15:23
標(biāo)題:
51單片機(jī)計(jì)算器程序狀態(tài)圖與Proteus仿真
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png
(22.31 KB, 下載次數(shù): 92)
下載附件
2020-12-4 16:45 上傳
狀態(tài)圖.jpg
(97.45 KB, 下載次數(shù): 72)
下載附件
2020-12-4 16:45 上傳
單片機(jī)源程序如下:
#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;
// 用來標(biāo)記小數(shù)點(diǎn)是否按下
bit is_dot_press = 0;
// 用來記錄小數(shù)點(diǎn)按下后鍵盤按下的數(shù)的數(shù)量
u8 after_dot_press_number = 0;
// (float) 等價(jià)于 (double) 6位有效數(shù)字
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; //設(shè)置定時(shí)器模式
TMOD |= 0x02; //設(shè)置定時(shí)器模式
TL0 = 0x9C; //設(shè)置定時(shí)初值
TH0 = 0x9C; //設(shè)置定時(shí)重載值
TF0 = 0; //清除TF0標(biāo)志
TR0 = 1; //定時(shí)器0開始計(jì)時(shí)
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;
}
}
復(fù)制代碼
全部資料51hei下載地址(仿真+程序):
09-實(shí)現(xiàn)一個(gè)簡便的計(jì)算器.7z
(116.72 KB, 下載次數(shù): 47)
2020-12-4 15:23 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
作者:
泰興電子
時(shí)間:
2023-4-9 16:29
第一次輸入數(shù)不能帶小數(shù),否則運(yùn)算符后的第二次輸入數(shù)出錯(cuò)。比如7.1+2=9.2 。但是顯示為7.1+0.02=7.12 。不知什么原因?樓主能不能查一下,更正后我再來下載一下。
作者:
泰興電子
時(shí)間:
2023-4-13 15:57
已解決了第一次輸入不能是小數(shù)的問題。但是出現(xiàn)了第二個(gè)問題,就是不能及時(shí)顯示小數(shù)點(diǎn)及小數(shù)點(diǎn)后面的零,只有小數(shù)點(diǎn)后面是除零外的數(shù)才能及時(shí)顯示。一直沒有找到原因,樓主幫一下,謝謝!
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1