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] = '