A. 用單片機C語言編程做個計算器,求詳細代碼,一定要可用的,發到[email protected]謝謝。
#include <reg51.h>
#define uchar unsigned char
long First,End; //定義全局變數
void delay(int n) //***延時程序***//
{int i,j;
for(i=0;i<n;i++)
{for(j=0;j<50;j++)
;}
}
long add(long x,long y) //***加法程序***//
{long z;
z=x+y;
return(z);
}
long sub(long x,long y) //***減法程序***//
{long z;
if(x>=y)
z=x-y;
else
{z=y-x;
z=z+10e6;} //***最高位用1表示負數***//
return(z);
}
long mul(long x,long y) //***乘法程序***//
{long z;
z=x*y;
return(z);
}
long div(long x,long y) //***除法程序***//
{long z;
z=x/y;
return(z);
}
uchar kbscan(void) //***鍵盤掃描程序***//
{
uchar sccode;
P1=0xf0;
if((P1&0xf0)!=0xf0) //發全0行掃描碼,列線輸入
{ delay(222); //延時去抖
if((P1&0xf0)!=0xf0)
{sccode=0xfe; //逐行掃描初值
while((sccode&0x10)!=0)
{P1=sccode; //輸出行掃描碼
if((P1&0xf0)!=0xf0)
{
return(P1);} //如果檢測到有鍵按下,返回鍵值
else
sccode=(sccode<<1)|0x01; //行掃描碼左移一位
}
}
}
return(0); //無鍵按下,返回值為0
}
void display(void) //***顯示程序***//
{int i;
uchar code rel[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //數碼管選通
uchar code led[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b}; //定義0-9
uchar data num[8];
num[0]=First/10000000; //千萬位
num[1]=First/1000000%10; //百萬位
num[2]=First/100000%10; //十萬位
num[3]=First/10000%10; //萬位
num[4]=First/1000%10; //千位
num[5]=First/100%10; //百位
num[6]=First/10%10; //十位
num[7]=First%10; //個位
for(i=7;i>=0;i--)
{P3=rel[i]; //位選輸出
P2=led[num[i]]; //數據輸出
delay(2); //此延時必不可少?
}
}
void main(void) //***主程序***//
{ int k,n;
uchar f,g,key,gn1;
n=0;
f=0;
P0=0; //初始時指示燈滅
while(1) //不斷查詢是否有按鍵動作
{ key=kbscan(); //獲取返回鍵值
if(key!=0)
{
switch(key) //解碼,將對應按鍵返回值轉換為相應數值
{
case 0xee: k=0;break;//0
case 0xde: k=1;break;//1
case 0xbe: k=2;break;//2
case 0x7e: k=3;break;//3
case 0xed: k=4;break;//4
case 0xdd: k=5;break;//5
case 0xbd: k=6;break;//6
case 0x7d: k=7;break;//7
case 0xeb: k=8;break;//8
case 0xdb: k=9;break;//9
case 0xbb: k=10;First=0;End=0;f=0;break;//清除
case 0x7b: k=11;break;//等於
case 0xe7: k=12;f=1;break;//加
case 0xd7: k=13;f=2;break;//減
case 0xb7: k=14;f=3;break;//乘
case 0x77: k=15;f=4;break;//除
}
P0=1;
delay(280); //有按鍵時,指示燈的顯示時間
P0=0; //按鍵指示滅
if(k<10) //為數字鍵時(0-9)
{
if(f!=0) //為數字鍵時,如果已經有功能鍵按下
{
n++; //記錄數字鍵所按次數
gn1=0; //清除標志,再次為功能鍵時進行運算
g=f; //保存運算標志
if(n==1) //輸入為各位數時,直接賦值
First=k;
else if(n>1) //輸入為多位數時,將它轉化為10進制的多位數
First=First*10+k;
}
else //如果沒有功能鍵按下
{
n++;
gn1=1; //定義標志,當下一次為功能鍵時,停止數據輸入
if(n==1)
First=k;
else if(n>1)
First=First*10+k;
End=First; //將第一個數保存
}
}
else if(k>11) //為功能鍵時(+-*/)
{
if(gn1==1) //前一次數字鍵之後為功能鍵時
{
n=0; //清除計數標志
}
else //如果再次輸入功能鍵,則進行運算
{n=0; //清除計數標志
switch(g)
{case 1: First=add(End,First);break;
case 2: First=sub(End,First);break;
case 3: First=mul(End,First);break;
case 4: First=div(End,First);break;}
}
End=First; //保存本次結果
}
else if(k==11) //為等於號時(=)
{n=0;
gn1=1; //接著輸入為功能鍵時可以繼續運算
switch(g)
{case 1: First=add(End,First);break;
case 2: First=sub(End,First);break;
case 3: First=mul(End,First);break;
case 4: First=div(End,First);break;
}
End=First; //保存最終運算結果
f=0; //清除運算標志
}
}
display(); //調用顯示程序
}
}
這個吧!改些地方就能用
B. 用單片機設計簡易計算器
給你些子程序,自己看著湊吧。呵呵。有了這些,寫出來應該不難了。
;@@@@@@@@@雙位元組整數運算@@@@@@@@@@@@@@@@@@
;***********雙位元組無符號加法**************
;入口: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
C. 單片機計算器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;
}
}
}
D. 大神,求51單片機做簡易計算器的那個c語言程序
以下是我編的簡易計算器程序,基本成功
//4*4鍵盤檢測程序,按下鍵後相應的代碼顯示在液晶屏上
//顯示5位後,第6次顯示操作符號
//再顯示下一個數
// 鍵值與功能對應表
//鍵值 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//功能 0 1 2 3 4 5 6 7 8 9 + - × ÷ = 清零
#include<reg52.h>
sbit beep=P2^3;
sbit lcden=P3^4;
sbit rs=P3^5;
sbit rw=P3^6;
#define uint unsigned int
#define ulint unsigned long int
#define uchar unsigned char
#define lcddata P0
ulint bb,dd,ee,ff;
uchar d,flag1;
uchar fd1,fd2;
uchar b1=16,b2=16,b3=16,b4=16,b5=16;
uchar d1=16,d2=16,d3=16,d4=16,d5=16;
uchar f1=16,f2=16,f3=16,f4=16,f5=16,f6=16,f7=16,f8=16,f9=16,f10=16;
uchar key,keyval,c,temp;
void Delay1ms(uint i) //1ms延時程序
{
uint j;
for(;i>0;i--)
{
for(j=0;j<125;j++)
{;}
}
}
void write_com(uchar com)
{
lcddata=com;
rs=0;
rw = 0;
lcden=0;
Delay1ms(10);
lcden=1;
Delay1ms(10);
lcden=0;
}
void write_date(uchar date)
{
lcddata=date;
rs=1;
rw=0;
lcden=0;
Delay1ms(10);
lcden=1;
Delay1ms(10);
lcden=0;
}
void init2()
{
rw=0;
write_com(0x38);
Delay1ms(10);
write_com(0x0f);
Delay1ms(10);
write_com(0x06);
Delay1ms(10);
write_com(0x01);
Delay1ms(10);
}
void display1(uchar A1,uchar A2,uchar A3,uchar A4,uchar A5) //第1個數顯示程序
{
init2();
write_com(0x80);//第1行,第1字
Delay1ms(10);
write_date(0x30+A1);
Delay1ms(10);
write_date(0x30+A2);
Delay1ms(10);
write_date(0x30+A3);
Delay1ms(10);
write_date(0x30+A4);
Delay1ms(10);
write_date(0x30+A5);
Delay1ms(10);
}
void display2(uchar A1,uchar A2,uchar A3,uchar A4,uchar A5) //第2個數顯示程序
{
write_com(0x88);//第1行,第1字
Delay1ms(10);
write_date(0x30+A1);
Delay1ms(10);
write_date(0x30+A2);
Delay1ms(10);
write_date(0x30+A3);
Delay1ms(10);
write_date(0x30+A4);
Delay1ms(10);
write_date(0x30+A5);
Delay1ms(10);
}
void display3(uchar a) //操作符號顯示程序
{
write_com(0x86);//第1行,第1字
Delay1ms(10);
switch(a)
{
case 10:
write_date('+');
Delay1ms(10);
case 11:
write_date('-');
Delay1ms(10);
case 12:
write_date('x');
Delay1ms(10);
case 13:
write_date('/');
Delay1ms(10);
}
}
void display4(uchar A1,uchar A2,uchar A3,uchar A4,uchar A5,uchar A6,uchar A7,uchar A8,uchar A9,uchar A10,uchar A11,uchar A12) //結果顯示程序
{
write_com(0x80+0x40);//第2行,第1字
Delay1ms(10);
if (flag1==0)
{
write_date('-');
}
else write_date('+');
Delay1ms(10);
write_date(0x30+A1);
Delay1ms(10);
write_date(0x30+A2);
Delay1ms(10);
write_date(0x30+A3);
Delay1ms(10);
write_date(0x30+A4);
Delay1ms(10);
write_date(0x30+A5);
Delay1ms(10);
write_date(0x30+A6);
Delay1ms(10);
write_date(0x30+A7);
Delay1ms(10);
write_date(0x30+A8);
Delay1ms(10);
write_date(0x30+A9);
Delay1ms(10);
write_date(0x30+A10);
Delay1ms(10);
write_date('.');
Delay1ms(10);
write_date(0x30+A11);
Delay1ms(10);
write_date(0x30+A12);
Delay1ms(10);
}
uchar keyscan()
{
key=16;
P3=0xef;//P3.7輸出1個低電平
temp=P3; //讀取
temp=temp&0x0f;//屏蔽高4位
if(temp!=0x0f)
{
Delay1ms(10);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xed:
key=4;
break;
case 0xeb:
key=8;
break;
case 0xe7:
key=12;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xdf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay1ms(10);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xde:
key=1;
break;
case 0xdd:
key=5;
break;
case 0xdb:
key=9;
break;
case 0xd7:
key=13;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xbf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay1ms(10);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xbe:
key=2;
break;
case 0xbd:
key=6;
break;
case 0xbb:
key=10;
break;
case 0xb7:
key=14;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0x7f;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay1ms(10);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0x7e:
key=3;
break;
case 0x7d:
key=7;
break;
case 0x7b:
key=11;
break;
case 0x77:
key=15;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
return(key);
}
void main()
{ while(1)
{
c=1;
while(c<6)//輸入第1個5 位數
{
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;
}
c++;
}
display1(b1,b2,b3,b4,b5);
}
while(c==6) //輸入計算符號
{
keyval=keyscan();
if((keyval>=10)&&(keyval<14)) //可去一層括弧,因邏輯運算優先順序較低
{
d=keyval;
}
c=1;
display3(d);
}
while(c<6) //輸入第2個5 位數
{
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;
}
c++;
}
display2(d1,d2,d3,d4,d5);
}
bb= b1*10000+b2*1000+b3*100+b4*10+b5;
dd=d1*10000+d1*1000+d3*100+d4*10+d5;
while(keyval!=14) //等待按下"="
{
keyval=keyscan();
}
Delay1ms(10);
switch(d)
{
case 10:ee=bb+dd; break;//+
case 11:
flag1=1;
if(bb>=dd)
{
ee=bb-dd; //-
flag1=0;
}
else ee=dd-bb;
break;
case 12:ee=bb*dd; break;//*可能會溢出
case 13:ee=bb/dd; //除法小數部分會丟失,保留2位
ff=bb%dd;
fd1=ff*10/dd;
fd2=ff*100/dd%10;
break;
}
f10=ee/1000000000%10;
f9=ee/100000000%10;
f8=ee/10000000%10;
f7=ee/1000000%10;
f6=ee/100000%10;
f5=ee/10000%10;
f4=ee/1000%10;
f3=ee/100%10;
f2=ee/10%10;
f1=ee%10;
display4(f10,f9,f8,f7,f6,f4,f4,f3,f2,f1,fd1,fd2);
while(keyval!=15)
{
keyval=keyscan();
}
b1=0;b2=0;b3=0;b4=0;b5=0;
d1=0;d2=0;d3=0;d4=0;d5=0;
bb=0;dd=0;ee=0;
init2();
}
}
E. 單片機的簡易計算器
單片機計算器
基本功能介紹:
簡單的加減乘除的運算。
時間顯示功能,而且能實現計算器模塊和時間模塊之間的任意切換。
按鍵音卻換功能。
原理;
多功能單片機計算器是一個實現加減乘除的和時間功能的計算器,主要的硬體組成由,一個AT89s52單片機晶元,一個LED液晶(1602液晶),一個4*4鍵盤,和4個特殊功能按鍵。
一個時鍾晶元(DS1302),一個蜂鳴器。
單個硬體模塊個的介紹
AT89S52:
主要控制晶元,它是由8kflash,256BRAM,6個中斷源,詳情參考AT89S52的技術文檔.
1602液晶
1602液晶模塊內部的字元發生存儲器(CGROM)已經存儲了160個不同的點陣字元圖形,這些字元有:阿拉伯數字、英文字母的大小寫、常用的符號等,每一個字元都有一個固定的代碼,比如大寫的英文字母「A」的代碼是01000001B(41H),顯示時模塊把地址41H中的點陣字元圖形顯示出來,我們就能看到字母「A」,而且可以實現一些復雜的字元操作:1:清顯示,游標復位到地址00H位置,2:游標和顯示模式設置 游標移動方向,高電平右移,低電平左移,屏幕上所有文字是否左移或者右移。高電平表示有效,低電平則無效 3:顯示開關控制,控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示,控制游標的開與關,高電平表示有游標,低電平表示無游標,控制游標是否閃爍,高電平閃爍,低電平不閃爍4:游標或顯示移位,高電平時移動顯示的文字,低電平時移動游標5:功能設置命令 DL:高電平時為4位匯流排,低電平時為8位匯流排 N:低電平時為單行顯示,高電平時雙行顯示 F: 低電平時顯示5x7的點陣字元,高電平時顯示5x10的點陣字元(高低電平在相應的指令上實現),詳情可參考1602的技術文檔。
1602採用標準的16腳介面: 第1腳:VSS為地電源第2腳:VDD接5V正電源第3腳:V0為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高,對比度過高時會產生「鬼影」,使用時可以通過一個10K的電位器調整對比度第4腳:RS為寄存器選擇,高電平時選擇數據寄存器、低電平時選擇指令寄存器。第5腳:RW為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。當RS和RW共同為低電平時可以寫入指令或者顯示地址,當RS為低電平RW為高電平時可以讀忙信號,當RS為高電平RW為低電平時可以寫入數據。第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。 第7~14腳:D0~D7為8位雙向數據線。 第15~16腳:空腳。
1602液晶和單片機的接法
4*4鍵盤,和4個特殊功能按鍵
K(切換鍵) No(復位鍵)
(時間設置鍵) C(清除鍵) +
1 2 3 —
4 5 6 *
7 8 9 %(除)
—/+ 0 。 =
前4個為特殊功能鍵,
後十六個採用鍵盤掃描接法,
掃描原理:
首先給p3口賦11111110(0xfe),然後再讀取p3口的值,如果為11101110(0xee)說明是第一排第一個被按下,如果是11011110(0xde)說明是第一排第二個被按下,如果是10111110(0xbe)說明是第一排第三個被按下,如果是0111110(0x7e)說明是第一排第四個被按下,
判斷二三四排的按鍵,都採用同樣的方法,只要分別給P3口賦不同的值即可,在讀取p3口的值,在判斷。用這樣的方法即可實現4*4鍵盤的掃描,只要有鍵按下,就可以知道是那個鍵按下,通過這種方法可大大節省單片機的io口的資源。詳情可參考網上的鍵盤掃描原理
時鍾晶元(DS1302)
DS1302 是DALLAS 公司推出的涓流充電時鍾晶元內含有一個實時時鍾/日歷和31 位元組靜態RAM ,通過簡單的串列介面與單片機進行通信實時時鍾/日歷電路提供秒分時日日期月年的信息每月的天數和閏年的天數可自動調整時鍾操作可通過AM/PM 指示決定採用24 或12 小時格式DS1302 與單片機之間能簡單地採用同步串列的方式進行通信僅需用到三個口線1 RES 復位2 I/O 數據線3 SCLK串列時鍾時鍾/RAM 的讀/寫數據以一個位元組或多達31 個位元組的字元組方式
實時時鍾具有能計算2100 年之前的秒分時日日期星期月年的能力還有閏年調整的能力(詳情可參考DS1302的技術文檔
管腳描述
X1 X2 32.768KHz 晶振管腳
GND 地
RST 復位腳
I/O 數據輸入/輸出引腳
SCLK 串列時鍾
Vcc1,Vcc2 電源供電管腳
計算器工作大概流程
F. 51單片機1602顯示屏簡易計算器c語言代碼
1,首先得有個矩陣鍵盤
2,然後焊好線寫好驅動
3,實現內部演算法,頂多加減乘除4種了
4,1602顯示響應
一步一步做吧,說起來不難,做起來是很煩的哦
G. 單片機做計算器的程序
1、直接調用庫函數。
H. 單片機做的計算器(C語言代碼)
前段時間我自己寫的一個,你看看,先是電路圖,後面是代碼圖是用protues畫的,有什麼不懂加我QQ478769652 //程序測試通過
//能使用的功能:輸入K1(+,-,*,/)K2,按=得到結果,然後按on/c或0重新開始
//不能輸入K1+K2+K3或者類似的輸入,這種輸入導致程序出錯
//計算除法的時候不能顯示小數,如5/3得到的結果是1
#include<reg52.h>
unsigned char code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit P2_0=P2^0;
sbit P2_1=P2^1;
sbit P2_2=P2^2;
sbit P2_3=P2^3;
sbit P2_4=P2^4;
sbit P2_5=P2^5;
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_6=P3^6;
sbit P3_7=P3^7;long int n=0;
unsigned int flag;
void display();
void delay();
void keyboard();
main()
{
//m1,m2分別保存第一次和第二次輸入的兩個數據
//當m1,m2的輸入值超過999999時,此時將其情0
long int m1,m2;
P2=0xff;
while(1)
{
//檢測輸入的第一個數據
while(1)
{
display();
keyboard();
if(n>999999) n=0;
P3=0xf7;
if(P3_7==0) {flag=1; while(!P3_7); m1=n; n=0; break; }
P3=0xfb;
if(P3_7==0) {flag=2; while(!P3_7); m1=n; n=0; break; }
P3=0xfd;
if(P3_7==0) {flag=3; while(!P3_7); m1=n; n=0; break; }
P3=0xfe;
if(P3_7==0) {flag=4; while(!P3_7); m1=n; n=0; break; }
}
//檢測輸入的第二個數據
while(1)
{
display();
keyboard();
if(n>999999) n=0;
P3=0xf7;
if(P3_6==0) {m2=n; break;}
}
//計算結果,將其保存在n中然後進行顯示,注意當n的值太大超過4位元組時,此時顯示亂碼
while(1)
{
if(flag==1) n=m1+m2;
if(flag==2) n=m1-m2;
if(flag==3) n=m1*m2;
//由於類型原因,計算結果沒有小數
if(flag==4) n=m1/m2;
if(n>999999) n=0;
display();
P3=0xf7;
//計算完成之後,可以用on/c或者是0進行清0,然後進行下一輪計算
if(P3_4==0||P3_5==0) {n=0;break;}
}
}
}void keyboard()
{
//檢測第一行的按鍵
P3=0xfe;
if(P3_4==0)
{
n=n*10+7;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+8;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+9;
while(!P3_6);
}
//檢測第二行的按鍵
P3=0xfd;
if(P3_4==0)
{
n=n*10+4;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+5;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+6;
while(!P3_6);
}
//檢測第三行的按鍵
P3=0xfb;
if(P3_4==0)
{
n=n*10+1;
while(!P3_4);
}
if(P3_5==0)
{
n=n*10+2;
while(!P3_5);
}
if(P3_6==0)
{
n=n*10+3;
while(!P3_6);
} P3=0xf7;
if(P3_5==0)
{
n=n*10+0;
while(!P3_5);
}
}//顯示子程序
void display()
{
P0=tab[n%10];
P2_5=0;
delay();
P2_5=1; P0=tab[n/10%10];
P2_4=0;
delay();
P2_4=1; P0=tab[n/100%10];
P2_3=0;
delay();
P2_3=1; P0=tab[n/1000%10];
P2_2=0;
delay();
P2_2=1; P0=tab[n/10000%10];
P2_1=0;
delay();
P2_1=1; P0=tab[n/100000];
P2_0=0;
delay();
P2_0=1;
}
void delay()
{
int i;
for(i=0;i<500;i++);
}
I. 怎樣用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] = '