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 
  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位数以内的加减法)