導航:首頁 > 操作系統 > 計算器代碼講解單片機

計算器代碼講解單片機

發布時間:2022-12-23 18:40:14

單片機做計算器的程序

1、直接調用庫函數。

⑵ 用C語言編寫單片機上計算器程序遇到問題

問題一:如何輸入一個兩位數是吧……

通過串口輸入:串口進來的數是以位傳輸的,如果是8位的,你需要先將數據轉換成十進制數,用(x*10+y)得到兩位數,x是高位,y是低位。這樣就得到了兩位的數了!

問題二:無論加減乘除都是二進制形式計算的!比如你輸入的是1和2,他們二進制形式為別是1,10,那麼加起來後就是11,即3!

如果你想輸入33,即先輸入3,再輸入3,按照3*10+3就得到33.

你輸入的時候應該一位一位的輸入,應該都是這樣吧,從鍵盤上按下一個數字就發送給單片機,單片機接收後再次接收一個數,直到你按下+-*/為止,然後就把它轉換成十進制形式加成你想要的兩位或者更多位!

最後再進行加法或其它!

⑶ 單片機計算器C語言程序

//*************************************************************************************************
//*************************************************************************************************
//**<程序名>:多功能計算器 **
//**<功能>:可以進行6位數以內正整數的加減乘除運算,以及計時器和自定義倒計時功
*
//* ******************************頭文件及宏定義************************** *
//* *
//*************************************************************************************************
#include "includes.h"

#define TIME0H 0xFC
#define TIME0L 0x18 //定時器0溢出時間:5ms

#define TIME1H 0x44
#define TIME1L 0x80 //定時器1溢出時間:48ms

//*************************************************************************************************
//* *
//* ********************************全局變數****************************** *
//* *
//*************************************************************************************************

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<定時器0定時刷新LED計數>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
unsigned long ul_Number=0; //LCD實時顯示數字。

unsigned char uca_ShowCustom[6]={0x88,0x83,0xC6,0xA1,0x86,0x84};
//存放自定義顯示字元。

unsigned char uc_DisCount=1; //LCD時事刷新計數。

bit b_ShowMode=0; //顯示模式標志位。
//0--數字模式,將要顯示的數字賦給ul_Number便可時事顯示數值,
// 默認為數字模式;
//1--自定義模式,該模式下自定義字元顯示。

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<定時器1計數刷新定時(計時模式)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
unsigned char uc_TimeCount=1; //定時器1定時計數。

bit b_ClockStart=0; //定時器1顯示計數標志位。

extern bit b_ClockOppose; //TimeOppose.c

extern unsigned long ul_ClockOppose;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<防抖動標志>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

bit b_KeyShock=0; //鍵盤防抖動標志位。
//當按鍵中斷產生時,首先判斷此位。
//0--執行鍵盤掃描及鍵碼處理程序;1--不執行。

bit b_KillShock=0; //防抖標志清除位:0--不清除;1--清除。

unsigned char uc_KillCount=1; //抖動標志清除計數,使用定時器1。

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<LCD閃爍顯示報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
bit b_LCDClean=0; //通過設置b_LCDClean為1便可啟動延時清空LCD顯示。

unsigned char uc_CleanCount=1; //延遲時間可在T1中斷中設定。

unsigned char uc_ReportSymbol;

bit b_ReportFlash=0;

