基于Atmega16的简易计算器实验设计和Proteus仿真

该程序参考https://zhuanlan.zhihu.com/p/128593249,实现了两个多位数字的加减乘除,在此基础上增加了按键‘C’对结果和输入数字的清除功能,尚未实现输入的逐位清除,此外,在运算除法时只能显示结果的整数部分。仿真基于Proteus8.6进行。

Proteus仿真电路图

LCD1602

功能代码

#include "LCD1602.h"
void lcd_port_init()
{DDRA = 0xff;PORTA = 0xff;DDRB = 0xff;PORTB = 0xff;
}
void delay(unsigned int t)
{while(t--){;}
}
/*
void LCD1602_Read_Status()
{unsigned char temp;RS_CLR;RW_CLR;EN_CLR;delay(10);RW_SET;delay(30);EN_SET;delay(100);temp=PINB;delay(100);EN_CLR;delay(10);RW_CLR;RS_SET;
}
void LCD1602_Read_Data()
{}*/
void LCD1602_Write_Command(unsigned char dat)
{delay(5000);RS_CLR;RW_CLR;DDRB = 0xff;delay(10);PORTB = dat;EN_CLR;delay(2);EN_SET;
}
void LCD1602_Write_Data(unsigned char dat)
{delay(5000);RS_SET;RW_CLR;DDRB = 0xff;delay(10);PORTB = dat;EN_CLR;delay(2);EN_SET;
}
void LCD1602_init()
{lcd_port_init();delay(15000);LCD1602_Write_Command(0x38);    /*显示模式设置*/delay(5000);LCD1602_Write_Command(0x38);    /*显示模式设置*/delay(5000);LCD1602_Write_Command(0x38);    /*显示模式设置*/delay(5000);LCD1602_Write_Command(0x08);          //关显示delay(5000);LCD1602_Write_Command(0x01);    /*显示清屏*/delay(5000);LCD1602_Write_Command(0x06);    //指针自加delay(5000);LCD1602_Write_Command(0x0c);    /*显示光标移动设置*/delay(5000);
}void LCD_write_string(unsigned char x,unsigned char y,unsigned char *s) //写字符串s函数
{if(y == 0){LCD1602_Write_Command(0x80 + x);}else{LCD1602_Write_Command(0xc0 + x);//第二行}while(*s){LCD1602_Write_Data(*s);s++;}
}

头文件

#ifndef _LCD1602_H
#define _LCD1602_H
#include<iom16v.h>
#define RS 0
#define RW 1
#define EN 2
#define RS_SET PORTA=PORTA|(1<<RS)
#define RS_CLR PORTA=PORTA&(~(1<<RS))
#define RW_SET PORTA=PORTA|(1<<RW)
#define RW_CLR PORTA=PORTA&(~(1<<RW))
#define EN_SET PORTA=PORTA|(1<<EN)
#define EN_CLR PORTA=PORTA&(~(1<<EN))
void lcd_port_init();
void delay(unsigned int t);
void LCD1602_Write_Command(unsigned char dat);
void LCD1602_Write_Data(unsigned char dat);
#endif

矩阵键盘

功能代码

#include<iom16v.h>
#include <AVRdef.h>unsigned int KeyResult,key_flag=0;//按键值,按键读取标志位void Key_Result(unsigned char KeyRead,unsigned char i)//结果扫描函数,键盘(列,行)
{if(i==0) //第一行{switch (KeyRead){case 0x0e: KeyResult=1,key_flag=1; break; //(1,1)(行,列)case 0x0d: KeyResult=2,key_flag=1; break; //(1,2)case 0x0b: KeyResult=3,key_flag=1; break; //(1,3)case 0x07: KeyResult=10,key_flag=1; break; //(1,4)(+)}}else if(i==1) //第二行{switch (KeyRead){case 0x0e: KeyResult=4,key_flag=1; break; //(2,1)case 0x0d: KeyResult=5,key_flag=1; break; //(2,2)case 0x0b: KeyResult=6,key_flag=1; break; //(2,3)case 0x07: KeyResult=11,key_flag=1; break; //(2,4)(-)}}else if(i==2) //第三行{switch (KeyRead){case 0x0e: KeyResult=7,key_flag=1; break; //(3,1)case 0x0d: KeyResult=8,key_flag=1; break; //(3,2)case 0x0b: KeyResult=9,key_flag=1; break; //(3,3)case 0x07: KeyResult=12,key_flag=1; break; //(3,4)(*)}}else if(i==3) //第四行{switch (KeyRead){case 0x0e: KeyResult=13,key_flag=1; break; //(4,1)(C)case 0x0d: KeyResult=0,key_flag=1; break; //(4,2)case 0x0b: KeyResult=14,key_flag=1; break; //(4,3)(=)case 0x07: KeyResult=15,key_flag=1; break; //(4,4)(/)}}
}void Key_Scan(void)
{unsigned char KeyRead,i; //KeyRead保存键盘输入状态,i保存当前行DDRC=0xf0; //PC0~3带上拉输入,PC4~7输出低电平PORTC=0x0f;KeyRead=PINC; //读取键盘结果KeyRead&=0x0f; //屏蔽高四位if(KeyRead!=0x0f) //判断键盘是否被按下{delay_xms(15);//消抖for(i=0;i<4;i++){PORTC=~BIT(i+4); //第i列低电平|第i行扫描DDRC=0xf0; //PD0~3带上拉输入,PD4~7输出低电平KeyRead=PINC; //读取键盘结果Key_Result(KeyRead&0x0f,i); //传递读取结果(屏蔽高四位),当前行(i)}}
}

头文件

#ifndef _MatrixKey_h
#define _MatrixKey_h
#include<iom16v.h>
#include <AVRdef.h>
extern unsigned int KeyResult;
extern unsigned int key_flag;
Key_Result(unsigned char KeyRead,unsigned char i);
void Key_Scan();
#endif

主函数

#include<iom16v.h>
#include "LCD1602.h"
#include "MatrixKey.h"unsigned char L1[16];//显示第一行
unsigned char L2[16];//显示第二行int result1 = 0; //存储第一个整数
int result2 = 0; //存储第二个整数
int Oper = 0;  //存储运算符
unsigned int succeed_flag = 0,clear_flag=0;//计算完成标志位,清除标志位void delay_1ms(void)
{unsigned char i,j;for(i=0;i<40;i++)for(j=0;j<33;j++){;}
}void delay_xms(unsigned int x)
{unsigned int i;for(i=0;i<x;i++){delay_1ms();}
}void display_line1(void)//第一行输入显示
{static unsigned int num=0;unsigned char str = 0;/*如果有计算完成标志,将显示内容清除,并将此标志位清零*/if(succeed_flag == 1){    sprintf((char *)L1,"               ");LCD_write_string(0,0,L1);sprintf((char *)L2,"               ");LCD_write_string(0,1,L2);succeed_flag = 0;num = 0;}switch(KeyResult){case 0 :  str = '0';  break;case 1 :  str = '1';  break;case 2 :  str = '2';  break;case 3 :  str = '3';  break;case 4 :  str = '4';  break;case 5 :  str = '5';  break;case 6 :  str = '6';  break;case 7 :  str = '7';  break;case 8 :  str = '8';  break;case 9 :  str = '9';  break;case 10 : str = '+';   break;case 11 : str = '-';   break;case 12 : str = '*';   break;case 13 : clear_flag = 1;   break;case 14 : str = '=';   break;case 15 : str = '/';   break;default:break;}L1[num]=str;num++;if(clear_flag == 1){    sprintf((char *)L1,"            ");LCD_write_string(0,0,L1);sprintf((char *)L2,"            ");LCD_write_string(0,1,L2);num=0;clear_flag=0;  }LCD_write_string(0,0,L1);key_flag=0;if(num>=16){num=0;}
}/*识别第一个数字*/
void distinguish_num1(void)
{static int num = 0;unsigned int key;key=KeyResult;/*如果被按下的是数字*/    switch(key){case 0 :  num = num * 10 + 0;  break;case 1 :  num = num * 10 + 1;  break;case 2 :  num = num * 10 + 2;  break;case 3 :  num = num * 10 + 3;  break;case 4 :  num = num * 10 + 4;  break;case 5 :  num = num * 10 + 5;  break;case 6 :  num = num * 10 + 6;  break;case 7 :  num = num * 10 + 7;  break;case 8 :  num = num * 10 + 8;  break;case 9 :  num = num * 10 + 9;  break;default:break;}    /*如果被按下的是运算符,则将之前的数字进行合成,然后保存运算符*/if(key == 10){/*加法*/Oper = 1;result1 = num;num = 0;   //将num清零,避免影响之后的计算}else if(key == 11){/*减法*/Oper = 2;result1 = num;num = 0;   //将num清零,避免影响之后的计算}else if(key == 12){/*乘法*/Oper = 3;result1 = num;num = 0;   //将num清零,避免影响之后的计算}else if(key == 13){/*清除*/result1 = 0;Oper = 0;num = 0;}else if(key == 15){/*除法*/Oper = 4;result1 = num;num = 0;   //将num清零,避免影响之后的计算}
}/*识别第二个数字*/
void distinguish_num2(void)
{static int num = 0;/*如果被按下的是数字*/ unsigned int key;key=KeyResult; switch(key){case 0 :  num = num * 10 + 0;  break;case 1 :  num = num * 10 + 1;  break;case 2 :  num = num * 10 + 2;  break;case 3 :  num = num * 10 + 3;  break;case 4 :  num = num * 10 + 4;  break;case 5 :  num = num * 10 + 5;  break;case 6 :  num = num * 10 + 6;  break;case 7 :  num = num * 10 + 7;  break;case 8 :  num = num * 10 + 8;  break;case 9 :  num = num * 10 + 9;  break;default:break;}if(key == 13){/*清除*/result2 = 0;Oper = 0;num = 0;}    /*当等于号被按下时,识别第二个数字,并将结果计算,显示*/if(key == 14){result2 = num;if(Oper == 1)  /*加*/{result2 = result1 + result2;            }else if(Oper == 2)  /*减*/{result2 = result1 - result2;}else if(Oper == 3)  /*乘*/{result2 = result1 * result2;}else if(Oper == 4)  /*除*/{result2 = result1 / result2;}        sprintf((char *)L2,"%d   ",result2);LCD_write_string(0,1,L2);/*将第一,二个数字,运算符以及保存的num清零*/result1 = 0;result2 = 0;Oper = 0;num = 0;/*计算完成标志置1*/succeed_flag = 1;}
}void main()
{LCD1602_init();while(1){Key_Scan();if(key_flag){display_line1();/*当第一串数字没有识别时,执行此函数,识别第一串数字以及运算符*/if(Oper == 0){distinguish_num1();}/*当第一串数字以及运算符已经确定的时候,执行识别第二串数字函数*/else{distinguish_num2();                    }                 }   }
}

源代码和仿真文件下载

基于Atmega16的简易计算器实验设计和Proteus仿真相关推荐

  1. 简单计算器的设计java_(基于java的简易计算器的设计.doc

    (基于java的简易计算器的设计 基于java的简易计算器的设计 摘要 自从java语言诞生以来,java语言就以不可抵挡的趋势很快成为国际上广泛流行的面向对象编程语言,它既具有高级语言的特点,又少了 ...

  2. 51单片机设计简易计算机原理,基于AT89C51单片机简易计算器的设计(DOC).docx

    PAGE PAGE # 基于AT89C51单片机简易计算器的设计 [摘要]单片机的出现是计算机制造技术高速发展的产物,它是嵌 入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域, 电子.科技 ...

  3. 基于PyQt5的简易计算器

    基于PyQt5的简易计算器之四 提示:基于PyQt5的简易计算器之一为环境搭建 基于PyQt5的简易计算器之二为Qt Designer使用 基于PyQt5的简易计算器之三为按键的功能实现 基于PyQt ...

  4. 基于QT5实现简易计算器

    基于QT5实现简易计算器 一.写在前面 二.成品展示 三.界面布局 四.按钮功能 五.源码下载 六.补充 一.写在前面 软件介绍: 仿照win10计算器,基于qt5实现具有简单运算的计算器. 环境: ...

  5. 基于java平台简易计算器_基于java的简易计算器的设计

    基于java的简易计算器的设计 基于java的简易计算器的设计 摘要 自从java语言诞生以来,java语言就以不可抵挡的趋势很快成为国际上广泛流行的面向对象编程语言,它既具有高级语言的特点,又少了C ...

  6. 【011】基于51单片机的低频信号发生proteus仿真与实物设计

    ​一.资料内容 (1).基于51单片机的低频信号发生proteus仿真设计一份: (2).基于51单片机的低频信号发生proteus仿真设计keli源代码一份: (3).基于51单片机的低频信号发生A ...

  7. 基于51单片机的LCD1602电子钟闹钟proteus仿真设计

    本设计是基于51单片机的LCD1602电子钟闹钟proteus仿真设计 源码+仿真+原理图+器件清单 仿真软件版本:proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 编 ...

  8. 【004】基于51单片机的音乐播放器proteus仿真设计

    一.压缩包资料内容(私信获取) (1).基于51单片机的音乐播放器proteus仿真设计一份: (2).基于51单片机的音乐播放器proteus仿真设计keli源代码一份: (3).基于51单片机的音 ...

  9. 基于STM32大棚DHT11温湿度监测的Proteus仿真

    本设计仅供学习参考 基于STM32大棚DHT11温湿度监测的Proteus仿真 (代码+仿真+原理图+PCB) 原理图:Altium Designer 仿真图protues 8.9 程序编译器:kei ...

最新文章

  1. offsetof使用小结
  2. 【笔记】buck/boost/buck-boost相关计算公式
  3. 在D-Bus适配器中声明信号
  4. leetcode 328. Odd Even Linked List | 328. 奇偶链表(Java)
  5. .net:设计一个web应用
  6. begintrans返回值_SQL事务回滚 ADO BeginTrans, CommitTran 以及 RollbackTrans 方法
  7. RxPermissions 源码解析之举一反三
  8. 开弹幕卡顿的原因_QQ飞车手游卡顿严重怎么解决,来看看这个安卓手游卡顿解决方法!...
  9. How do I UPDATE from a SELECT in SQL Server?
  10. opencv-api houshlinesp
  11. 【渝粤教育】国家开放大学2018年春季 8662-22T特色课(1) 参考试题
  12. 关于boot.ini文件里的/noexecute=optin
  13. DWR3.0 文件上传
  14. 视频格式转换完全进阶
  15. C语言全局变量,局部变量,静态局部变量的区分
  16. leetcode 每日一题 一起进步714 买卖股票的最佳时机含手续费
  17. Modbus的十大问题
  18. 祝贺 弓叶科技总经理莫卓亚荣获“松山湖奋斗之星”
  19. Python爬虫:ZzzFun动漫视频网
  20. explicit含义

热门文章

  1. android免费商用图标,免费商用!!!(线性图标)
  2. 要想加入红队,需要做好哪些准备?
  3. 安全删除Windows XP SP2的四种方法(转)
  4. 数据库连接池的原理及验证
  5. CREO:CREO软件之工程图【插入页面】、【装配图出工程图】、【将视图转为绘制图元】、【工程图输入到CAD中去修改】的简介及其使用方法(图文教程)之详细攻略
  6. Java学习笔记(七)
  7. 国密ESAM模块,7816接口、SPI接口、IIC接口可选
  8. Web Services教程
  9. 如何使用React+Elementui搭建项目
  10. 操作系统ucore实验——lab1