单片机C语言简易计算器
- 格式:doc
- 大小:56.85 KB
- 文档页数:15
单片机简易计算器的设计设计一个单片机简易计算器,我们首先需要明确计算器的功能和要求。
在这个设计中,我们将实现基本的四则运算功能和一些其他的功能,如开方、求倒数等。
我们将采用Keil C51来编写程序,并在STC89C52单片机上进行实现。
首先,我们需要定义一些输入和输出的接口。
我们将使用4个按键作为操作输入,它们分别是加、减、乘和除。
此外,我们还需要一个用于计算结果的显示屏,并使用一个7段数码管来显示输出结果。
在连接电路图中,我们需要将4个按键分别连接到P0口的4个IO引脚上,并将7段数码管的引脚连接到P2口。
此外,我们还需要将一个用于切换输入的按键连接到P1口。
接下来,我们将定义一些全局变量和函数来实现我们的计算器功能。
首先,我们需要定义一些常量,如加、减、乘和除的符号。
然后,我们需要定义一些变量来存储输入的数字和操作符号,以及存储计算结果的变量。
接下来,我们需要定义一些函数来实现不同的计算功能。
我们将实现加、减、乘和除的函数,并在这些函数中将数字和操作符号作为参数进行传递。
然后,我们需要定义一个主函数来对按键进行读取和执行不同的操作。
我们将使用一个无限循环来不断读取按键输入,根据不同的按键进行不同的操作。
在主函数中,我们还需要使用一个延时函数来防止按键的抖动效应。
最后,我们需要将计算结果显示在数码管上。
我们将编写一个函数来将计算结果转换为7段数码管上的数字,并将其显示出来。
在这个函数中,我们将使用一个循环来依次点亮不同的数码管段。
整个程序的流程如下:1.初始化所有的IO口2.定义常量和全局变量3.定义计算函数4.定义显示函数5.定义主函数-读取按键输入-根据不同的按键执行不同的操作-调用计算函数进行计算-调用显示函数显示结果在这个设计中,我们使用了一个简单的计算例子,这只是一个基础框架。
如果要实现更多功能,如开方、求倒数等,只需要在函数中进行相应的修改即可。
此外,我们还可以添加一些其他的功能,如存储和读取计算结果等。
单片机设计简易计算器单片机是指将整个计算机系统集成在一块芯片上的微处理器。
设计一个简易计算器,可以使用单片机实现各种基本运算,如加、减、乘、除以及开方等。
首先,我们需要选择单片机的类型和开发环境。
常用的单片机有51系列、AVR系列、ARM系列等。
根据具体需求,选择一种合适的单片机进行设计。
接下来,需要设计计算器的硬件电路。
计算器的核心部分是输入和输出部分,因此需要设计一个合适的显示屏和按键阵列。
一种常用的显示屏是数码管,可以显示数字和一些特殊字符。
按键阵列可以使用矩阵型按键。
在硬件设计完成后,需要进行软件编程。
首先要开发一个简单的操作系统,以便管理单片机的资源和任务。
然后,根据计算器的功能需求,在操作系统上开发相应的计算器应用程序。
计算器的软件程序主要包括以下几个模块:1.输入模块:通过按键阵列读取用户输入的数字和操作符,并且根据用户的输入进行相应的处理。
2.运算模块:根据用户输入的操作符进行相应的运算,包括加、减、乘、除以及开方等。
3.输出模块:将运算结果通过数码管显示出来。
以下是一个简单计算器的软件程序设计示例:```c#include <reg51.h>sbit row1 = P1^0;sbit row2 = P1^1;sbit row3 = P1^2;sbit col1 = P1^3;sbit col2 = P1^4;sbit col3 = P1^5;sbit col4 = P1^6;void delay(unsigned int ms)unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 112; j++);unsigned char keyscarow1 = 0; // 设置第一行为低电平row2 = 1;row3 = 1;if (col1 == 0) { delay(10); while(col1 == 0); return '1'; } if (col2 == 0) { delay(10); while(col2 == 0); return '2'; } if (col3 == 0) { delay(10); while(col3 == 0); return '3'; }if (col4 == 0) { delay(10); while(col4 == 0); return '+'; } row1 = 1;row2 = 0; // 设置第二行为低电平row3 = 1;if (col1 == 0) { delay(10); while(col1 == 0); return '4'; } if (col2 == 0) { delay(10); while(col2 == 0); return '5'; } if (col3 == 0) { delay(10); while(col3 == 0); return '6'; } if (col4 == 0) { delay(10); while(col4 == 0); return '-'; } row1 = 1;row2 = 1;row3 = 0; // 设置第三行为低电平if (col1 == 0) { delay(10); while(col1 == 0); return '7'; } if (col2 == 0) { delay(10); while(col2 == 0); return '8'; } if (col3 == 0) { delay(10); while(col3 == 0); return '9'; } if (col4 == 0) { delay(10); while(col4 == 0); return '*'; } return 0;void display(unsigned char number)P2 = number;void maiunsigned char num1 = 0, num2 = 0, result = 0; unsigned char operator = 0;while (1)num1 = keyscan(;if (num1 == '+')operator = '+';} else if (num1 == '-')operator = '-';} else if (num1 == '*')operator = '*';} else if (num1 != 0)while (1)num2 = keyscan(;if (num2 != 0)break;}}if (operator == '+')result = num1 + num2;} else if (operator == '-')result = num1 - num2;} else if (operator == '*')result = num1 * num2;}display(result);}}```以上程序是一个简单的计算器程序示例。
/*...............菜鸟一枚,不好勿喷→_→............................【简易计算器的功能简介】【时间紧,先做个简易的吧,复杂的算法太难,没那么多时间写【现在也不太会→_→】,以后再研究→_→】此程序是完全基于开发板的,可在板子上直接测试【程序跑飞的概率比较大,还不太明白是哪的问题】可实现总数小于等于九位【long int】的数字的加减乘除运算【每次只能进行一项】,可清楚修改输入的数据,由于键盘等因素显示【4X4】,没有小数点键,故无法直接进行小数运算,进行除法运算时,小数点后最多可保留6位,第7位进行四舍五入。
显示器采用1602,输入或修改时开光标并闪烁,输入数据超出9位,有警告提示,加上运算符总的输入不超过15位【超过10输入逻辑已经错误】。
显示结果时关光标【重复按下时结果不变】,显示结果后,也可对输入端进行修改,按下等于键再次显示结果。
2015/1 qq:1036894850 */#include"reg52.h"#include"stdio.h"#define uchar unsigned charsbit rs=P2^4;//lcd的控制线口sbit rw=P2^5;sbit ep=P2^6;uchar ip[15];//存输入的数据,15位【理论上10位就够了】'$'记运算符'*'记为负号uchar sign;//存运算符int k=0,equ=0,sk=0,ksk=0,sg=0;void write_data(uchar dat); //给1602写数据void write_com(uchar com);void lcdinit();void delay(int z);void warn();void key_deal(uchar key);void sdeal(uchar i);void key_sub_deal();void key_equ_deal();void key_del_deal();uchar scankey();void main(){uchar key=0xff;lcdinit(); //1602初始化,结果输出位显示0,数据输入位光标闪烁。
STC89c52单片机计算器C语言程序STC89C52单片机计算器C语言程序下面是STC89C52单片机计算器的C语言程序,适用于P2位选P0段选时钟12MHZ。
程序代码如下:includedefine uchar unsigned chardefine uint unsigned intuchar Led[17] = {0x3f。
0x06.0x5b。
0x4f。
0x66.0x6d。
0x7d。
0x07.0x7f。
0x6f。
0x77.0x7c。
0x39.0x5e。
0x79.0x71.0x00};long float Number[]={0,0,0,0};uchar A[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};long int D[] = {0,0,0,0,0,0,0,0};uchar code C[] = {0x0.0xFE。
0xFD。
0xFB。
0xF7.0xEF。
0xDF。
0xBF。
0x7F};uchar k=16;uchar b;long float Out_put;uchar e=0;uchar g=0;uchar L=0;uchar g1=0;uchar g2=0;uchar g3=0;uchar g4=0;char j=-1;uchar m=0;uchar n=0;uchar x=0;程序中包含了头文件和宏定义,以及数码管段选、数码管显示位控制寄存器、数码管显示内容寄存器、数码管位选、按键控制变量等各种变量。
其中,Led数组存储了数码管的段选值,Number数组存储了数字,A数组存储了数码管的位选值,D数组存储了数码管的显示内容,C数组存储了数码管的位选值,k、b、Out_put、e、g、L、g1、g2、g3、g4、j、m、n、x 等变量用于按键控制和运算。
代码中没有明显的格式错误,可以直接使用。
下面是已经修改过的文章:uchar xo = 0./*控制开始计数小数点的变量*/long int result;void Delay(uint o) {uint i。
C语⾔实现简易计算器(可作加减乘除)C语⾔实现简易计算器(加减乘除)计算器作为课设项⽬,已完成答辩,先将代码和思路(注释中)上传⼀篇博客已增添、修改、整理⾄⽆错且可正常运⾏虽使⽤了栈,但初学者可在初步了解栈和结构语法后理解代码#include <stdlib.h>#include <stdio.h>#include <string.h>#define IsDouble 0#define IsChar 1//_______________________________________________________________________________________________________________________________________________________ //1.⽀持浮点数和字符的栈typedef struct {char * buffer;int typesize;int top;int max;} stack;stack * CreateStack(int max, int typesize);//创建⼀个栈void DestroyStack(stack *);//释放栈的空间void ClearStack(stack *);//清空栈int Push(stack *, void *);//⼊栈int Pop(stack *, void *);//出栈int GetSize(stack *s);//得到栈的⼤⼩int GetTop(stack *, void *);//找到栈顶int IsEmpty(stack *);//判断是否为空栈,空则下溢int IsFull(stack *);//判断栈是否已满,满则溢出stack * CreateStack(int max, int typesize){stack * s = (stack*)malloc(sizeof(stack));//为栈s malloc内存if (!s) return 0;//为结构中buffer元素malloc内存s->buffer = (char *)malloc(sizeof(char) * max * typesize);if (!s->buffer) return 0;//初始化结构中的栈顶,最⼤值,类型⼤⼩s->top = -1;s->max = max;s->typesize = typesize;return s;}void DestroyStack(stack* s){free(s->buffer);//先释放buffer的空间free(s);//在释放s的空间}void ClearStack(stack * s){s->top = -1;//清空栈(栈头位置归零)}int Push(stack * s, void * data){if (IsFull(s)) return 0;//如果栈已满则return 0,防⽌溢出//栈未满则将栈头移动打动下⼀位置,并将data中的元素拷⼊栈中buffer的第top位置s->top++;memcpy(s->buffer + s->top*s->typesize, data, s->typesize);//⼊栈成功return 1return 1;}int Pop(stack * s, void * data){if (IsEmpty(s)) return 0;//出栈判断栈是否为空,若为空则return 0//栈未空则将buffer中top位置的字符拷⼊data记录,并让栈头向前移动⼀个位置memcpy(data, s->buffer + s->top*s->typesize, s->typesize);s->top--;//成功则return 1return 1;}int GetSize(stack *s){return s -> top+1;//栈头位置+1得到⼤⼩}int GetTop(stack *s, void * data){if (IsEmpty(s)) return 0;//如果栈空return 0//栈不为空则将top位置的字符拷回data记录,得到栈头memcpy(data, s->buffer + s->top*s->typesize, s->typesize);//成功则return 1;return 1;}int IsEmpty(stack * s){return s->top == -1;//如果top为-1则栈空}int IsFull(stack * s){return s->top == s->max-1;//如果top为max-1则栈满}//___________________________________________________________________________________________________________________________________________________ //2.定义⼀个cal类型,其中data存数时sign为IsDouble,存字符时,sign为Ischartypedef struct {double data;char sign;} cal;//3.查找对应符号(找到则返回该符号下标)(找不到则说明该部分为数字返回-1)int SearchCode(char ch){char * code = "+-*/()@";//@为终⽌符,算式输⼊结束int index = 0;//while (code[index]){if (code[index] == ch) return index;index++;}return -1;}//4.得到两个符号间的优先级//与SearchCode相对应,char GetPriority(char ch, char next){//创建⼀个perferen表,第i⾏(列)对应SearchCode函数中code中的第i个字符char perferen[7][7] = {">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<=E",">>>>E>>","<<<<<E="};//找到两个形参对应的字符int c = SearchCode(ch);int n = SearchCode(next);//如果找不到对应运算符(字符不是运算符⽽是为数字)return Eif (c==-1 || n==-1) return 'E';//如果找到两个对应运算符则按照优先级表返回两个运算符的优先级return perferen[c][n];}//5.四则运算double add(double a, double b) { return a+b; }double sub(double a, double b) { return a-b; }double mul(double a, double b) { return a*b; }double ddiv(double a, double b) { return a/b; }//整合四种运算double calcu(double a, char ch, double b){double (*calculation[4])(double,double) = {add,sub,mul,ddiv};return calculation[SearchCode(ch)](a,b);}//6.检测字符串int CheckStr(char * buffer){int n;//遍历字符串确保算式中⽆⾮法字符若检测到⾮法字符return 0,若都合法则return 1for (n = 0;buffer[n];n++){if ((SearchCode(buffer[n]) != -1 || buffer[n] == '.' || (buffer[n] >= '0' && buffer[n] <= '9')) && buffer[n] != '@') continue;else return 0;}buffer[n] = '@';//加上终⽌符,表⽰算式结束buffer[n+1] = '\0';return 1;}//7.得到数据转化为double类型存⼊rsint GetDigit(char * buffer, int * n, double * rs){char str[30];int i,j = 0;for (i = 0;SearchCode(buffer[*n]) == -1;i++){str[i] = buffer[*n];//从*n位置开始,将这⼀串数字字符存⼊str(*n)++;}str[i] = '\0';for (i = 0;str[i];i++){if (str[i] == '.') j++;}//如果⼀段⼩数有多个⼩数点或⼩数点在数字⾸尾,return 0if (j>1 || str[i-1] == '.' || str[0] == '.') return 0;//rs接收转化为double的数据*rs = atof(str);//操作成功return 1return 1;}//8.将⽤户输⼊的buffer字符串转化为可供程序运算的calstr数组int resolu(char * buffer, cal * calstr){int i = 0, j = 0;cal c;while (buffer[i]){if (SearchCode(buffer[i]) == -1){//如果得到数据不成功则return 0if (GetDigit(buffer,&i, &c.data) == 0) return 0;//如果成功得到数据则在c.sign标记为浮点数c.sign = IsDouble;//将c存⼊数组calstr中calstr[j++] = c;}else{//若符号为运算符//判断正负号if (buffer[i] == '-' && (buffer[i-1] == '('||buffer[i-1] == '+'||buffer[i-1] == '-'||buffer[i-1] == '*'||buffer[i-1] == '/') || (i==0 && buffer[0] == '-')){ i++;if (GetDigit(buffer,&i, &c.data) == 0) return 0;//在符号的下⼀位开始查找,若找不到数字return 0//否则,给数字取相反数,c.sign标记为浮点数,存⼊calstr中c.data = 0 - c.data;c.sign = IsDouble;calstr[j++] = c;} else//如果是正号,与符号处理⽅式同理if (buffer[i] == '+' && (buffer[i-1] == '('||buffer[i-1] == '+'||buffer[i-1] == '-'||buffer[i-1] == '*'||buffer[i-1] == '/') || (i==0 && buffer[0] == '+')){ i++;if (GetDigit(buffer, &i, &c.data) == 0) return 0;c.sign = IsDouble;calstr[j++] = c;}else{//如果不是正负号,则为运算符,先强制转换为double类型存在c.data⾥,然后c.sign标记为char类型,存⼊calstrc.data = (double)buffer[i++];c.sign = IsChar;calstr[j++] = c;}}}//操作蔡成功则return 1return 1;}//9.计算出结果int result(cal * calstr, double * rs){stack * pst = CreateStack(100,sizeof(char));//运算符栈stack * pnd = CreateStack(100,sizeof(double));//数据栈double num1,num2;int n = 0;char ch = '@';Push(pst, &ch);//在转换得到的calstr中遍历直到终⽌符'@"while(ch != '@' || !(calstr[n].sign == IsChar && (char)calstr[n].data == '@')){//如果calstr的n位上是浮点数,则将这个data压栈进⼊数据栈pnd中if (calstr[n].sign == IsDouble){Push(pnd, &(calstr[n].data));n++;}//反之,如果是运算符,则要检测优先级else{switch( GetPriority(ch, (char)calstr[n].data)){//如果运算符优先级较⼩,则让ch等于优先级⼤的符号并压⼊符号栈pst中case '<':ch = (char)calstr[n].data;Push(pst, &ch);n++;break;//如果结果为等号,让符号出栈暂存到ch中case '=':if (!Pop(pst, &ch)) return 0;n++;break;//如果ch优先级较⾼,则将前两个数字及运算符出栈,分别储存⾄num2,ch,num1中,进⾏运算,得到的结果再次压栈进⼊pnd中 case '>':if (!(Pop(pnd,&num2) && Pop(pst,&ch) && Pop(pnd,&num1))) return 0;num1 = calcu(num1,ch,num2);Push(pnd, &num1);break;//如果符号顺序出错,return 0case 'E':return 0;}}//检测是否可以得到栈顶符号,栈空则return 0if (!GetTop(pst, &ch)) return 0;}//如果栈中得到了最终结果,并且取出pnd中的最终结果到rs,return 1if (GetSize(pnd) == 1 && GetTop(pnd,rs)){DestroyStack(pst);DestroyStack(pnd);return 1;}//否则 return 0else{return 0;}}//10.⽤户交互函数void treatment(){char buffer[100];//⽤户输⼊的字符串(算式)cal calstr[50];//计算⽤的数组double rs = 0;//计算结果printf("Enter your equation:");gets(buffer);//让⽤户输⼊算式buffer//⽤户不输⼊"exit"就不退出while (!(buffer[0]=='e' && buffer[1]=='x' && buffer[2]=='i' && buffer[3]=='t')){//检查buffer中字符君合法,成功将buffer转化为⽤于计算的calstr数组,成功计算出结果存⼊rsif (CheckStr(buffer) && resolu(buffer,calstr) && result(calstr,&rs)){printf("\n%lf\n",rs);}else{printf("\nError!\n");}printf("Enter \"exit\"to quit");printf("\nEnter your equation:");gets(buffer);//再次让⽤户输⼊算式}printf("\nbye\n");}//11.主函数int main(){treatment();}参考⽂献链接如下[参考⽂献]()。
C语言简易计算器的实现C语言简易计算器是一种用于进行基本数学运算的程序。
实现一个简易计算器的关键是要能够解析用户输入的数学表达式,并将其转化为计算机可以理解的形式,然后进行计算,并输出结果。
下面是一个大约1200字以上的示例实现。
```c#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#include <ctype.h>#define MAX_SIZE 100//定义操作符的优先级int getPriority(char op)if (op == '+' , op == '-')return 1;else if (op == '*' , op == '/')return 2;elsereturn 0;//进行四则运算int calculate(int a, int b, char op)switch (op)case '+': return a + b;case '-': return a - b;case '*': return a * b;case '/': return a / b;default: return 0;}//将中缀表达式转换为后缀表达式void infixToPostfix(char* infixExp, char* postfixExp) char stack[MAX_SIZE];int top = -1;int j = 0;for (int i = 0; infixExp[i] != '\0'; i++)if (isdigit(infixExp[i])) { // 数字直接输出到后缀表达式while (isdigit(infixExp[i]))postfixExp[j++] = infixExp[i++];}postfixExp[j++] = ' ';i--;}else if (infixExp[i] == '(') { // 左括号压入栈stack[++top] = infixExp[i];}else if (infixExp[i] == ')') { // 右括号弹出栈内所有操作符并输出到后缀表达式,直到遇到左括号while (top != -1 && stack[top] != '(')postfixExp[j++] = stack[top--];postfixExp[j++] = ' ';}top--; // 弹出栈顶的左括号}else { // 操作符while (top != -1 && getPriority(stack[top]) >=getPriority(infixExp[i]))postfixExp[j++] = stack[top--];postfixExp[j++] = ' ';stack[++top] = infixExp[i];}}while (top != -1) { // 将栈内剩余操作符弹出并输出到后缀表达式postfixExp[j++] = stack[top--];postfixExp[j++] = ' ';}postfixExp[j] = '\0';//计算后缀表达式的值int evaluatePostfix(char* postfixExp)char stack[MAX_SIZE];int top = -1;for (int i = 0; postfixExp[i] != '\0'; i++)if (isdigit(postfixExp[i])) { // 数字压入栈int num = 0;while (isdigit(postfixExp[i]))num = num * 10 + (postfixExp[i++] - '0');stack[++top] = num;i--;}else if (postfixExp[i] == ' ')continue;}else { // 操作符,弹出栈顶的两个数进行计算,并将结果压入栈int b = stack[top--];int a = stack[top--];int result = calculate(a, b, postfixExp[i]);stack[++top] = result;}}return stack[top];int maichar infixExp[MAX_SIZE];printf("请输入中缀表达式:");fgets(infixExp, sizeof(infixExp), stdin); // 读取用户输入//将中缀表达式转换为后缀表达式char postfixExp[MAX_SIZE];infixToPostfix(infixExp, postfixExp);printf("后缀表达式为:%s\n", postfixExp);//计算后缀表达式的值并输出int result = evaluatePostfix(postfixExp);printf("计算结果为:%d\n", result);return 0;```这个简易计算器的实现基于栈的数据结构。
51单片机简易计算器#include<reg51.h>#include<math.h>#define uchar unsigned char #define uint unsigned int sbit beep=P2^3;sbit dula=P2^6;sbit wela=P2^7;sbit rw=P1^1;sbit rs=P1^0;sbit lcden=P2^5;void yunsuan();void keyinput(char s);void write_data(char ddata);void write_com(char command);void display(long a);void init();void dealerror();void dataoverflow();void welcome();char code table1[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};char code table2[]="789/456*123-.0=+";char j,k,temp,temp1,temp2,key,mchar,m,flag2=0,flag3=0; long x,y,num;int operators,input,iny;char error[5]="error";char overflow[8]="overflow";char welcome_[16]="welcome to use !";void delay(uint x)//延时{uint a,b;for(a=x;a>0;a--)for(b=10;b>0;b--);}void delay_ms(uint x)//延时{uint a,b;for(a=x;a>0;a--)for(b=110;b>0;b--);}void write_com(uchar com)//写命令{P0=com;rs=0;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void write_data(uchar date)//写数据{P0=date;rs=1;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}long ming(int x){long m;switch(x){case 9:m=1000000000;return m;break; case 8:m=100000000;return m;break; case 7:m=10000000;return m;break; case 6:m=1000000;return m;break; case 5:m=100000;return m;break; case 4:m=10000;return m;break; case 3:m=1000;return m;break;case 2:m=100;return m;break;case 1:m=10;return m;break; case 0:m=1;return m;break; }}void display(long a){long d;int i,flag1=0,temp,c=-1;init();if(a<0){a=a*c;write_data('-');}for(i=9;i>=0;i--){d=ming(i);temp=a/d;a=a%d;if((temp==0)&&(flag1==0)) ;else{write_data(0x30+temp);flag1=1;}if(i==2){write_data('.');flag1=1;}}}void init()//LCD初始化{rw=0;dula=0;wela=0;write_com(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口delay(20);write_com(0x0e); //显示模式设置delay(20);write_com(0x06); //显示模式设置:光标右移,字符不移delay(20);write_com(0x01); //清屏幕指令,将以前的显示内容清除delay(20);}void yunsuan() // 运算{if (iny){switch(operators){case 1:x=x+y;num=x;if(num<10000000000&&num>-10000000000){display(num);}elsedataoverflow();break;case 2:x=x-y;num=x;if(num<10000000000&&num>-10000000000) {display(num);}elsedataoverflow();break;case 3:x=x*y;num=x/100;if(num<10000000000&&num>-10000000000) {display(num);}elsedataoverflow();break;case 4:if (y==0)dealerror();else{if(y<100){x=x*100;y=y*100;}y=y/100;x=x/y;num=x;if(num<10000000000&&num>-10000000000) {display(num);}elsedataoverflow();}break;}y=0;}}void dealerror()//除数为0{int i=0;write_com(0x01);for(i=0;i<5;i++)write_data(error[i]);}void dataoverflow()//数值溢出{int i=0;write_com(0x01);for(i=0;i<8;i++)write_data(overflow[i]);}void welcome()//欢迎界面{int i=0;write_com(0x01);for(i=0;i<16;i++)write_data(welcome_[i]);}void keyinput(char s) //键盘输入{if(s<='9'&&s>='0') //判断按下的键是否为数值{if(flag3==0)num=num*10+100*(s-'0');elsenum=num*10+10*(s-'0');if(flag2==1){num=num/10;flag3=1;}if (operators>0){y=num;iny=1;}elsex=num;if(num<10000000000&&num>-10000000000) //当前数值是否超出限定范围display(num);elsedataoverflow();}elseswitch(s){case '.':/*iny=0;operators=0;*/flag2=1;break;case '=':write_data(table2[14]); delay(10);yunsuan();iny=0;operators=0;num=0;flag2=0;flag3=0;break;case '+':if (operators) yunsuan();operators=1;write_data(table2[15]); num=0;flag2=0;flag3=0;break;case '-':if (operators) yunsuan(); operators=2;write_data(table2[11]); num=0;flag2=0;flag3=0;break;case '*':if (operators) yunsuan(); operators=3;write_data(table2[7]); num=0;flag2=0;flag3=0;break;case '/':if (operators) yunsuan(); operators=4;write_data(table2[3]); num=0;flag2=0;flag3=0;break;}}void main() //主函数{char i;char flag0=1;init();welcome();for(i=0;i<10;i++) delay_ms(100);init();while(1){P3=0xf0;temp1=P3;P3=0x0f;temp2=P3;temp=temp1|temp2; while(P3!=0x0f) {beep=0;}beep=1;for(i=0;i<16;i++) {if(temp==table1[i]) {m=table2[i];flag0=0;}}if(flag0==0) {keyinput(m); flag0=1;}}}。
课程设计报告单片机原理及应用课程名称简易计算器设计设计题目专业班级名姓号学1.项目概述中国古代最早采用的一种计算工具叫算筹。
这种算筹多用竹子制成,也有用木头,兽骨充当材料的。
约二百七十枚一束,放在布袋里可以随身携带。
17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的“纳皮尔算筹”,英国牧师奥却德发明了圆柱形对数计算尺,这种计算尺不仅能做加减乘除,乘方,开方运算,甚至可以计算三角函数,指数函数和对数函数,这些计算工具不仅带动了计算器的发展,也为现代计算器发展奠定了良好的基础,成为现代社会应用广泛的计算工具。
2.项目要求基于AT89C51单片机的简易计算器,设计要求如下:(1)计算器至少能正常显示8位数。
(2)开机时,显示“0”(3)计算器能对整数进行简单的加减乘除四则运算,在做除法时能自动舍去小数部分(4)运算结果超过可显示的位数时能进行出错提示。
3.小组人员组成及分工4.系统设计1.框图设计八位七段数码管显示AT89C51按键录入模块(0-9录入+-*/=c)5.硬件设计(1)电路原理图:(2)元件清单:6.软件设计(1)算法流程图:主函数录入数值调用运算程序结束显示函数中断结束按键函数行扫描列扫描赋值给变量运算查值(2)程序清单:#include<reg51.H>/***按键程序***/char keyscan();/***显示程序***/void display();char dsp[9]={0,0,12,12,12,12,12,12,12}; //初始化显示数组/***计算程序***/void calculate(char k,char c1[8],char c2[8]);/***片选***/unsigned char code Select[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};/***码选***/unsigned char code LED_CODES[]={0xC0,0xF9,0xA4,0xB0,0x99, //0-40x92,0x82,0xF8,0x80,0x90, //5-90x86,0xAF,0xFF,0x7F,0xBF,}; //E,r,空格,.,-/***main函数***/void main(void){char i,j,k,c;char a[8],b[8];/***定时1ms***/TMOD=0;//TL0=-(1000/256);//TH0=-(1000%6);总中断开关EA = 1; //ET0 = 1; //开中断TR0 = 1; // 启用计数器0LR:do{for(i=1;i<9;i++) //数字录入循环{dsp[0]=keyscan();if(c==2&&dsp[0]<10) //此段代码验证是否有旧的计算结果在显示,且不再参与新计算{dsp[1]=dsp[0];for(j=2;j<9;j++)dsp[j]=12;c=0;}else if(c==2&&dsp[0]>9) // 旧的计算结果将参与新的计算,作为第一个数{c=0;}if(dsp[0]==0&&dsp[1]==0&&dsp[2]==12) //个位为0且十位为空时按下0,按键无效,跳回LR等待正确输入{/***goto跳转标志***/goto LR;}else if(dsp[0]>9) break; //有操作符按下,跳出数字录入循环else{for(j=i;j>0;j--)dsp[j]=dsp[j-1]; //移位,以正确显示数字}}if(i==9) //判断是否输入8 个有效数字,是则等待操作符,否则直接判断操作符{do // 使用do while无论是否第一个数都取一次操作符{dsp[0]=keyscan(); // 获取操作符号if(dsp[0]==14||dsp[0]<10) //按下C或者第9位数字清零{dsp[1]=0;for(i=2;i<9;i++)dsp[i]=12;c=0;}}while((dsp[0]==15)&&(c==0)); //等号被按下,等待新的操作符(仅对第一个数字有效)}else if(dsp[0]==14) //按下C清零{dsp[1]=0;for(i=2;i<9;i++)dsp[i]=12;c=0;}while(dsp[0]==15&&c==0) //未输满8位且是第一个数字即按下等号,等待非等号操作符{dsp[0]=keyscan(); //获取操作符号if(dsp[0]==14||dsp[0]<10) //按下C或者数字都进行清零,重新输入a{dsp[0]=14; //将dsp[0]置为14,防止因数字清零未能拦截dsp[1]=0;for(i=2;i<9;i++)dsp[i]=12;c=0;}}}while(dsp[0]==14); //数字输入未完成即按下C,重新等待输入do{if(c==0) //没有数字输入{k=dsp[0]; //存计算符(循环内已排除C、=、数字)for(i=0;i<8;i++) // 将第一个数存入a[8]{a[i]=dsp[i+1];}dsp[1]=0; // 清零for(i=2;i<9;i++)dsp[i]=12;c=1; //已输入a/***goto跳转标志***/goto LR;}else if(c==1){for(i=0;i<8;i++) //将第二个数存入b[8]{b[i]=dsp[i+1];}c=2; //已输入bif(dsp[0]!=15) //b输完后操作符不是等号{calculate(k,a,b);for(i=0;i<8;i++) //将计算结果存入a[8],a值更新{a[i]=dsp[i+1];}k=dsp[0]; //更新计算符c=1;/***goto跳转标志***/goto LR;}}}while((dsp[0]==15)&&(c<2)); //直到ab输入完成且按下等号calculate(k,a,b); //进行最后计算/***goto跳转标志***/goto LR; //跳回LR,等待新一轮计算while(1); //防止程序跑飞}char keyscan(){char KeyL;char KeyR;char j;do{do{P3=0xF0;P3=P3|0xF0;//行扫描11110000if(P3!=0xF0){KeyL=P3;P3=0x0F;P3=P3|0x0F;// 列扫描00001111KeyR=P3;}}while(KeyL==0xF0||KeyR==0x0F);for(j=0;j<12;j++) //延时0.001s=1ms{;}}while(P3!=0x0F);switch(KeyL&KeyR){case 0x28:{return 0;break;}case 0x11:{return 1;break;}case 0x21:{return 2;break;}case 0x41:{return 3;break;}case 0x12:{return 4;break;}case 0x22:{return 5;break;}case 0x42:{return 6;break;}case 0x14:{return 7;break;}case 0x24:{return 8;break;}case 0x44:{return 9;break;}case 0x81:{return 10;break;}//加法(第一行,第四列)case 0x82:{return 11;break;}//减法(第二行,第四列)case 0x84:{return 12;break;}//乘法(第三行,第四列)case 0x88:{return 13;break;}//除法(第四行,第四列)case 0x18:{return 14;break;}// 清零(第四行,第一列)case 0x48:{return 15;break;}//计算结果(第四行,第三列)}}void display() interrupt 1 using 1 //利用定时器中断实现间时显示{char i,j,h;ET0=0;for(j=8;j>0;j--) //扫描8次{for(i=7;i>=0;i--) //从高位到低位扫描显示{P2=0;P1=LED_CODES[dsp[8-i]];P2=Select[i];for(h=0;h<8;h++){;}}}TL0=-(1000/256);TH0=-(1000%6);ET0=1;}void calculate(char k,char a[8],char b[8]){char r[8];long i,x,y;i=0;x=0;y=0;for(i=7;i>0;i--) //数值转化,将代表空格的12转化为数字0,因为个位不显示空格,默认为0,所以不转化{while(a[i]==12)a[i]=0;while(b[i]==12)b[i]=0;}x=a[4];x=10000*x;x=x+a[0]+a[1]*10+a[2]*100+a[3]*1000+a[5]*100000+a[6]*1000000+a[7]*10000000;y=b[4];y=10000*y;y=y+b[0]+b[1]*10+b[2]*100+b[3]*1000+b[5]*100000+b[6]*1000000+b[7]*10000000;if(k==10)//加法运算{x=x+y;if(x>99999999) //大于8位,显示Err{r[0]=11; //rr[1]=11; //rr[2]=10; //Er[3]=12; //空格r[4]=12;r[5]=12;r[6]=12;r[7]=12;}else{r[0]=x_x0010_;r[1]=(x_x0010_0)/10;r[2]=(x_x0010_00)/100;r[3]=(x_x0010_000)/1000;r[4]=(x_x0010_0000)/10000;r[5]=(x_x0010_00000)/100000;r[6]=(x_x0010_000000)/1000000;r[7]=x/10000000;}}if(k==11)//减法运算{if(x<y){x=y-x;if(x>9999999){r[0]=11; //rr[1]=11; //rr[2]=10; //Er[3]=12; //空格r[4]=12;r[5]=12;r[6]=12;r[7]=12;}else{r[0]=x_x0010_;r[1]=(x_x0010_0)/10;r[2]=(x_x0010_00)/100;r[3]=(x_x0010_000)/1000;r[4]=(x_x0010_0000)/10000;r[5]=(x_x0010_00000)/100000;r[6]=(x_x0010_000000)/1000000;r[7]=x/10000000;for(i=7;i>0;i--) //将有效数字的高一位转化为-号{if(r[i]==0&&r[i-1]!=0){r[i]=14;break;}}}}else{x=x-y;r[0]=x_x0010_;r[1]=(x_x0010_0)/10;r[2]=(x_x0010_00)/100;r[3]=(x_x0010_000)/1000;r[4]=(x_x0010_0000)/10000;r[5]=(x_x0010_00000)/100000;r[6]=(x_x0010_000000)/1000000;r[7]=x/10000000;}}if(k==12)//乘法运算{i=x;x=x*y;if(y==0){x=0;}else if(x>99999999||x<i) //积大于99999999或者小于乘数都认为是异常,存在其他可能的溢出,须自行辨别{r[0]=11; //rr[1]=11; //rr[2]=10; //Er[3]=12; //空格r[4]=12;r[5]=12;r[6]=12;r[7]=12;}else{r[0]=x_x0010_;r[1]=(x_x0010_0)/10;r[2]=(x_x0010_00)/100;r[3]=(x_x0010_000)/1000;r[4]=(x_x0010_0000)/10000;r[5]=(x_x0010_00000)/100000;r[6]=(x_x0010_000000)/1000000;r[7]=x/10000000;}}if(k==13)//除法运算{if(y==0) // 被除数不能为0{r[0]=11; //rr[1]=11; //rr[2]=10; //Er[3]=12; //空格r[4]=12;r[5]=12;r[6]=12;r[7]=12;}else{x=x/y;r[0]=x_x0010_;r[1]=(x_x0010_0)/10;r[2]=(x_x0010_00)/100;r[3]=(x_x0010_000)/1000;r[4]=(x_x0010_0000)/10000;r[5]=(x_x0010_00000)/100000;r[6]=(x_x0010_000000)/1000000;r[7]=x/10000000;}}for(i=7;i>0;i--) //数值转化,将高位的无效数字0转化为空格符12 {if(r[i]==0)r[i]=12;elsebreak;}for(i=0;i<8;i++) //将计算结果存入dsp[9],显示数更新{dsp[i+1]=r[i];}}。