unsigned char uca_FlashBlank[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

//*************************************************************************************************
//* *
//* ********************************主函數****************************** *
//* *
//*************************************************************************************************
void main()
{
P2=0x0F; //初始化鍵盤介面。

TMOD=0x11; //定時器0:模式一;定時器0:模式一.

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<定時器0,用於LCD刷新>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TH0=TIME0H;
TL0=TIME0L;
TR0=1; //開啟定時器0
ET0=1; //開定時器0中斷

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<定時器1,用於1s計時 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TH1=TIME1H;
TL1=TIME1L;
TR1=1; //開啟定時器1
ET1=1; //開定時器1中斷

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<外部中斷0,用於執行鍵盤掃描和鍵處理程序>>>>>>>>>>>>>>>>>>>>>>>>>>>
IT0=1; //外部中斷0,中斷方式:下降沿
EX0=1; //開啟外部中斷0

PT0=1; //把定時器0溢出中斷設為高優先順序。

EA=1; //開啟總中斷

while(1);
}

//*************************************************************************************************
//* *
//* ***************************外部中斷0,調用鍵盤掃描程序************************* *
//* *
//*************************************************************************************************
void vINT0(void) interrupt 0
{
EX0=0; //在鍵掃描處理時,關閉外部中斷0,防抖動。

if(b_KeyShock==0)
{
vKeyProcess(ucKeyScan()); //當判斷有按鍵按下時,掃描鍵盤,並把掃描結果進行處理。
b_KeyShock=1; //設置防抖動標志。
}
else b_KeyShock=0; //如果有抖動則不執行鍵掃描,恢復防抖動標志。

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<設置防抖動清除標志位 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(b_KeyShock==1)
b_KillShock=1; //如果防抖動標志位開啟則開啟防抖動標志清除位,
//300ms後清除防抖動標志。

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<恢復鍵掃描處理前初始狀態 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
P2=0x0F; //恢復P2口。
EX0=1; //恢復按鍵中斷。
}

//*************************************************************************************************
//* *
//* ****************定時器1中斷,用於計時功能和防抖動標志清除以及顯示報告**************** *
//* *
//*************************************************************************************************
void vTimer1(void) interrupt 3
{
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<計時模式計數刷新>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(b_ClockStart==1) //當計時模式開啟式,如計時處於運行狀態則執行定時計數增加。
{
if(b_ClockOppose==0) //正常計時。
{
if(uc_TimeCount%21==0)
{
uc_TimeCount=1;
ul_Number++;
}
else uc_TimeCount++;
}
else
{ //倒計時模式。
if(uc_TimeCount%21==0)
{
uc_TimeCount=1;
if(ul_ClockOppose>0)
{
ul_ClockOppose--;
ul_Number=ul_ClockOppose;
}
else
{
b_ClockStart=0;
uc_ReportSymbol=7;
b_LCDClean=1;
}
}
else uc_TimeCount++;
}
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<防抖動標志清除>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(b_KillShock==1)
{
if(uc_KillCount%5==0) //當防抖動標志位為1時,計時300ms後清除抖動標志位。
{
b_KeyShock=0;
b_KillShock=0;
uc_KillCount=1;
}
else uc_KillCount++;
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<LCD顯示報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(b_LCDClean==1)
{
if(uc_CleanCount==1)
{
EX0=0; //關閉鍵盤中斷,此時按鍵無效。
vShowReport(uc_ReportSymbol);
b_ShowMode=1;
}
if(uc_CleanCount%40==0) //通過設置b_LCDClean為1便可啟動延時清空LCD顯示。
{
b_LCDClean=0; //關閉清零標志位,清零結束。
uc_CleanCount=1; //恢復清零計數為初始值1.
b_ShowMode=0; //恢復顯示模式為默認的數字模式。
b_ReportFlash=0;
EX0=1; //重新開啟鍵盤中斷。
}
else
{
//<<<<<<<<<<<<<<<<<<<<<<<<<實現閃爍報告功能>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(uc_CleanCount%7==0)
{
if(b_ReportFlash==0)
{
vCharCopy(uca_FlashBlank);
b_ReportFlash=1;
}
else
{
vShowReport(uc_ReportSymbol);
b_ReportFlash=0;
}
}
uc_CleanCount++;
}
}

TH1=TIME1H;
TL1=TIME1L;

}

//*************************************************************************************************
//* *
//* ***************************定時器0,定時刷新LED************************* *
//* *
//*************************************************************************************************
void vTimer0(void) interrupt 1
{
if(b_ShowMode==0)
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<數字模式>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
vShowOneNum(*(pucLedNum(ul_Number)+uc_DisCount),6-uc_DisCount); //在LCD上顯示1位數字。
if(uc_DisCount==5)
uc_DisCount=0; //定時器0在每次被觸發時,改變LCD顯示。
else uc_DisCount++; //從第一位到第六位循環顯示。
}
else
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<自定義模式>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
vShowCustom(uca_ShowCustom[uc_DisCount],uc_DisCount);
if(uc_DisCount==5)
uc_DisCount=0; //定時器0在每次被觸發時,改變LCD顯示。
else uc_DisCount++; //從第一位到第六位循環顯示。
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<恢復定時器0初始狀態 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TH0=TIME0H;
TL0=TIME0L;
},
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//*************************************************************************************************
//*************************************************************************************************
//**<程序名>:鍵盤掃描子程序 **
//**<功能>:當有外部中斷0時調用此函數,使用列掃描的方式獲取鍵碼,鍵碼由2位數字組成。高位為行號 **
//** 低位為列號。 **
//*************************************************************************************************
//*************************************************************************************************

//*************************************************************************************************
//* *
//* ******************************頭文件及宏定義************************** *
//* *
//*************************************************************************************************
#include <at89x51.h>

#define SCANPORT P2 //4×4鍵盤掃描埠,低4位是行線,高4位是列線。
//採用逐列掃描的方法,無按鍵時,低4位輸出1,高4位輸出0。
//當有按鍵時,高4位輸出掃描電位,低4位輸入掃描結果。

//*************************************************************************************************
//* *
//* ********************************全局變數****************************** *
//* *
//*************************************************************************************************
unsigned char uca_LineScan[4]={0xEF,0xDF,0xBF,0x7F}; //列線掃描電壓,分為第1,2,3,4根列線
//為低電平,其他為高電平。

//*************************************************************************************************
//* *
//* ********************************函數實現****************************** *
//* *
//*************************************************************************************************
unsigned char ucKeyScan()
{
unsigned char ucTemp=0; //掃描狀態暫存。
unsigned char ucRow=0,ucLine=0; //行號,列號。

for(ucLine=0;ucLine<4;ucLine++) //列掃描
{
SCANPORT=uca_LineScan[ucLine]; //輸出掃描電位。
ucTemp=SCANPORT&0x0F; //輸入掃描電位,並屏蔽高4位。
if(ucTemp!=0x0F)
{ //判斷該列是否有按鍵按下。
switch(ucTemp)
{
case 0x0E: ucRow=10;break; //如果有,則判斷行號。
case 0x0D: ucRow=20;break;
case 0x0B: ucRow=30;break;
case 0x07: ucRow=40;break;
default: ucRow=50;break;
}
break;
}
}
return ucRow+ucLine+1; //返回按鍵編碼。格式為2位數,高位為行號,低位為列號。
}

/////////////////////////////////////////////////////////////////////
//*************************************************************************************************
//*************************************************************************************************
//**<程序名>:計算器處理主程序,根據計算器的輸入狀態分派不同的函數對按鍵進行處理。 **
//**<功能>:當b_WorkMode=0是,若有鍵按下則調用此函數對鍵碼進行處理。 **
//*************************************************************************************************
//*************************************************************************************************

//*************************************************************************************************
//* *
//* ******************************頭文件及宏定義************************** *
//* *
//*************************************************************************************************
#include "CalReady.h"

//*************************************************************************************************
//* *
//* ********************************全局變數****************************** *
//* *
//*************************************************************************************************
extern unsigned long ul_Number; //LCE顯示數據,LCD實時顯示該數字。

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<工作模式(默認為計算器模式)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
extern bit b_WorkMode; //0--計算器模式;
//1--計時模式。
//定義在KeyProcess.c中。
unsigned char uc_ModeChange=0;

extern bit b_LCDClean;

extern unsigned char uc_ReportSymbol;

unsigned long ul_NumberOne=0; //第一個數
unsigned long ul_NumberTwo=0; //第二個數
unsigned char uc_Operator=0; //運算符
unsigned long ul_Result=0; //運算結果
unsigned char uc_NumPointer=1; //計算狀態

//*************************************************************************************************
//* *
//* *******************************計算器處理主函數****************************** *
//* *
//*************************************************************************************************

void vCalculator(unsigned char ucKeyCode)
{
if(ucKeyCode==41) //判斷按鍵是不是'NO/C'。
{
if(uc_NumPointer==1) //如果是『NO/C』鍵則判斷手機否是狀態一。
{
if(uc_ModeChange==2) //如果是狀態一則看uc_ModeChange是不是2。
{
uc_ModeChange=0; //如果是2則計時器模式。
b_WorkMode=1;

uc_ReportSymbol=3; //閃爍顯示:-CHAG-1。表明正在切換狀態。
b_LCDClean=1;
}
else
{
uc_ModeChange++; //如果uc_ModeChange不是2則加一。
ul_NumberOne=0; //清除所有數據,將所有數據恢復到狀態一。
ul_NumberTwo=0;
ul_Number=0;
uc_NumPointer=1;
}
}
else
{
ul_NumberOne=0; //清除所有數據,將所有數據恢復到狀態一。
ul_NumberTwo=0;
ul_Number=0;
uc_NumPointer=1;
}
}
else
{ //如果不是「NO/C」鍵,首先將uc_ModeChange清零。
uc_ModeChange=0;
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<根據不同狀態分派不同的鍵處理函數>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
switch(uc_NumPointer)
{
case 1:
vCalReadyOne(ucKeyCode); //進入狀態一。
break;
case 2:
vCalReadyTwo(ucKeyCode); //進入狀態二。
break;
case 3:
vCalReadyThree(ucKeyCode); //進入狀態三。
break;

default:break;
}
}

}

⑷ 求解釋單片機程序

這是一個 8位2進制數轉換成10進制顯示的程序,或者叫計算器。
改變的地方是為了模擬成功。低位在右。 1101B 轉換過來正好是13

;p3口接段碼a,b,c,d,e,f,g, p2.5-7口接位碼,選哪個數碼管顯示
a_bit equ 20h ;個位數存放處
b_bit equ 21h ;十位數存放處
org 0000H
SJMP main
ORG 0030H
main:
mov p0,#0ffh ;初始化p0口
loop: mov a,p0 ;將a中的十六進制數轉換成10進制
mov b,#10 ;10進制/10=10進制
div ab
mov b_bit,a ;十位在a
mov a_bit,b ;個位在b

mov dptr,#numtab ;指定查表啟始地址
mov a,a_bit ;取個位數
MOVC A,@A+DPTR ;查個位數的7段代碼
mov p3,a
acall d1ms
mov p2,#40h ;顯示個位數
acall d1ms
mov p2,#0ffh ;屏蔽所有顯示
acall d1ms

mov dptr,#numtab ;指定查表啟始地址
mov a,b_bit ;取十位數
MOVC A,@A+DPTR ;查十位數的7段代碼
mov p3,a
call d1ms
mov p2,#80h ;顯示十位數
acall d1ms
mov p2,#0ffh ;屏蔽所有顯示

SJMP loop
d1ms:
MOV R2,#200
DJNZ R2,$
nop
RET
numtab: DB 3FH,6H,5BH,4FH,66H,6DH,7DH,7H,7FH,6FH
end

你看這句, loop: mov a,p0 ;將a中的十六進制數轉換成10進制
把p0 送A 才開始的轉換 。 這可不是我加的。不知你說的fpga在哪裡。當然把p0改成fpga就是你說的那個功能了。
總之 理解成16進制轉換成2位10進制數再顯示就對了, 至於16進制數是哪來的 就全看在那用了吧。

⑸ 怎樣用51單片機做計算器啊

1、硬體模擬圖

4、程序源代碼

#include <reg51.h>#include <intrins.h>

#include <ctype.h>

#include <stdlib.h>

#define uchar unsigned char

#define uint unsigned int

uchar operand1[9], operand2[9];

uchar operator;

void delay(uint);

uchar keyscan();

void disp(void);

void buf(uint value);

uint compute(uint va1,uint va2,uchar optor);

uchar code table[] = {0xc0,0xf9,0xa4,0xb0,0x99,

0x92,0x82,0xf8,0x80,0x90,0xff};

uchar dbuf[8] = {10,10,10,10,10,10,10,10};

void delay(uint z)

{

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

uchar keyscan()

{

uchar skey;

P1 = 0xfe;

while((P1 & 0xf0) != 0xf0)

{

delay(3);

while((P1 & 0xf0) != 0xf0)

{

switch(P1)

{

case 0xee: skey = '7'; break;

case 0xde: skey = '8'; break;

case 0xbe: skey = '9'; break;

case 0x7e: skey = '/'; break;

default: skey = '#';

}

while((P1 & 0xf0) != 0xf0)

;

}

}

P1 = 0xfd;

while((P1 & 0xf0) != 0xf0)

{

delay(3);

while((P1 & 0xf0) != 0xf0)

{

switch(P1)

{

case 0xed: skey = '4'; break;

case 0xdd: skey = '5'; break;

case 0xbd: skey = '6'; break;

case 0x7d: skey = '*'; break;

default: skey = '#';

}

while((P1 & 0xf0) != 0xf0)

;

}

}

P1 = 0xfb;

while((P1 & 0xf0) != 0xf0)

{

delay(3);

while((P1 & 0xf0) != 0xf0)

{

switch(P1)

{

case 0xeb: skey = '1'; break;

case 0xdb: skey = '2'; break;

case 0xbb: skey = '3'; break;

case 0x7b: skey = '-'; break;

default: skey = '#';

}

while((P1 & 0xf0) != 0xf0)

;

}

}

P1 = 0xf7;

while((P1 & 0xf0) != 0xf0)

{

delay(3);

while((P1 & 0xf0) != 0xf0)

{

switch(P1)

{

case 0xe7: skey = '$'; break;

case 0xd7: skey = '0'; break;

case 0xb7: skey = '='; break;

case 0x77: skey = '+'; break;

default: skey = '#';

}

while((P1 & 0xf0) != 0xf0)

;

}

}

return skey;

}

void main()

{

uint value1, value2, value;

uchar ckey, cut1 = 0, cut2 = 0;

uchar operator;

uchar i, bool = 0;

init:

buf(0);

disp();

value = 0;

cut1 = cut2 = 0;

bool = 0;

for(i = 0;i < 9;i++)

{

operand1[i] = '';

operand2[i] = '';

}

while(1)

{

ckey = keyscan();

if(ckey != '#')

{

if(isdigit(ckey))

{

switch(bool)

{

case 0:

operand1[cut1] = ckey;

operand1[cut1+1] = '';

value1 = atoi(operand1);

cut1++;

buf(value1);

disp();

break;

case 1:

operand2[cut2] = ckey;

operand2[cut2+1] = '';

value2 = atoi(operand2);

cut2++;

buf(value2);

disp();

break;

default: break;

}

}

else if(ckey=='+'||ckey=='-'||ckey=='*'||ckey=='/')

{

bool = 1;

operator = ckey;

buf(0);

dbuf[7] = 10;

disp();

}

else if(ckey == '=')

{

value = compute(value1,value2,operator);

buf(value);

disp();

while(1)

{

ckey = keyscan();

if(ckey == '$')

goto init;

else

{

buf(value);

disp();

}

}

}

else if(ckey == '$')

{ goto init;}

}

disp();

}

}

uint compute(uint va1,uint va2,uchar optor)

{

uint value;

switch(optor)

{

case '+' : value = va1+va2; break;

case '-' : value = va1-va2; break;

case '*' : value = va1*va2; break;

case '/' : value = va1/va2; break;

default : break;

}

return value;

}

void buf(uint val)

{

uchar i;

if(val == 0)

{

dbuf[7] = 0;

i = 6;

}

else

for(i = 7; val > 0; i--)

{

dbuf[i] = val % 10;

val /= 10;

}

for( ; i > 0; i--)

dbuf[i] = 10;

}

void disp(void)

{

uchar bsel, n;

bsel=0x01;

for(n=0;n<8;n++)

{

P2=bsel;

P0=table[dbuf[n]];

bsel=_crol_(bsel,1);

delay(3);

P0=0xff;

}

}

(5)計算器代碼講解單片機擴展閱讀:

PROTEUS 是單片機課堂教學的先進助手

PROTEUS不僅可將許多單片機實例功能形象化,也可將許多單片機實例運行過程形象化。前者可在相當程度上得到實物演示實驗的效果,後者則是實物演示實驗難以達到的效果。

它的元器件、連接線路等卻和傳統的單片機實驗硬體高度對應。這在相當程度上替代了傳統的單片機實驗教學的功能,例:元器件選擇、電路連接、電路檢測、電路修改、軟體調試、運行結果等。

課程設計、畢業設計是學生走向就業的重要實踐環節。由於PROTEUS提供了實驗室無法相比的大量的元器件庫,提供了修改電路設計的靈活性、提供了實驗室在數量、質量上難以相比的虛擬儀器、儀表,因而也提供了培養學生實踐精神、創造精神的平台

隨著科技的發展,「計算機模擬技術」已成為許多設計部門重要的前期設計手段。它具有設計靈活,結果、過程的統一的特點。可使設計時間大為縮短、耗資大為減少,也可降低工程製造的風險。相信在單片機開發應用中PROTEUS也能茯得愈來愈廣泛的應用。

使用Proteus 軟體進行單片機系統模擬設計,是虛擬模擬技術和計算機多媒體技術相結合的綜合運用,有利於培養學生的電路設計能力及模擬軟體的操作能力;

在單片機課程設計和全國大學生電子設計競賽中,我們使用 Proteus開發環境對學生進行培訓,在不需要硬體投入的條件下,學生普遍反映,對單片機的學習比單純學習書本知識更容易接受,更容易提高。

實踐證明,在使用 Proteus 進行系統模擬開發成功之後再進行實際製作,能極大提高單片機系統設計效率。因此,Proteus 有較高的推廣利用價值。

⑹ 51單片機計算器

剛做過,發給你參考下
這是原理圖
51單片機簡易計算器程序:
#include <reg51.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
//---------定義引腳--------------------
bit clr=0;
bit ok=0;
bit xiaoshu=0;
bit jiego=0;
bit first_1=1;
bit first_2=1;
sbit dout = P3^2;
sbit load = P2^0;
sbit din = P2^1;
sbit dclk = P2^2;
sbit beer=P0^1;
sbit LCD1602_RS=P2^3;
sbit LCD1602_RW=P2^4;
sbit LCD1602_E=P2^5;
//---------定義變數--------------------
uchar ch451_key=0xff;
uchar yun_sign;
uchar xiabiao=0;
uchar tab[32];
uchar tab1[]={"welcome to use!"};
uchar tab2[]={" make by JunRu!"};
uchar tab3[]={"ERR0R"};
float opr_1=0,opr_temp=0,end=0,a;
//---------聲明函數--------------------
void ch451_init(void); //CH451初始化
void ch451_write(uint command);//寫命令或數據到ch451
uchar ch451_read(void); //讀按鍵值
uchar get_char(void);
void LCD_init(void);//初始化;
void delay(unsigned int k);//延時程序
void LCD_inter_command(unsigned char command);//寫入控制字
void LCD_inter_dat(unsigned char dat);//寫入要顯示的數據
void set_xy(unsigned char x,unsigned char y);//找地址
void write(unsigned char date);//寫入字元
void lcdbusy();//查忙時
void display(void);
void spec(void);
void get_end(void);
void hun_he(uchar n);
//-------- 主函數----------------------
void main()
{
uchar i;
LCD_init();//LCD初始化;
ch451_init();//CH451初始化
EA = 1;//打開中斷
LCD_inter_command(0x01);//清屏
for(i=0;i<=14;i++)
{
LCD_inter_dat(tab1[i]);
beer=0;
delay(4000);//延時
beer=1;
}
LCD_inter_command(0xc0);//從第二行開始顯示
for(i=0;i<=14;i++)
{
LCD_inter_dat(tab2[i]);
beer=0;
delay(4000);//延時
beer=1;
}
delay(0xffff);
delay(0xffff);
LCD_inter_command(0x01);
while(1)
{
if(ok)
{
display();
ok=0;clr=1;
}
}
}
//----------子函數--------------------
void hun_he(uchar n)
{int j;
switch(n)
{
case '+':opr_temp=opr_temp+opr_1;break;
case '-':opr_temp=opr_temp-opr_1;break;
case '*':opr_temp=opr_temp*opr_1;break;
case '/':
{
if(a==0)//減數為零顯錯
{ LCD_inter_command(0xc0);
for(j=0;j<=4;j++)
{
LCD_inter_dat(tab3[j]);
beer=0;
delay(4000);//延時
beer=1;
}
}
else
{opr_temp=opr_temp/opr_1;}
break;
}
default:break;}
}
void ch451_init(void)//CH451初始化
{
EX0 = 1;
din = 0;
din = 1;
ch451_write(0x403); //開顯示
ch451_write(0x580); //BCD解碼方式
}
void ch451_write(uint command)//寫命令或數據到ch451
{ uchar i;
EX0 = 0;
load = 0;
for(i=0;i<12;i++)
{
din = command&1;
dclk = 0;
command>>=1;
dclk = 1;
}
load = 1;
EX0 = 1;
}
uchar ch451_read(void)//讀按鍵值
{ uchar key=0x07;
uchar i;
EX0=0;
load = 0;
for(i=0;i<4;i++) //將0111讀入
{
din = key &1;
dclk = 0;
key>>=1;
dclk =1;
}
load = 1;
key = 0;
for(i=0;i<7;i++) //從CH451讀出按鍵值
{
key<<=1;
key|= dout;
dclk =0;
dclk =1;
}
EX0 =1;
return key;
}
void EX0_ISR(void)interrupt 0 //中斷程序
{
uchar temp;
ch451_key=ch451_read(); //將讀出的按鍵值賦給變數
spec();
if(clr) {LCD_inter_command(0x01);clr=0;}
temp=get_char();
if(temp){tab[xiabiao++]=temp; LCD_inter_dat(temp);}
if(xiabiao>=16)LCD_inter_command(0xc0);//若大於16,則從第2行開始顯示
if(ok) get_end();
beer=0;
delay(3000);
beer=1;
}
uchar get_char(void)
{
uchar dis=0;
uint temp=0,temp1=0;
switch(ch451_key)
{
case 0x40:dis='1';break;
case 0x41:dis='2';break;
case 0x42:dis='3';break;
case 0x48:dis='4';break;
case 0x49:dis='5';break;
case 0x4A:dis='6';break;
case 0x50:dis='7';break;
case 0x51:dis='8';break;
case 0x52:dis='9';break;
case 0x58:dis='0';break;
case 0x43:dis='+';break;
case 0x4B:dis='-';break;
case 0x53:dis='x';break;
case 0x5B:dis='/';break;
case 0x44:dis='!';break;
case 0x5A:dis='=';
ok=1; //遇到「=」,開始運算
break;
case 0x59:dis='.';break; //小數點
case 0x5C: //刪除鍵
LCD_inter_command(0x01);
xiabiao=0;
break;
default: break;
}
return dis;
}
void spec(void) //特殊功能鍵
{
switch(ch451_key)
{
case 0x4C:LCD_inter_command(0x10);{if(xiabiao>0)xiabiao-=1;}break; //左移
case 0x54:LCD_inter_command(0x14);{xiabiao+=1;}break; //右移
default:break;
}
}
void delay(unsigned int k)//延時程序
{
while (k--);
}
void LCD_inter_command(unsigned char command)//寫入控制字
{
delay(5000);
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_E=1;
P1=command;
LCD1602_E=0;
lcdbusy();
}
void LCD_init(void)//初始化;
{delay(5000);
LCD_inter_command(0x01);//清屏
delay(5000);
LCD_inter_command(0x38);//設置為8位的數據介面,兩行顯示,5、7點字元
delay(5000);
LCD_inter_command(0x0E);//顯示打開,游標開並閃爍
delay(5000);
}
void LCD_inter_dat(unsigned char dat)//寫入要顯示的數據
{
delay(5000);
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_E=1;
P1=dat;
LCD1602_E=0;
lcdbusy();
}
void lcdbusy()//查忙
{
P1=0xFF;
LCD1602_RS=0;
LCD1602_RW=1;
LCD1602_E=1;
while((P1&0x80)==1);
}
void display(void) //轉化在LCD上顯示計算結果
{
int temp=end; //浮點數
int i;
uint xiao_temp;
uint xx; //浮點數的整數部分
if (end>-32769&&end<32768)
{
xx=fabs(end);
xiao_temp=(fabs(end)-xx)*1000;//取出浮點數的小數部分
LCD_inter_command(0xc0);
if(end<0) LCD_inter_dat('-');beer=0;delay(4000); beer=1;//判斷是否為負數,若是則顯示負號
if(xx>9999) LCD_inter_dat((xx/10000)%10+'0'); beer=0;delay(4000);beer=1;
if(xx>999) LCD_inter_dat((xx/1000)%10+'0');beer=0;delay(4000);beer=1; //在LCD上顯示千位的數
if(xx>99)LCD_inter_dat((xx/100)%10+'0'); beer=0;delay(4000);beer=1;//百位
if(xx>9)LCD_inter_dat((xx/10)%10+'0');beer=0;delay(4000); beer=1;//十位
LCD_inter_dat(xx%10+'0');beer=0;delay(4000); beer=1;//個位
if(xiao_temp!=0) //顯示小數部分
{
LCD_inter_dat('.');beer=0;delay(4000);beer=1;
LCD_inter_dat((xiao_temp/100)%10+'0');beer=0;delay(4000);beer=1;
LCD_inter_dat((xiao_temp/10)%10+'0');beer=0;delay(4000);beer=1;
LCD_inter_dat(xiao_temp%10+'0');beer=0;delay(4000);beer=1;
}
}
else {LCD_inter_command(0xc0);//從第二行開始顯示
for(i=0;i<=4;i++)
{ LCD_inter_dat(tab3[i]);
beer=0;
delay(4000);//延時
beer=1;
}
}
}
void get_end(void)//計運算元程序
{ float xiaoshu=1;
uchar fu_flag=0;
uchar xiao_flag=0;
uchar lianji_sign;
uchar i=0;
uchar j;
uchar n;//正負標記符
while(i<=xiabiao)
{
while(tab[i]<=0x39&&tab[i]>=0x30)
{
n=0;
opr_1*=10;
opr_1+=tab[i++]-0x30;
n='+';
}
switch(tab[i])
{
case '.': xiao_flag=1;break;//遇到小數點跳到「if(xiao_flag)」里
case '!': fu_flag=1;break;
case '+': xiaoshu=1;yun_sign='+';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='+'; break;
case '-': xiaoshu=1;yun_sign='-';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='-'; break;
case 'x': xiaoshu=1;yun_sign='x';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='*';break;
case '/': xiaoshu=1;yun_sign='/';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);a=opr_1;opr_1=0;lianji_sign='/';break;
case '=':
switch(yun_sign)//進行運算
{
case '+':end=opr_temp+opr_1;break;
case '-':end=opr_temp-opr_1;break;
case 'x':end=opr_temp*opr_1;break;
case '/':{
if(a==0)//減數為零顯錯
{ LCD_inter_command(0xc0);
for(j=0;j<=4;j++)
{
LCD_inter_dat(tab3[j]);
beer=0;
delay(4000);//延時
beer=1;
}
}
else
{end=opr_temp/opr_1;}
break;
}
default:break;
}
ok=1;//開始進行顯示,標志位置1
xiabiao=0;//小數的標志位清零
break;
default:break;
}
i++;
if(xiao_flag)//表示小數
{
while(tab[i]<=0x39&&tab[i]>=0x30)
{
xiaoshu*=0.1;
switch(n)
{
case '+': opr_1=opr_1+(tab[i++]-0x30)*xiaoshu;break;
case '-': opr_1=opr_1-(tab[i++]-0x30)*xiaoshu; break ;
default:break; }
xiao_flag=0;
}
}

if(fu_flag)
{
while(tab[i]<=0x39&&tab[i]>=0x30)
{
n=0;
opr_1=-opr_1*10;
opr_1=-(opr_1+(tab[i++]-0x30));
n='-';
fu_flag=0;
}
}
}
opr_1=0;
opr_temp=0;
xiabiao=0;
xiaoshu=1;
}

⑺ 剛開始學習單片機,求解釋單片機簡單計算器的除法程序部分(最好每句都說明一下

else if(fuhao==4) //是否為4,
{
write_com(0x80+0x4f); //寫入命令。你的函數應該是液晶顯示的。
write_com(0x04); //一樣命令
i=0;
c=(long)(((float)a/b)*1000); //計算c的數據

while(c!=0) //判斷C如果不等於0.,其實是直到等於0就退出
{
write_date(0x30+c%10);
c=c/10; //10位一次運算
i++;
if(i==3) //設置小數點位數
write_date(0x2e); //寫數據
}
if(a/b<=0)
write_date(0x30); //寫數據
write_date(0x3d); //寫數據
a=0;b=0;flag=0;fuhao=0; //變數清零,
}

⑻ 用單片機設計簡易計算器

給你些子程序,自己看著湊吧。呵呵。有了這些,寫出來應該不難了。

;@@@@@@@@@雙位元組整數運算@@@@@@@@@@@@@@@@@@
;***********雙位元組無符號加法**************
;入口:R6(H),R7,R4(H),R5,出口:和R6(H),R7(L)
UADD: MOV A,R7
ADD A,R5
MOV R7,A
MOV A,R6
ADDC A,R4
MOV R6,A
RET
;***********雙位元組無符號減法**************
;入口:被減數R6(H),R7(L),減數R4(H),R5(L),出口:差R6(H),R7(L)
CLR C
MOV A,R7
SUBB A,R5
MOV R7,A
MOV A,R6
SUBB A,R4
MOV R6,A
RET
;***********雙位元組無符號乘法**************
;入口:R6(H),R7(L),R4(H),R5(L),出口:積R6(H),R7(L)
UMUL: MOV A,R7
MOV B,R5
MUL AB
MOV R0,B
XCH A,R7
MOV B,R4
MUL AB
ADD A,R0
XCH A,R6
MOV B,R5
MUL AB
ADD A,R6
MOV R6,A
RET

;***********雙位元組無符號除法*****************
;入口:R6(H),R7(L),R4(H),R5(L),出口:商R6(H),R7(L),余R4(H),R5(L)
;影響:R2,R3,
;堆棧需求:1
UDIV: CLR C
CLR A
MOV R2,A
MOV R3,A
MOV B,#10H
MOVBIT: MOV A,R7;R6、R7中數據左移一位到R2、R3中,C到R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
CLR C ;R2R3-R4R5
MOV A,R3
SUBB A,R5
PUSH Acc
MOV A,R2
SUBB A,R4
JBC Cy,MOVBIT0;不夠減,清C繼續左移
MOV R2,A;夠減,存回余數並置位C
POP Acc
MOV R3,A
SETB C
SJMP MOVBIT1
MOVBIT0: POP Acc
MOVBIT1: DJNZ B,MOVBIT
MOV A,R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R2
MOV R4,A
MOV A,R3
MOV R5,A
RET

(7) 標號: DIVD 功能:雙位元組二進制無符號數除法

入口條件:被除數在R2、R3、R4、R5中,除數在R6、R7中。
出口信息:OV=0 時,雙位元組商在R2、R3中,OV=1 時溢出。
影響資源:PSW、A、B、R1~R7 堆棧需求: 2位元組
DIVD: CLR C ;比較被除數和除數
MOV A,R3
SUBB A,R7
MOV A,R2
SUBB A,R6
JC DVD1
SETB OV ;溢出
RET
DVD1: MOV B,#10H ;計算雙位元組商
DVD2: CLR C ;部分商和余數同時左移一位
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
XCH A,R2
RLC A
XCH A,R2
MOV F0,C ;保存溢出位
CLR C
SUBB A,R7 ;計算(R2R3-R6R7)
MOV R1,A
MOV A,R2
SUBB A,R6
ANL C,/F0 ;結果判斷
JC DVD3
MOV R2,A ;夠減,存放新的余數
MOV A,R1
MOV R3,A
INC R5 ;商的低位置一
DVD3: DJNZ B,DVD2 ;計算完十六位商(R4R5)
MOV A,R4 ;將商移到R2R3中
MOV R2,A
MOV A,R5
MOV R3,A
CLR OV ;設立成功標志
RET

⑼ 51單片機計算器,運算部分和結果顯示怎麼寫

要求還不低,i簡單的我有,不能實現混合運算比較
主程序如下:
void main()
{ while(1)
{
c=1;
while(c<7)//輸入第1個6 位數
{
keyval=keyscan();
if(keyval<10)
{
switch(c)
{
case 1:b1=keyval; break;
case 2:b2=keyval; break;
case 3:b3=keyval; break;
case 4:b4=keyval; break;
case 5:b5=keyval; break;
case 6:b6=keyval; break;
}
c++;
}
display(b1,b2,b3,b4,b5,b6);
}
while(c==7) //輸入計算符號
{
keyval=keyscan();
if(keyval>=10)
{
d=keyval;
}
c=1;
}
while(c<7) //輸入第2個6 位數
{
keyval=keyscan();
if(keyval<10)
{
switch(c)
{
case 1:d1=keyval; break;
case 2:d2=keyval; break;
case 3:d3=keyval; break;
case 4:d4=keyval; break;
case 5:d5=keyval; break;
case 6:d6=keyval; break;
}
c++;
}
display(d1,d2,d3,d4,d5,d6);
}
P1=0;
bb= b1*100000+b2*10000+b3*1000+b4*100+b5*10+b6;
dd=d1*100000+d2*10000+d3*1000+d4*100+d5*10+d6;
while(keyval!=15) //等待按下"="號
{
keyval=keyscan();
}
delay(100);
switch(d1)//根據輸入的運算符,作不同的運算
{
case 10:ee=bb+dd; break;//加
case 11:
flag1=0;
if(bb>=dd)//減
{
ee=bb-dd;
flag1=1;;//flag 是正負號標志
}
else ee=bb-dd;
break;
case 12:ee=bb*dd; break;//乘
case 13:ee=bb/dd; break; //除
}
f1=ee/100000%10;;// 分離個十百千萬
f2=ee/10000%10;
f3=ee/1000%10;
f4=ee/100%10;
f5=ee/10%10;
f6=ee%10;
display(f1,f2,f3,f4,f5,f6);//顯示運算結果
}
}

⑽ 怎樣用51單片機做計算器啊

1、首先第一步就是要進行查找元器件並放入到原理圖中,如下圖所示。



(10)計算器代碼講解單片機擴展閱讀


電腦模擬:

單片機有了開發系統,隨著單片機的發展開發系統也在不斷發展。 keil是一種先進的單片機集成開發系統。

它代表著匯編語言單片機開發系統的最新發展,首創多項便利技術,將開發的編程/模擬/調試/寫入/加密等所有過程一氣呵成,中間不須任何編譯或匯編。

功能特性:

1、可以模擬63K程序空間,接近64K 的16位地址空間;

2、可以模擬64Kxdata 空間,全部64K 的16位地址空間;

3、可以真實模擬全部32 條IO腳;

4,完全兼容keilC51 UV2 調試環境,可以通過UV2 環境進行單步,斷點, 全速等操作;

5、可以使用C51語言或者ASM匯編語言進行調試 ;

6、可以非常方便地進行所有變數觀察,包括滑鼠取值觀察,即滑鼠放在某 變數上就會立即顯示出它此的值;

7、可選 使用用戶晶振,支持0-40MHZ晶振頻率;

8、片上帶有768位元組的xdata,您可以在模擬時選 使用他們,進行xdata 的模擬;

9、可以模擬雙DPTR 指針;

10、可以模擬去除ALE 信號輸出. ;

11、自適應300-38400bps 的所有波特率通訊;

12、體積非常細小,非常方便插入到用戶板中.插入時緊貼用戶板,沒有連接電纜,這樣可以有效地減少運行中的干擾,避免模擬時出現莫名其妙的故障;

13、模擬插針採用優質鍍金插針,可以有效地防止日久生銹,選擇優質園腳IC插座,保護模擬插針,同時不會損壞目標板上的插座. ;

14,模擬時監控和用戶代碼分離,不可能產生不能模擬的軟故障;

15、RS-232介面不計成本採用MAX202集成電路,串列通訊穩定可靠,絕非一般三極體的簡易電路可比。

功能限制:

模擬器佔用單片機串口及定時器2,與Keil C(PC)通訊,故不支持串口及定時器2 的模擬功能。全速運行時單片機串口及定時器2 可供用戶使用。

使用方法:

1、將模擬器插入需模擬的用戶板的CPU插座中,模擬器由用戶板供電;

2、將模擬器的串列電纜和PC機接好,打開用戶板電源;

3、通過Keil C 的IDE 開發模擬環境UV2 下載用戶程序進行模擬、調試。

閱讀全文

與計算器代碼講解單片機相關的資料

熱點內容
linuxoracle命令行登錄 瀏覽:224
android深度休眠 瀏覽:169
php微信開發例子 瀏覽:843
醫得app登錄密碼是什麼 瀏覽:140
spring開發伺服器地址 瀏覽:411
伺服器上如何查看伺服器的埠 瀏覽:678
單片機伺服器編譯 瀏覽:770
單口usb列印機伺服器是什麼 瀏覽:859
戰地五開伺服器要什麼條件 瀏覽:956
在word中壓縮圖片大小 瀏覽:255
javatomcat圖片 瀏覽:419
程序員生產智能創意 瀏覽:67
匯和銀行app怎麼登錄 瀏覽:383
騰訊伺服器如何上傳源碼 瀏覽:747
單片機的原理概述 瀏覽:512
火控pdf 瀏覽:269
如何復制雲伺服器centos環境 瀏覽:988
債權pdf 瀏覽:305
紅色番字的app怎麼下載 瀏覽:876
雲伺服器流程教課 瀏覽:704