51单片机实现4位数以内的加减法

  中南民族大学,电子信息工程学院,开设了一门课程,叫《嵌入式电路设计》,由舒老师带头,旨在引导低年级的学生入门嵌入式,其内容比较多,包括模电、数电、C语言、单片机、EDA技术等。最近有位师弟找到我,希望我能帮他指导一下,利用AT89C52单片机设计一个最小系统,其中包括矩阵键盘、数码管显示、中断、2位数加减法、定时计数与暂停等功能。我也粗略的设计了一个,在此分享出来,希望能对初学者有所帮助,使更多的人加入到嵌入式的行业来。

  开发工具:keil

  仿真工具:proteus

电路图

代码如下:

头文件:inc_all.h

 1 #ifndef INC_ALL_H_
 2 #define INC_ALL_H_
 3 
 4 volatile unsigned char keyValue;
 5 volatile unsigned char sign;
 6 volatile long int opr1;
 7 volatile long int opr2;
 8 volatile long int SysValue=0;
 9 volatile int keyCounter;
10 volatile int cnt50ms=0;
11 volatile bit StartFlag;
12 
13 void Init_Timer0();
14 void Init_Timer1();
15 void delayms(int t);
16 unsigned char KeyScan(void);
17 void showNumber(long int num);
18 void keyAnalyzing(unsigned char keyval);
19 
20 #endif

