⑴ 单片机做计算器的程序
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] = '