精华内容
下载资源
问答
  • 单片机计算器,本人的课程设计程序,外加proteus仿真电路图。非常实用。
  • at89c51单片机 计算器 矩阵键盘 c语言代码 课程设计
  • 12864液晶显示屏,结合4*4矩阵键盘,简易计算器,功能:1、基本整数的加减乘除; 2、有清除功能;3、除法计算,结果保留两位小数;4、分母为0报错
  • 单片机矩阵键盘计算器,含程序,仿真图。属于示例程序。
  • 51单片机计算器

    2019-01-30 14:10:24
    用51单片机实现计算器功能,包括加减乘除,且支持退格功能。使用矩阵键盘,最右边一列从上到下代表加减乘除,S13代表退格,S15代表等于号,其余为数字
  • 单片机计算器

    2012-06-07 20:14:55
    本书基于KeilμVision程序设计平台和Proteus硬件仿真平台,精心编写了100余个8051单片机C语言程 序设计案例。 全书基础设计类案例贯穿8051单片机最基本的端口编程、定时/计数器应用、中断和串口通信;硬 件应用类...
  • 51单片机设计矩阵键盘简易计算器keil工程文件C源文件,可进行整数之间的运算,没有小数,除法得出的结果可能不正确,有负数的运算
  • 非常适合新手学习51单片机,利用1602显示,里面有原理图,根据硬件看代码,非常容易理解
  • 计算器 程序要求 用矩阵按键实现简单的加减乘除运算 程序代码 #include <reg51.h> #include <stdio.h> Sbit colj=P1^4; Sbit coL2=P1^5; Sbit coL3=P1^6; Sbit coL4=P1^7; unSigned char code table[]={0x3f,0x06,0x...
  • 基于51单片机矩阵计算器设计

    千次阅读 2018-03-16 08:36:47
    当初本科的毕业设计不是很完美,一直想把它完善一下,这学期刚开始有点时间,就以一个小项目的...Ø 为了生成单片机可执行文件,选择使用了Ubuntu系统下的sdcc编译器,安装使用都很简单(想多在Ubuntu下进行编程)...

          当初本科的毕业设计不是很完美,一直想把它完善一下,这学期刚开始有点时间,就以一个小项目的方式,综合自己这一年多来的代码阅读收获,重写了这个工程。

    一,平台的重新搭建

    Ø  在win7上重新安装了proteus7.8用于仿真阶段的测试,并从以前的资料中找到了仿真模型;

    Ø  为了生成单片机可执行文件,选择使用了Ubuntu系统下的sdcc编译器,安装使用都很简单(想多在Ubuntu下进行编程),参考http://blog.csdn.net/adam_embedded/article/details/45310325

    Ø  字模提取软件,用于各种字符码的提取;

    二,仿真代码重写

    Ø  仿照之前见过的比较系统的工程目录,创建了自己的工程目录:

    Ø  模仿C++类的方式,按照不同的功能,将之前冗杂的单个工程文件分成了几个分开的功能文件:

    Ø  每个.c实现不同类的功能:

    keyboard_function:

    lcd_function:

    core_function:

    三,实验效果

           完成了相加,相乘,求模,求转置的功能,求逆运算因为会牵扯到小数运算和显示,并未将其放入该工程,以下是主要的显示效果:

      

          

         

    四,项目缺陷

    Ø  由于屏幕尺寸问题,局限在3*3的矩阵计算上;

    Ø  没有删除错误输入的清除功能(待实现);

    Ø  较小的RAM使得很容易内存不足,程序编写受到限制(待配合硬件加入外部存储器);

    Ø  单循环机制,没有有效的使用中断来避免各种意外情况(待将键盘扫面、功能选择等函数写入中断函数);

                                                                  

                                                                   2018.3.15

    展开全文
  • 基于C51单片机计算器程序,物超所值!矩阵键盘用于输入数值及运算符号,大家快来看啊~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • 1602液晶显示,矩阵键盘。因51单片机限制,只可以精确到7位。
  • 《基于C51单片机简易计算器的课程设计.doc》由会员分享,可免费在线阅读全文,更多与《基于C51单片机简易计算器的课程设计(最终版)》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。1、位七段码,H...

    《基于C51单片机简易计算器的课程设计.doc》由会员分享,可免费在线阅读全文,更多与《基于C51单片机简易计算器的课程设计(最终版)》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。

    1、位七段码,H单元存放数值的百位七段码,H单元存放数值的千位七段码。本方案设计中由P口输出字形码,P口输出字位码。先将存放于H单元的数值个位七段码由P口输出,同时P口输出使数值个位显示数码管点亮的字位码。由于采用的是共阴数码管,所以只有该位数码管对应的P为,其他位PP位,点亮延时MS。然后P口输出数值十位七段码,P位,数值十位数码管点亮,延时MS。接着P口输出数值百位七段码,P为,数值百的点亮时间为~ms,由于人的视觉暂留现象及发光二极体的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示资料,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的IO埠,而且功耗更低。综上所述我们在本设计方案中选用了动态显示。位LED显示的程序框图如图所示:图LED显示流程图主程序设计主程序进行程序中用到的一些存储单元的初始化,数值显示和*键盘扫描。首先,进行存储单元初始化,给数码管显示单元HH赋予“”字形数据,将数值计数单元,存储单元,HH,HH,H,H,AH,BH,CH,赋予初值零。之后,调用键盘扫描子

    2、amnumgt=amamnumlt=)dislay(num);el使用的标准键盘就是编码键盘。在智能仪器中,使用并行接口芯片或串行接口芯片HD均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可以在相关资料中得到。当系统功能比较复杂,案件数量很多时,采用编码键盘可以简化软件设计。但大多数智能仪器和电子产品的按键数目都不很多(个以内),为了降低成本和简化电路通常采用非编码键盘。非编码键盘的电路由设计者根据需要自己决定,按键信息通过接口软件来获取。本课题需要个按键,故选择非编码键盘,为了减少所占用的端口,由P口采用*矩阵式键盘。图键盘样式输出电路设计数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“”可分为位、位、位等等数码管;按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。共阳级数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管。共阳级数码管在应用时应将公共极COM接到+V,当某一字段发光二极管的阴极为低电平时,相应字

    3、段就点亮。当某一字段的阴极为高电平时,对应的字段就不亮。。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管。共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮。当某一字段的阳极为低电平时,对应的字段就不亮。LED显示器由七段发光二极管组成,排列成字形状,因此也成为七段LED显示器,器排列形状如下图所示:图LED段码为了显示数字或符号,要为LED显示器提供代码,即字形代码。七段发光二极管,再加上一个小数点位,共计段,因此提供的字形代码的长度正好是一个字节。简易计算器用到的数字~的共阴极字形代码如下表所示:显示字型gfedcBa段码fhhbhfhhdhdhhfhfh表~七段数码管共阴级字形代码由于数值单元存放的是二进制数,而我们大家熟悉的是十进制数,所以应将数值单元中的二进制数字转换为十进制数字,即BCD码。要通过数码管显示出当前的数值,还必须将BCD码进一步转换为七段码,转换的最终结果数据存放于显示缓冲区HH单元中,其中H单元存放数值的个位七段码,H单元存放数值的十

    4、=)按下ONC键,清零{flag_fuhao=;shu=shu=fuhao=flag_shu=newkey=;}elseif(key_shu==amamflag_shu==amamfuhao)按下quot=quot{switch(fuhao){case:shu=shu+shu;eak;case:shu=shushu;eak;case:shu=shu*shu;eak;case:shu=shushu;eak;}fuhao=;flag_fuhao=;}elseif((key_shugt=)amam(key_shu=)amam(key_shult=))按下运算符{flag_fuhao=;if(flag_shu==){if(fuhao==){shu=shu;shu=;fuhao=key_shu;flag_shu=;}else{switch(fuhao){case:shu=shu+shu;eak;case:shu=shushu;eak;case:shu=shu*shu;eak;case:shu=shushu;eak;}shu=;fuhao=key_shu

    5、。最后P口输出数值千位七段码,P为,数值千位数码管点亮,延时MS。发光二极管LED是单片机应用系统中的一种简单而最常用的输出设备,其在系统中的主要作用是显示单片机的输出数据、状态等。因而作为典型的外围器件,LED显示单元是反映系统输出和操作输入的有效元器件。LED具备数字接口可以方便的和单片机引脚连接;它的优点是价格低,寿命长,对电压电流的要求低以及容易实现多路等,因而在单片机应用系统中获得了广泛的应用,所以在此设计中我首先选用了LED作为显示器件。如图所示:图数码显示管程序设计本方案中的程序设计采用了模块化设计,各部分程序都分别进行独立的设计,最后主程序通过调用各模块程序来运行,编程中所使用的语言全部都是C语言,可以利用keil软件进行灵活的编译,编译完成后也可生成HEX文件,利用ISP编程软件通过串口写到单片机中。本方案程序设计中部分包括主程序模块、液晶显示模块、功能按键和控制输出等部分。下面仅仅叙述了各部分程序设计的基本思想和流程图,详细程序请参阅附录。读键输入程序流程图为了实现键盘的数据输入功能和命令处理功能,每个键都有其处理子程序,

    6、,通过我的不懈努力,在动手方面,我会得到提高。这一点,我坚信。在此次的课程设计中我最大的体会就是进一步认识到了理论联系实践的重要性。一份耕耘,一份收获。通过这段时间的设计,让我明白科学的思维方法和学习方法是多么重要,只有这样才能够有很高的效率,才能够让自己的工作更完美。总而言之,此次毕业设计让我学到了好多平时在课堂上学不到的东西,增加了我的知识运用能力,增强我的实际操作能力。谢谢老师给我们提供这么好的机会,为我们之后走向社会奠定了一个好的基础。在我做课程设计的整个过程中,无论是在设计的选题、构思和资料的收集方面,还是在设计的研究方法以及成文定稿方面,或是在论文的写作过程中,都得到了许多同学的宝贵建议,在此一并致以诚挚的谢意。感谢所有关心、支持、帮助过我的同学。元件清单元件数量单价(元)M晶振STCC芯片轻触按键排阻四位一体公阴数码管电阻若干杜邦线排针电容若干总计附录简易计算器源程序includedefineucharunsignedchardefineuintunsignedintdefineduanP数码管显示段选定义defineweiP数

    7、较符合人们的日常思维,缺点是一级的程序错误会对整个程序产生影响。功能和操作:加减乘除运算和显示。A:上电后,屏幕初始化,按下“ONC”键。B:计算。按下数字键,屏幕显示要运算的第一个数字,再按下符号键,然后再按下数字键,屏幕显示要运算的第二个数字,最后按下“﹦”号键,屏幕上显示出计算结果。C:如果要再次计算,可以按下“ONC”键清零,或者按下单片机的复位键,重新初始化。硬件联系图如下图:硬件连线图结论课程设计是培养学生运用所学的专业知识,发现,提出,分析和解决实际问题,锻炼实际动手能力的重要环节,是对学生实际工作能力的具体训练和考察,随着科学技术日新月异的发展,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说遍布我们生活之中。这次设计进一步端正了我的学习态度,学会了实事求是,严谨的作风,对自己要严格要求。急于求成是不好的,通过此次毕业设计我深有体会。如果省略了那些必要的步骤,急于求成,不仅会浪费时间,还会适得其反。我觉得动手之前,应该有清楚的步骤,这一步是很重要的。就目前来说,我的动手能力虽然还有差距,但我知道数码管点亮,延时MS

    8、in(){flag=;标志关机while(){if(keyscan()==)开机检测{flag=;标志开机shu=shu=fuhao=flag_shu=newkey=;初始化变量while(flag){if(!flag_fuhao)dislay(shu);elsedislay(shu);key_shu=keyscan();if(newkey==)sedislay(shu);}returnnum;}}key=xfb;if(key!=xfb){delay();if(key!=xfb){switch(key){casexeb:num=;eak;casexdb:num=;eak;casexbb:num=;eak;casexb:num=;eak;}newkey=;delay();while(key!=xfb){if(flag)if(!shuamamnumgt=amamnumlt=)dislay(num);elsedislay(shu);}returnnum;}}key=xf;if(key!=xf){delay();if(key!=xf){switch(

    9、;}}elseif(flag_shu==)fuhao=key_shu;}newkey=;}}}}}键盘扫描ucharkeyscan(){key=xfe;if(key!=xfe){delay();if(key!=xfe){switch(key){casexee:num=;eak;casexde:num=;eak;casexbe:num=;eak;casexe:num=;eak;quotquot}newkey=;delay();while(key!=xfe){if(flag)if(!shuamamnumgt=amamnumlt=)dislay(num);elsedislay(shu);}returnnum;}}key=xfd;if(key!=xfd){delay();if(key!=xfd){switch(key){casexed:num=;eak;casexdd:num=;eak;casexbd:num=;eak;casexd:num=;eak;*}newkey=;delay();while(key!=xfd){if(flag)if(!shua

    10、码管显示位选定义definekeyP键盘接口定义sbitOFF=P^;关机键定义unsignedlongintshu,shu;进行运算的两个变量数ucharnum;键盘扫描返回值charflag,flag_shu,flag_fuhao,fuhao,newkey;flag开机标志新按键标志,fuhao运算符charkey_shu;按键值unsignedcharcodeWela[]={xdf,xef,xf,xfb,xfd,xfe};六位数码管的位选unsignedcharcodeDuan[]={xf,x,xb,xf,x,xd,xd,x,xf,xf,x};无显示共阴极数码管ucharkeyscan();键盘扫描函数voiddislay(unsignedlongint);数码管显示函数voiddelay(uinti)延时函数{while(i);}***********************************************主函数************************************************voidma

    11、序,和数码管显示数据转换程序,数码管动态显示子程序。主程序不断进行键盘扫描,数码管显示数据转换子程序和动态显示子程序。首先初始化参数,送LED低位显示“”,功能键(“+”、“”、“*”、“”、“+”)位不显示。然后扫描键盘看是否有键输入,若有,读取键码。判断键码是数字键、清零键还是“+”、“”、“*”“”,是数值键则送LED显示并保存数值,是清零键则做清零处理,是功能键则又判断是“=”还是运算键,若是“=”则计算最后结果并送LED显示,若是运算键则保存相对运算程序的首地址。运算主程序框图如所示:图运算主程序框图仿真与调试在程序设计方法上,模块化程序设计是单片机应用中最常用的程序设计方法。设计的中心思想是把一个复杂应用程序按整体功能划分成若干相对独立的程序模块,各模块可以进行单独的设计、编程和调试,然后组合起来。这种方法便于设计和调试,容易实现多个程序共存,但各个模块之间的连接有一定的难度。根据需要我们可以采取自上而下的程序设计方法,此方法先从主程序开始设计,然后再编制各从属程序和子程序,层层细化逐步完成,最终完成一个复杂程序的设计。这种方法比

    12、ey){casexe:num=;eak;ONCcasexd:num=;eak;casexb:num=;eak;=casex:num=;eak;+}newkey=;delay();while(key!=xf){if(flag)if(!shuamamnumgt=amamnum)dis_flag=;elseif(dis_shugt)dis_flag=;elseif(dis_shugt)dis_flag=;elseif(dis_shugt)dis_flag=;elseif(dis_shugt)dis_flag=;elsedis_flag=;for(dis_aa=;dis_aaltdis_flag;dis_aa++){dis_data[dis_aa]=dis_shu%;dis_shu=dis_shu;}数码管段选for(dis_aa=;dis_aaltdis_flag;dis_aa++){duan=Duan[dis_data[dis_aa]];wei=Wela[dis_aa];delay();wei=xff;}数码管位选}新键值{if(key_shu=

    展开全文
  • 利用51单片机设计一个简单的计算器,能够实现简单的运算
  • 13.4 单片机计算器实例

    千次阅读 2016-07-08 06:12:58
    按键和液晶,可以组成我们最简易的计算器。下面我们来写一个简易整数计算器提供给大家学习。为了让程序不过于复杂,我们这个计算器不考虑连加,连减等连续计算,不考虑小数情况。加减乘除分别用上下左右来替代,回车...
    按键和液晶,可以组成我们最简易的计算器。下面我们来写一个简易整数计算器提供给大家学习。为了让程序不过于复杂,我们这个计算器不考虑连加,连减等连续计算,不考虑小数情况。加减乘除分别用上下左右来替代,回车表示等于,ESC 表示归 0。程序共分为三部分,一部分是 1602 液晶显示,一部分是按键动作和扫描,一部分是主函数功能。 
    
       
    1. /***************************Lcd1602.c 文件程序源代码*****************************/
    2. #include <reg52.h>
    3. #define LCD1602_DB P0
    4. sbit LCD1602_RS = P1^0;
    5. sbit LCD1602_RW = P1^1;
    6. sbit LCD1602_E = P1^5;
    7. /* 等待液晶准备好 */
    8. void LcdWaitReady(){
    9. unsigned char sta;
    10. LCD1602_DB = 0xFF;
    11. LCD1602_RS = 0;
    12. LCD1602_RW = 1;
    13. do {
    14. LCD1602_E = 1;
    15. sta = LCD1602_DB; //读取状态字
    16. LCD1602_E = 0;
    17. //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止
    18. }while (sta & 0x80);
    19. }
    20. /* 向 LCD1602 液晶写入一字节命令,cmd-待写入命令值 */
    21. void LcdWriteCmd(unsigned char cmd){
    22. LcdWaitReady();
    23. LCD1602_RS = 0;
    24. LCD1602_RW = 0;
    25. LCD1602_DB = cmd;
    26. LCD1602_E = 1;
    27. LCD1602_E = 0;
    28. }
    29. /* 向 LCD1602 液晶写入一字节数据,dat-待写入数据值 */
    30. void LcdWriteDat(unsigned char dat){
    31. LcdWaitReady();
    32. LCD1602_RS = 1;
    33. LCD1602_RW = 0;
    34. LCD1602_DB = dat;
    35. LCD1602_E = 1;
    36. LCD1602_E = 0;
    37. }
    38. /* 设置显示 RAM 起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
    39. void LcdSetCursor(unsigned char x, unsigned char y){
    40. unsigned char addr;
    41. if (y == 0){ //由输入的屏幕坐标计算显示 RAM 的地址
    42. addr = 0x00 + x; //第一行字符地址从 0x00 起始
    43. }else{
    44. addr = 0x40 + x; //第二行字符地址从 0x40 起始
    45. }
    46. LcdWriteCmd(addr | 0x80); //设置 RAM 地址
    47. }
    48. /* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
    49. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){
    50. LcdSetCursor(x, y); //设置起始地址
    51. while (*str != '\0'){ //连续写入字符串数据,直到检测到结束符
    52. LcdWriteDat(*str++);
    53. }
    54. }
    55. /* 区域清除,清除从(x,y)坐标起始的 len 个字符位 */
    56. void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len){
    57. LcdSetCursor(x, y); //设置起始地址
    58. while (len--){ //连续写入空格
    59. LcdWriteDat(' ');
    60. }
    61. }
    62. /* 整屏清除 */
    63. void LcdFullClear(){
    64. LcdWriteCmd(0x01);
    65. }
    66. /* 初始化 1602 液晶 */
    67. void InitLcd1602(){
    68. LcdWriteCmd(0x38); //16*2 显示,5*7 点阵,8 位数据接口
    69. LcdWriteCmd(0x0C); //显示器开,光标关闭
    70. LcdWriteCmd(0x06); //文字不动,地址自动+1
    71. LcdWriteCmd(0x01); //清屏
    72. }
    Lcd1602.c 文件中根据上层应用的需要增加了 2 个清屏函数:区域清屏——LcdAreaClear,整屏清屏——LcdFullClear。
       
    1. /**************************keyboard.c 文件程序源代码*****************************/
    2. #include <reg52.h>
    3. sbit KEY_IN_1 = P2^4;
    4. sbit KEY_IN_2 = P2^5;
    5. sbit KEY_IN_3 = P2^6;
    6. sbit KEY_IN_4 = P2^7;
    7. sbit KEY_OUT_1 = P2^3;
    8. sbit KEY_OUT_2 = P2^2;
    9. sbit KEY_OUT_3 = P2^1;
    10. sbit KEY_OUT_4 = P2^0;
    11. unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
    12. { '1', '2', '3', 0x26 }, //数字键 1、数字键 2、数字键 3、向上键
    13. { '4', '5', '6', 0x25 }, //数字键 4、数字键 5、数字键 6、向左键
    14. { '7', '8', '9', 0x28 }, //数字键 7、数字键 8、数字键 9、向下键
    15. { '0', 0x1B, 0x0D, 0x27 } //数字键 0、ESC 键、 回车键、 向右键
    16. };
    17. unsigned char pdata KeySta[4][4] = { //全部矩阵按键的当前状态
    18. {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
    19. };
    20. extern void KeyAction(unsigned char keycode);
    21. /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
    22. void KeyDriver(){
    23. unsigned char i, j;
    24. static unsigned char pdata backup[4][4] = { //按键值备份,保存前一次的值
    25. {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
    26. };
    27. for (i=0; i<4; i++){ //循环检测 4*4 的矩阵按键
    28. for (j=0; j<4; j++){
    29. if (backup[i][j] != KeySta[i][j]){ //检测按键动作
    30. if (backup[i][j] != 0){ //按键按下时执行动作
    31. KeyAction(KeyCodeMap[i][j]); //调用按键动作函数
    32. }
    33. backup[i][j] = KeySta[i][j]; //刷新前一次的备份值
    34. }
    35. }
    36. }
    37. }
    38. /* 按键扫描函数,需在定时中断中调用,推荐调用间隔 1ms */
    39. void KeyScan(){
    40. unsigned char i;
    41. static unsigned char keyout = 0; //矩阵按键扫描输出索引
    42. static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区
    43. {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
    44. {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
    45. };
    46. //将一行的 4 个按键值移入缓冲区
    47. keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
    48. keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
    49. keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
    50. keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
    51. //消抖后更新按键状态
    52. for (i=0; i<4; i++){ //每行 4 个按键,所以循环 4 次
    53. if ((keybuf[keyout][i] & 0x0F) == 0x00){
    54. //连续 4 次扫描值为 0,即 4*4ms 内都是按下状态时,可认为按键已稳定的按下
    55. KeySta[keyout][i] = 0;
    56. }else if ((keybuf[keyout][i] & 0x0F) == 0x0F){
    57. //连续 4 次扫描值为 1,即 4*4ms 内都是弹起状态时,可认为按键已稳定的弹起
    58. KeySta[keyout][i] = 1;
    59. }
    60. }
    61. //执行下一次的扫描输出
    62. keyout++; //输出索引递增
    63. keyout &= 0x03; //索引值加到 4 即归零
    64. switch (keyout){ //根据索引,释放当前输出引脚,拉低下次的输出引脚
    65. case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
    66. case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
    67. case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
    68. case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
    69. default: break;
    70. }
    71. }
    keyboard.c 是对之前已经用过多次的矩阵按键驱动的封装,具体到某个按键要执行的动作函数都放到上层的 main.c 中实现,在这个按键驱动文件中只负责调用上层实现的按键动作函数即可。
       
    1. /*****************************main.c 文件程序源代码******************************/
    2. #include <reg52.h>
    3. unsigned char step = 0; //操作步骤
    4. unsigned char oprt = 0; //运算类型
    5. signed long num1 = 0; //操作数 1
    6. signed long num2 = 0; //操作数 2
    7. signed long result = 0; //运算结果
    8. unsigned char T0RH = 0; //T0 重载值的高字节
    9. unsigned char T0RL = 0; //T0 重载值的低字节
    10. void ConfigTimer0(unsigned int ms);
    11. extern void KeyScan();
    12. extern void KeyDriver();
    13. extern void InitLcd1602();
    14. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
    15. extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
    16. extern void LcdFullClear();
    17. void main(){
    18. EA = 1; //开总中断
    19. ConfigTimer0(1); //配置 T0 定时 1ms
    20. InitLcd1602(); //初始化液晶
    21. LcdShowStr(15, 1, "0"); //初始显示一个数字 0
    22. while (1){
    23. KeyDriver(); //调用按键驱动
    24. }
    25. }
    26. /* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
    27. unsigned char LongToString(unsigned char *str, signed long dat){
    28. signed char i = 0;
    29. unsigned char len = 0;
    30. unsigned char buf[12];
    31. if (dat < 0){ //如果为负数,首先取绝对值,并在指针上添加负号
    32. dat = -dat;
    33. *str++ = '-';
    34. len++;
    35. }
    36. do { //先转换为低位在前的十进制数组
    37. buf[i++] = dat % 10;
    38. dat /= 10;
    39. } while (dat > 0);
    40. len += i; //i 最后的值就是有效字符的个数
    41. while (i-- > 0){ //将数组值转换为 ASCII 码反向拷贝到接收指针上
    42. *str++ = buf[i] + '0';
    43. }
    44. *str = '\0'; //添加字符串结束符
    45. return len; //返回字符串长度
    46. }
    47. /* 显示运算符,显示位置 y,运算符类型 type */
    48. void ShowOprt(unsigned char y, unsigned char type){
    49. switch (type){
    50. case 0: LcdShowStr(0, y, "+"); break; //0 代表+
    51. case 1: LcdShowStr(0, y, "-"); break; //1 代表-
    52. case 2: LcdShowStr(0, y, "*"); break; //2 代表*
    53. case 3: LcdShowStr(0, y, "/"); break; //3 代表/
    54. default: break;
    55. }
    56. }
    57. /* 计算器复位,清零变量值,清除屏幕显示 */
    58. void Reset(){
    59. num1 = 0;
    60. num2 = 0;
    61. step = 0;
    62. LcdFullClear();
    63. }
    64. /* 数字键动作函数,n-按键输入的数值 */
    65. void NumKeyAction(unsigned char n){
    66. unsigned char len;
    67. unsigned char str[12];
    68. if (step > 1){ //如计算已完成,则重新开始新的计算
    69. Reset();
    70. }
    71. if (step == 0){ //输入第一操作数
    72. num1 = num1*10 + n; //输入数值累加到原操作数上
    73. len = LongToString(str, num1); //新数值转换为字符串
    74. LcdShowStr(16-len, 1, str); //显示到液晶第二行上
    75. }else{ //输入第二操作数
    76. num2 = num2*10 + n; //输入数值累加到原操作数上
    77. len = LongToString(str, num2); //新数值转换为字符串
    78. LcdShowStr(16-len, 1, str); //显示到液晶第二行上
    79. }
    80. }
    81. /* 运算符按键动作函数,运算符类型 type */
    82. void OprtKeyAction(unsigned char type){
    83. unsigned char len;
    84. unsigned char str[12];
    85. if (step == 0){ //第二操作数尚未输入时响应,即不支持连续操作
    86. len = LongToString(str, num1); //第一操作数转换为字符串
    87. LcdAreaClear(0, 0, 16-len); //清除第一行左边的字符位
    88. LcdShowStr(16-len, 0, str); //字符串靠右显示在第一行
    89. ShowOprt(1, type); //在第二行显示操作符
    90. LcdAreaClear(1, 1, 14); //清除第二行中间的字符位
    91. LcdShowStr(15, 1, "0"); //在第二行最右端显示 0
    92. oprt = type; //记录操作类型
    93. step = 1;
    94. }
    95. }
    96. /* 计算结果函数 */
    97. void GetResult(){
    98. unsigned char len;
    99. unsigned char str[12];
    100. if (step == 1){ //第二操作数已输入时才执行计算
    101. step = 2;
    102. switch (oprt){ //根据运算符类型计算结果,未考虑溢出问题
    103. case 0: result = num1 + num2; break;
    104. case 1: result = num1 - num2; break;
    105. case 2: result = num1 * num2; break;
    106. case 3: result = num1 / num2; break;
    107. default: break;
    108. }
    109. len = LongToString(str, num2); //原第二操作数和运算符显示到第一行
    110. ShowOprt(0, oprt);
    111. LcdAreaClear(1, 0, 16-1-len);
    112. LcdShowStr(16-len, 0, str);
    113. len = LongToString(str, result); //计算结果和等号显示在第二行
    114. LcdShowStr(0, 1, "=");
    115. LcdAreaClear(1, 1, 16-1-len);
    116. LcdShowStr(16-len, 1, str);
    117. }
    118. }
    119. /* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
    120. void KeyAction(unsigned char keycode){
    121. if ((keycode>='0') && (keycode<='9')){ //输入字符
    122. NumKeyAction(keycode - '0');
    123. }else if (keycode == 0x26){ //向上键,+
    124. OprtKeyAction(0);
    125. }else if (keycode == 0x28){ //向下键,-
    126. OprtKeyAction(1);
    127. }else if (keycode == 0x25){ //向左键,*
    128. OprtKeyAction(2);
    129. }else if (keycode == 0x27){ //向右键,÷
    130. OprtKeyAction(3);
    131. }else if (keycode == 0x0D){ //回车键,计算结果
    132. GetResult();
    133. }else if (keycode == 0x1B){ //Esc 键,清除
    134. Reset();
    135. LcdShowStr(15, 1, "0");
    136. }
    137. }
    138. /* 配置并启动 T0,ms-T0 定时时间 */
    139. void ConfigTimer0(unsigned int ms){
    140. unsigned long tmp; //临时变量
    141. tmp = 11059200 / 12; //定时器计数频率
    142. tmp = (tmp * ms) / 1000; //计算所需的计数值
    143. tmp = 65536 - tmp; //计算定时器重载值
    144. tmp = tmp + 28; //补偿中断响应延时造成的误差
    145. T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
    146. T0RL = (unsigned char)tmp;
    147. TMOD &= 0xF0; //清零 T0 的控制位
    148. TMOD |= 0x01; //配置 T0 为模式 1
    149. TH0 = T0RH; //加载 T0 重载值
    150. TL0 = T0RL;
    151. ET0 = 1; //使能 T0 中断
    152. TR0 = 1; //启动 T0
    153. }
    154. /* T0 中断服务函数,执行按键扫描 */
    155. void InterruptTimer0() interrupt 1{
    156. TH0 = T0RH; //重新加载重载值
    157. TL0 = T0RL;
    158. KeyScan(); //按键扫描
    159. }
    main.c 文件实现所有应用层的操作函数,即计算器功能所需要信息显示、按键动作响应等,另外还包括主循环和定时中断的调度。

    通过这样一个程序,大家一方面学习如何进行多个.c 文件的编程,另外一个方面学会多个函数之间的灵活调用。可以把这个程序看成是一个简单的小项目,学习一下项目编程都是如何进行和布局的。不要把项目想象的太难,再复杂的项目也是这种简单程序的组合和扩展而已。
    展开全文
  • #include #define uint unsigned int#define uchar unsigned charsbit leden=P2^7;sbit rs=P2^6;sbit wr=P2^5;sbit key=P3^2;//sbit busy=P0^7;uchar i,j,num,num_1,temp;long a1,b, c;float a_c,b_c;...

    #include

    #define uint unsigned int

    #define uchar unsigned char

    sbit leden=P2^7;

    sbit rs=P2^6;

    sbit wr=P2^5;

    sbit key=P3^2;

    //sbit busy=P0^7;

    uchar i,j,num,num_1,temp;

    long a1,b, c;

    float a_c,b_c;

    uchar flag,fuhao;

    uchar code table[]={7,8,9,0,

    4,5,6,0,

    1,2,3,0};

    uchar code table1[]={7,8,9,0x2f-0x30,

    4,5,6,0x2a-0x30,

    1,2,3,0x2d-0x30,

    0x01-0x30,0,0x3d-0x30,0x2b-0x30};

    void delay(uchar n)

    {

    uchar i,j;

    for(i=n;i>0;i--)

    for(j=200;j>0;j--) ;

    }

    void write(uint w)

    {

    rs=0;

    wr=0;

    leden=0;

    P0=w;

    leden=1;

    delay(10);//check();

    leden=0;

    }

    void write_data(uint q)

    {

    rs=1;

    wr=0;

    leden=0;

    P0=q;

    leden=1;

    delay(10);

    leden=0;

    }

    void init()

    {

    num=1;

    leden=1;

    write(0x38);

    write(0x08);

    write(0x01);

    write(0x06);

    write(0x0f);

    num_1=0;

    i=0;j=0;a1=0;b=0;c=0;flag=0;fuhao=0;

    }

    void keyscan()

    {

    P1=0Xfe;

    if(P1!=0xfe)

    {

    delay(10);

    if(P1!=0xfe)

    {

    temp=P1&0xf0;

    switch(temp)

    {

    case 0xe0:num=0;break;

    case 0xd0:num=1;break;

    case 0xb0:num=2;break;

    case 0x70:num=3;break;

    }

    }

    while(P1!=0xfe);

    if(num==0||num==2||num==1)

    {

    if(j!=0)

    {

    write(0x01);

    j=0;

    }

    if(flag==0)

    {

    a1=a1*10+table[num];

    }

    else

    {

    b=b*10+table[num];

    }

    }

    else

    {

    flag=1;

    fuhao=4;//除号以按;

    }

    i=table1[num];

    write_data(0x30+i);

    }

    P1=0xfd;

    if(P1!=0xfd)

    {

    delay(10);

    if(P1!=0xfd)

    {

    temp=P1&0xf0;

    switch(temp)

    {

    case 0xe0:num=4;break;

    case 0xd0:num=5;break;

    case 0xb0:num=6;break;

    case 0x70:num=7;break;

    }

    }

    while(P1!=0xfd);

    if(num==4||num==5||num==6)

    {

    if(j!=0)

    {

    write(0x01);

    j=0;

    }

    if(flag==0)

    {

    a1=a1*10+table[num];

    }

    else

    {

    b=b*10+table[num];

    }

    }

    else

    {

    flag=1;

    fuhao=3;//乘号以按;

    }

    i=table1[num];

    write_data(0x30+i);

    }

    P1=0xfb;

    if(P1!=0xfb)

    {

    delay(10);

    if(P1!=0xfb)

    {

    temp=P1&0xf0;

    switch(temp)

    {

    case 0xe0:num=8;break;

    case 0xd0:num=9;break;

    case 0xb0:num=10;break;

    case 0x70:num=11;break;

    }

    }

    while(P1!=0xfb);

    if(num==8||num==9||num==10)

    {

    if(j!=0)

    {

    write(0x01);

    j=0;

    }

    if(flag==0)

    {

    a1=a1*10+table[num];

    }

    else

    {

    b=b*10+table[num];

    }

    }

    else if(num==11)

    {

    flag=1;

    fuhao=2;//jian号以按;

    }

    i=table1[num];

    write_data(0x30+i);

    }

    P1=0xf7;

    if(P1!=0xf7)

    {

    delay(10);

    if(P1!=0xf7)

    {

    temp=P1&0xf0;

    switch(temp)

    {

    case 0xe0:num=12;break;

    case 0xd0:num=13;break;

    case 0xb0:num=14;break;

    case 0x70:num=15;break;

    }

    }

    while(P1!=0xf7);

    switch(num)

    {

    case 12:{write(0x01);a1=0;b=0;flag=0;fuhao=0;}break;

    case 13:{

    if(flag==0)

    {

    a1=a1*10;

    write_data(0x30);

    }

    else if(flag==1)

    {

    b=b*10;

    write_data(0x30);

    }

    } break;

    case 14:{

    j=1;

    if(fuhao==1)

    {

    write(0x80+0x4f);

    write(0x04);

    c=a1+b;

    while(c!=0)

    {

    write_data(0x30+c%10);

    c=c/10;

    }

    write_data(0x3d);

    a1=0;b=0;

    flag=0;

    fuhao=0;

    }

    else if(fuhao==2)

    {

    write(0x80+0x4f);

    write(0x04);

    if(a1-b>0)

    {

    c=a1-b;

    }

    else

    {

    c=b-a1;

    }

    while(c!=0)

    {

    write_data(0x30+c%10);

    c=c/10;

    }

    if(a1-b<0)

    write_data(0x2d);

    write_data(0x3d);

    a1=0;b=0;flag=0;

    fuhao=0;

    }

    else if(fuhao==3)

    {

    write(0x80+0x4f);

    write(0x04);

    c=a1*b;

    while(c!=0)

    {

    write_data(0x30+c%10);

    c=c/10;

    }

    write_data(0x3d);

    a1=0;

    b=0;

    flag=0;

    fuhao=0;

    }

    else if(fuhao==4)

    {

    write(0x80+0x4f);

    write(0x04);

    i=0;

    c=a1/b;

    while(c!=0)

    {

    write_data(0x30+c%10);

    c=c/10;

    i++;

    if(i==3)

    write(0x2e);

    }

    if(a1/b<=0)

    write_data(0x30);

    write_data(0x3d);

    a1=0;

    b=0;

    flag=0;

    fuhao=0;

    }

    } break;

    case 15:

    {

    write_data(0x30+table1[num]);

    flag=1;

    fuhao=1;

    }    break;

    }

    }

    P1=0xf0;

    }

    void jisuanqi()

    {

    init();

    while(key)

    {

    keyscan();

    }

    }

    展开全文
  • 本文为单片机加法计算器程序,下面一起来学习下
  • 80C51单片机逐行扫描法的实现+简易计算器的功能实现。其中keyscan函数是逐行扫描函数,act是功能函数。
  • 《新基于51单片机的简易计算器》由会员分享,可在线阅读,更多相关《新基于51单片机的简易计算器(24页珍藏版)》请在人人文库网上搜索。1、基于51单片机的简易计算器1、前言:本设计是基于51系列单片机来进行的数字...
  • 简易计算器实验说明硬件设计动态数码管介绍矩阵按键介绍行列扫描线翻转法硬件实物连接软件设计`AC代码:`实验现象 实验说明 利用51单片机和keil uVision4共同完成通过按键来控制8位共阴数码管显示数据,并且通过按键...
  • 计算器采用51单片机,结合矩阵键盘以及1602显示屏,实现简单计算器功能,本系统中,最大计算为千位,超过千位,1602计算结果显示E,可以修改程序中的源码,即可使计算范围变大
  • 51单片机c语言计算器代码//8位液晶数码管显示的计算器,代码通俗易懂//用到数码管、矩阵键盘、中断三个模块#include"reg52.h"#include"stdio.h"typedef unsigned char uchar;typedef unsigned int uint;sbit Wei = ...
  • 在《51单片机(二十九)—— 矩阵键盘输入实验》中,我们对矩阵键盘的原理及使用方法进行了介绍。在本文中,我们采用矩阵键盘设计一个计算器,实现简单的计算器功能。 这个实验的代码的主函数如下所示。 main() ...
  • 单片机实现计算器加减乘除,可以实现四则运算的计算器,代码内有详细解释,keil软件实现,有兴趣欢迎大家下载 更多资料可私聊
  • 矩阵计算器

    2013-08-22 15:04:02
    矩阵键盘简易计算器,利用51单片机为控制核心,实现简易计算
  • 在上一篇简绍了几个重要的部分,下面先说一下计算器程序的 大体思路 : /这个计算器没有等于键,按下加号或减号相当于等号。/ 初始化中断,设置三个变量先用AB表示,值全部为零。 进入输入数字子程序,等待数字输入...
  • 51单片机简单计算器

    2021-07-20 09:19:20
    c51单片机简单计算器 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录c51单片机简单计算器前言代码缺点 前言 本文代码在下文博主给出的代码基础上进行了修改,关于硬件的介绍可以参考...
  • 基于51单片机计算器设计

    万次阅读 多人点赞 2019-04-22 16:05:21
    能做计算器单片机 单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域,电子、科技、通信、汽车、工业等。本次设计是设计一个简易计算器,能够...
  • 51单片机实现计算器

    2018-06-16 19:30:33
    16按键模拟计算器,1602显示 含protuse图 、

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 565
精华内容 226
关键字:

单片机计算器矩阵