源文件如下:main.c

  1 #include <reg52.h>
  2 #include "inc_all.h"
  3 //=======================================================
  4 //  数码管显示译码,共阴极
  5 //  0,1,2,3,4,5,6,7,8,9,灭,‘E’,'-'
  6 //=======================================================
  7 unsigned char code table[]={0x3F,0x06,0x5b,0x4F,0x66,
  8                             0x6d,0x7d,0x07,0x7F,0x6F,
  9                             0x00/* trun off */,
 10                             0x79/* Error */,
 11                             0x40/* - */};
 12 //========================================================
 13 //  定时器0初始化函数,定时50毫秒
 14 //  用键盘上的“START”键启动计数
 15 //  用键盘上的“SUS”键暂停计数
 16 //========================================================
 17 void Init_Timer0()      
 18 {
 19     TMOD |= 0x01;
 20     TH0  = 0x3C;
 21     TL0  = 0xB0;
 22     TR0  = 0;
 23     ET0  = 1;
 24 }
 25 //=========================================================
 26 //  定时器1初始化函数
 27 //  定时23毫秒,用于显示
 28 //  初始化后计时启动
 29 //=========================================================
 30 void Init_Timer1()     
 31 {
 32     TMOD |= 0x10;
 33     TH1  = 0xA6;
 34     TL1  = 0x28;
 35     TR1  = 1;
 36     ET1  = 1;
 37 }
 38 //=========================================================
 39 //  延时函数
 40 //=========================================================
 41 void delayms(int t)
 42 {
 43     int i,j;
 44     for(i=t;i>0;i--)
 45         for(j=25;j>0;j--)
 46             ;
 47 }
 48 //=========================================================
 49 //  四位数码管显示函数
 50 //  能自动灭零,自动识别正负号
 51 //  数值超出显示范围时显示错误"E---"
 52 //========================================================= 
 53 void showNumber(long int num)
 54 {
 55     unsigned char q,s,b,g;
 56     if(num>=0)
 57     {
 58         q = num/1000;
 59         b = num/100%10;
 60         s = num/10%10;
 61         g = num%10;
 62         if(num<10)
 63         {
 64             q = 10;
 65             b = 10;
 66             s = 10;
 67         }
 68         else if(num<100)
 69         {
 70             q = 10;
 71             b = 10;
 72         }
 73         else if(num<1000)
 74             q = 10;
 75         else if(num>9999)
 76         {
 77             q = 11;     //show error
 78             b = 12;
 79             s = 12;
 80             g = 12;
 81         }
 82     }
 83     else
 84     {
 85         if(num>-1000)
 86         {
 87             q = 12;
 88             b = (0-num)/100;
 89             s = (0-num)/10%10;
 90             g = (0-num)%10;
 91         }
 92         else
 93         {
 94             q = 11;     //show error
 95             b = 12;
 96             s = 12;
 97             g = 12;
 98         }
 99     }
100     P0 = 0x00;
101     P0 = table[q];
102     P2 = 0xFE;
103     delayms(10);
104     P0 = 0x00;
105     P0 = table[b];
106     P2 = 0xFD;
107     delayms(10);
108     P0 = 0x00;
109     P0 = table[s];
110     P2 = 0xFB;
111     delayms(10);
112     P0 = 0x00;
113     P0 = table[g];
114     P2 = 0xF7;
115     delayms(10);       
116 }
117 //=========================================================
118 //  键盘扫描函数
119 //  返回按键情况,扫描结果
120 //=========================================================      
121 unsigned char KeyScan(void)
122 {
123     unsigned char temp=0xF0;
124     P1 = temp;
125     temp = P1;
126     if(temp!=0xF0)
127     {
128         delayms(5);     //去抖动
129         temp = P1;
130         if(temp!=0xF0)
131         {
132             int t=0x01,i;
133             for(i=0;i<4;i++)
134             {
135                 P1 = ~(t<<i);
136                 temp = P1;
137                 switch(temp)                //按行扫描
138                 {
139                     case 0xee:  return '1';
140                     case 0xde:  return '2';
141                     case 0xbe:  return '3';
142                     case 0x7e:  return '+'; //加号
143 
144                     case 0xed:  return '4';
145                     case 0xdd:  return '5';
146                     case 0xbd:  return '6';
147                     case 0x7d:  return '-'; //减号
148 
149                     case 0xeb:  return '7';
150                     case 0xdb:  return '8';
151                     case 0xbb:  return '9';
152                     case 0x7b:  return 'r'; //复位
153 
154                     case 0xe7:  return '0';
155                     case 0xd7:  return 's'; //启动
156                     case 0xb7:  return 't'; //暂停
157                     case 0x77:  return '='; //等于
158                     default:    ;
159                 }
160             }
161         }
162     }
163     return '0';
164 }
165 //=========================================================
166 //  键盘解析函数
167 //  对扫描得到的键值进行解析
168 //=========================================================
169 void keyAnalyzing(unsigned char keyval)
170 {
171     if(keyval>='0' && keyval<='9')
172     {
173         switch(keyCounter)
174         {
175             case 0: SysValue = (int)keyval-0x30; 
176                     keyCounter++;     
177                     break;
178             case 1: ;
179             case 2: ;
180             case 3: SysValue =SysValue*10+(int)keyval-0x30;
181                     keyCounter++;
182                     break;
183             case 4: SysValue =SysValue*10+(int)keyval-0x30; 
184                     keyCounter=0; 
185                     break;
186         }
187     }
188     else
189     {
190         switch(keyval)
191         {
192             case '+':   sign = '+';                        
193                         opr1 = SysValue;
194                         SysValue = 0;
195                         keyCounter = 0;                        
196                         break;
197             case '-':   opr1 = SysValue;
198                         SysValue = 0;
199                         keyCounter = 0;
200                         sign = '-'; 
201                         break;
202             case 's':   sign = 's';  
203                         TR0 = 1;     //启动计数
204                         StartFlag = 1;
205                         break;
206             case 't':   sign = 't'; 
207                         if(StartFlag) 
208                             TR0 ^= 1;//暂停/启动计数
209                         break;
210             case 'r':   sign = 'r';  
211                         opr1 = 0;
212                         opr2 = 0;
213                         SysValue = 0;
214                         keyCounter = 0;
215                         TR0 = 0;    //停止计数器
216                         StartFlag = 0;
217                         break;
218             case '=':   opr2 = SysValue;
219                         if(sign=='+')
220                             SysValue = opr1+opr2;
221                         else if(sign=='-')
222                             SysValue = opr1 - opr2;
223                         opr1 = 0;
224                         opr2 = 0;
225                         keyCounter = 0;
226                         sign = '='; 
227                         break;
228         }
229     }
230 }
231 //=========================================================
232 //  主函数main
233 //  全局采用中断方式,有利于降低功耗
234 //=========================================================
235 void main()
236 {
237     EX0 = 1;        //允许外部0中断
238     IT0 = 1;        //外部0中断方式为 “下降沿”
239     Init_Timer0();  /*初始化定时器0,在键盘上点击“START”后
240                     开始计数,定时时间为1秒*/
241     Init_Timer1();  /*初始化定时器1,用于定时显示,定时时间
242                     为23毫秒,即每隔23毫秒调用一次显示函数*/
243     EA  = 1;        //总中断开
244     P1 = 0xF0;      //初始键盘接口     
245     while(1) ; 
246 }
247 //=========================================================
248 //  按键中断服务函数,采用外部中断0
249 //  按键中断,在中断里面检测按键并解析按键
250 //=========================================================
251 void key_isr(void) interrupt 0
252 {
253     EA = 0;
254     keyValue = KeyScan();
255     keyAnalyzing(keyValue);
256     P1 = 0xF0;
257     EA = 1;
258 }
259 //=========================================================
260 //  定时器0中断服务函数
261 //  用于,定时1秒计数,计数到8888后返回重新新计数
262 //=========================================================
263 void timer0_isr(void) interrupt 1
264 {
265     TR0  = 0;
266     TH0  = 0x3C;
267     TL0  = 0xB0;
268     TR0  = 1;   
269     cnt50ms++;          
270     if(cnt50ms==19)     //计数20次  20*50 = 1000毫秒,即1秒
271     {
272         cnt50ms = 0;
273         SysValue=(SysValue>8887)?0:SysValue+1;
274     }
275 }
276 //=========================================================
277 //  定时器1中断服务函数
278 //  方式1,定时时间为23毫秒
279 //  用于数码管显示
280 //=========================================================
281 void timer1_isr(void) interrupt 3
282 {
283     TR1  = 0;
284     TH1  = 0xA6;
285     TL1  = 0x28;
286     showNumber(SysValue);
287     TR1  = 1;   
288 }

 

