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
51单片机实现4位数以内的加减法相关推荐
- 51单片机4位数乘法C语言,51单片机实现4位数以内的加减法
中南民族大学,电子信息工程学院,开设了一门课程,叫<嵌入式电路设计>,由舒老师带头,旨在引导低年级的学生入门嵌入式,其内容比较多,包括模电.数电.C语言.单片机.EDA技术等.最近有位师弟 ...
- 51单片机2位数简易计算器C语言实现
今天是51单片机模块! 事实上,也是离不开C语言编程啦 适合手头上有51单片机且对硬件有兴趣的小伙伴们 这里推荐初学者(我自己就是哈哈哈)购买天祥电子51单片机开发板(TX-1C) 话不多说,上代码: ...
- 单片机 | 51单片机原理
[金善愚] 单片机应用原理篇 笔记整理 课程视频 :https://space.bilibili.com/483942191/channel/collectiondetail?sid=51090 文章 ...
- 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》
http://www.amobbs.com/forum.php?mod=viewthread&tid=3396563 <uCOS51移植心得>---七年前之<快快乐乐跟我学5 ...
- 单片机原理与实践学习记录之51单片机硬件基础
单片机原理与实践学习记录 第三课(更新时间:2021.9.6) 51单片机硬件基础 MCS-51是Intel公司生产的一个单片机系列的总称.在功能上,该系列单片机有基本型和增强型两大类,通常以芯片型号 ...
- 51单片机 | DAC数模转换实验
文章目录 一.DAC介绍 2.DAC 工作原理 二.PWM介绍 三.硬件设计 四.软件设计 1.PWM实现函数 2. 主函数 五.实验现象 这一节来介绍下如何使用 51 单片机输出模拟信号,要让 ...
- codeblocks 51单片机学习(四)简易计算器
基于51单片机的数码管和矩阵按键实现的简易计算器,其实可以加入的东西有很多,就像我这个负数运算还没有加进去,以及我的除法运算只能算655(65535/100)以内的数,不过就先做到这里,这个作品至少已 ...
- 基于51单片机LCD1602的简易矩阵键盘密码锁
写在前面 初次开始写博客,表达方面也许会有很多不足,希望自己能通过这种方式巩固自己的学习和锻炼表达能力,同时也是对于自己学习的记录. 一.功能介绍 四位密码锁,密码可更改,输入仅四次以内有效 矩阵键盘 ...
- 51单片机常用寄存器速查
51单片机常用寄存器速查表 一 : 定时器 / 计数器方式选择 : TMOD 地址 (89H) 不可位寻址 D7 D6 D5 D4 D3 D2 D1 D0 GATE C/T M1 M0 GATE C/ ...
最新文章
- MarkDown入门及技巧
- 几个常用有力的特征的分析LBP、HOG、FAST、SIFT/SURF、MSER、BRISK
- python最长回文子串leetcode_Python版LeetCode5. 最长回文子串
- KMP算法求解next数组值(模式串从下标0开始或从下标1开始)以及求值后与主串的匹配过程
- 窗体的Alpha通道透明色支持
- CentOS7 安装 Nginx PHP
- 要想挣大钱,就要懂一个基本
- pandas数据处理实践三(DataFrame.apply、merge、rename,数据预处理、DataFrame.drop_duplicates去重)
- 全网首发:编译jna:dispatch.h:30:34: fatal error: com_sun_jna_Function.h: 没有那个文件或目录
- 163Editor 编辑器概览
- Qt 环境下MAPX组件的编程
- WPS使用VB批量将多个sheet单独存储为xls文件
- 典型相关分析(SPSS)
- java -jar xxx.jar
- Python学习之——列表、字典、实验低配版非诚勿扰
- android 壁纸存储位置,手机图片去了哪?教你理清照片存放路径(全文)
- 今日头条Go建千亿级微服务的实践
- sqlite数据库使用
- 03 朴素贝叶斯方法
- C#WinForm文本框记忆上次输入文本内容