转载于:https://www.cnblogs.com/phelonYang/archive/2012/12/18/2823550.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科幻作家阿西莫夫上世纪预言2019: 计算机彻底变革教育,太空移民进行中

全世界只有3.14 % 的人关注了数据与算法之美2019年必将是充满机遇与挑战的一年&#xff0c;一年的时间世界可能发生很大的变化。我们应该如何期待新的一年&#xff1f;在这&#xff0c;数据汪带大家重新读1983年美国作家艾萨克阿西莫夫&#xff08;Isaac Asimov&#xff09;对2…

6月程序员平均工资出炉,你拖后腿了吗?

据有关部门统计&#xff1a;6月份全国招收程序员435501人&#xff0c;平均工资为15052元&#xff0c;很多小伙伴儿纷纷感慨工资被平均了。然而6月程序员工资的中位数却是13000元&#xff0c;这说明什么&#xff1f;也许不是被平均&#xff0c;而是真的拖后腿了&#xff0c;下面…

学习爬虫限时只需9.9,还在犹豫什么?

收拾行李回老家的小天&#xff0c;新春福利还是要准时送到大家手上的&#xff01;随着互联网的发展&#xff0c;google、百度等搜索引擎让我们获取信息愈加方便。Python是当今世界最热门的编程语言之一&#xff0c;在科研领域也发挥着强大的作用&#xff0c;尤其是在日常的学习…

eomj表情 mysql_mysql存储4字节的表情包数据报异常_Emoji表情包_Incorrect string value: #3...

本文章转载自&#xff1a;https://www.cnblogs.com/coprince/p/7485968.html原文如下&#xff1a;问题描述&#xff1a;从新浪微博抓取消息保存到MySQL数据中&#xff0c;对应数据库字段为varchar&#xff0c;字符编码utf-8。部分插入成功&#xff0c;部分插入失败&#xff0c;…

如何快速正确的安装 Ruby, Rails 运行环境

2019独角兽企业重金招聘Python工程师标准>>> 系统需求 首先确定操作系统环境&#xff0c;不建议在 Windows 上面搞&#xff0c;所以你需要用: Mac OS X任意 Linux 发行版本(Ubuntu,CentOS, Redhat, ArchLinux ...)强烈新手使用 Ubuntu 省掉不必要的麻烦&#xff01;…

你怕是对MD5算法有误解

大家常听到“MD5加密”、“对称加密”、“非对称加密”&#xff0c;那么MD5属于哪种加密算法&#xff1f;面试官问这样的问题&#xff0c;准是在给你挖坑。"MD5加密"纯属口嗨&#xff0c;MD5不是加密算法&#xff0c;是摘要算法。今天小码甲带大家梳理加密算法、摘要…

java main 声明_Java中main方面面试题

1.不用main方法如何定义一个类&#xff1f;不行&#xff0c;没有main方法我们不能运行Java类。在Java 7之前&#xff0c;你可以通过使用静态初始化运行Java类。但是&#xff0c;从Java 7开始就行不通了。2.main()方法需要的参数不是字符串数组&#xff1f;不是的&#xff0c;ma…

还在集什么五福,史上最惨锦鲤再次来袭!奖品堪比5年高考3年模拟!

全世界只有3.14 % 的人关注了数据与算法之美在锦鲤盛行的2018年我们超级数学建模也跟风来了一个“史上最惨锦鲤”活动为什么叫史上最惨锦鲤呢因为平常看一本数学书就已经头疼了何况我们奖品还是100本数学书试问除了学霸还有谁能承受这种殊荣巧的是最后的得主还真是一个学霸那就…

Python: logging日志模块简单示例

2019独角兽企业重金招聘Python工程师标准>>> Python的logging模块提供了通用的日志系统&#xff0c;可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别&#xff0c;并可以采用不同的方式记录日志&#xff0c;比如文件&#xff0c;HTTP GET/POST&#x…

开源基金会为何辟谣 鸿蒙背后有何玄机

最近&#xff0c;鸿蒙OS曝光率极高&#xff0c;受网络舆论热捧。铁流原本是不太愿意碰这个雷的&#xff0c;因网友提问&#xff0c;所以谈一谈这个事情。OpenHarmony和Harmony是两回事6月2日&#xff0c;公司官宣鸿蒙OS&#xff0c;给出了百台机型的升级计划&#xff0c;而且还…

java get image获取根路径_Java 获取资源文件路径

1 问题描述通过源码运行时&#xff0c;一般使用如下方式读取资源文件&#xff1a;String str "1.jpg";资源文件与源码文件放在同一目录下&#xff0c;或者拥有同一父级目录&#xff1a;String str "a/b/1.jpg";这样直接编译运行没有问题&#xff0c;但是…

阿里云开源的Blink,计算能力很疯狂:一眨眼,全部都算好!

全世界只有3.14 % 的人关注了数据与算法之美前两天&#xff0c;阿里云宣布开源“计算王牌”——实时计算平台Blink&#xff0c;回馈给ApacheFlink社区。官方称&#xff0c;计算延迟已经降到毫秒级&#xff1a;浏览网页的时候&#xff0c;你只是眨了一下眼睛&#xff0c;但在淘宝…

NET问答: 如何用 C# 计算相对时间 ?

咨询区 Jeff Atwood&#xff1a;给定一个 DataTime 值&#xff0c;如何计算如下时间&#xff1f;比如说&#xff1a;2 小时前&#xff1f;3 天前&#xff1f;1 个月前&#xff1f;回答区 neuracnu&#xff1a;我在 DateTime 类上做了一个扩展方法&#xff0c;你可以给它传递未来…

有趣程序和让人捧腹大笑的注释,你的注释还不够骚

全世界只有3.14 % 的人关注了数据与算法之美一&#xff0c;这个是关于数组的操作&#xff0c;数据汪也是才知道&#xff0c;居然还有这种操作# include <stdio.h>int main(){ int num[] {1,2,3,4};printf("the 3[num] result is : %d\n", 2[num]);return 0;}结…

java linux下载文件_java 从linux 下载文件

public static void main(String[] args) {SshClient client new SshClient();try {ConsoleKnownHostsKeyVerification console new ConsoleKnownHostsKeyVerification();client.connect("192.168.13.51", 22);//IP和端口//设置用户名和密码PasswordAuthentication…

读jQuery之二十(Deferred对象)

Deferred对象是由 jQuery.Deferred 构造的&#xff0c;jQuery.Deferred 被实现为简单工厂模式。 它用来解决JS中的异步编程&#xff0c;它遵循 Common Promise/A 规范。实现此规范的还有 when.js 和 dojo。 $.Deferred作为新特性首次出现在版本1.5中&#xff0c;这个版本利用De…

.NET之盛派微信SDK简单操作

开篇语在6月5号&#xff0c;我报名去参加了微软举办的一个线下分享的技术市集&#xff0c;分享人是苏老师和赵老师(非常感谢)&#xff0c;其中苏老师讲述了关于一些容器的部署等操作(也可以观看我的历史文章)&#xff0c;其中关于部署的示例代码是使用盛派微信SDK做了一个对接微…

预售┃连锁反应装置积木好玩到尖叫!

▲数据汪特别推荐点击上图进入玩酷屋之前推荐的“小小机械师”成了孩子最受欢迎的玩具&#xff0c;玩了的孩子几乎没有不喜欢的。还有家长买多套送给朋友的孩子作为生日礼物。有家长来问&#xff0c;还有没有这种类型的新产品。和厂家咨询后&#xff0c;小木找到了一款“小小机…

java文件调用脚本_Java中调用文件中所有bat脚本

//调用外部脚本String fileipsnull;//所有的路径String[] filesnull;String fileipnull;//单个路径try {InputStream is Thread.currentThread().getContextClassLoader().getResourceAsStream("pdfconfig.properties"); //加载线程文件成为流Properties prop new …

VMware VSphere 虚拟化云计算学习配置笔记(四)

2:接下来配置安装vcenter-db&#xff0c;安装MS SQL 2008r2 在vcenter-db服务器上安装配置MS SQL 2008r2过程截图&#xff1a; 这里可能会要耐心等一下才会出现一下提示&#xff1a; 选择左边installation 之后出现右边第一项新的安装&#xff1a; 转载于:https://blog.51cto.c…