不积跬步无以至千里,不积小流无以成江海。
基于1602液晶的整形加减乘除计算器,未考虑连续操作,未考虑被除数等问题。
代码下载可以到我的Github<传送门>
就只拉出main.c 说下主要实现思路:
/* ******************************************************************************* * 文件名:main.c * 描 述: * 作 者:CLAY * 版本号:v1.0.0 * 日 期: * 备 注: * ******************************************************************************* */ #include "config.h" #include "lcd1602.h" #include "keyboard.h" long num1=0, num2=0, result=0; u8 step=0, oprt=0; u8 T0RH, T0RL; void ConfigTimer0(u16 ms); void main() { EA = 1; ConfigTimer0(1); InitLcd1602(); LcdShowStr(15, 1, "0"); while(1) { KeyDriver(); } } u8 LongToStr(u8 *str, long dat) { u8 i=0; u8 len=0; u8 buf[12]; if(dat < 0) { dat = -dat; len++; *str++ = '-'; } do{ buf[i++] = dat % 10; dat /= 10; }while(dat > 0); len += i; while(i-- > 0) { *str++ = buf[i] + '0'; } *str = '\0'; return len; } void Reset() { step = 0; num1 = 0; num2 = 0; result = 0; LcdFullClear(); } void NumKeyAction(u8 num) { u8 buf[16]; u8 len; if(step > 1) { Reset(); } if(step == 0) { num1 = num1 * 10 + num; len = LongToStr(buf, num1); LcdShowStr(16-len, 1, buf); } else { num2 = num2 * 10 + num; len = LongToStr(buf, num2); LcdShowStr(16-len, 1, buf); } } void ShowOprt(u8 y, u8 type) { switch(type) { case 0: LcdShowStr(0, y, "+"); break; case 1: LcdShowStr(0, y, "-"); break; case 2: LcdShowStr(0, y, "*"); break; case 3: LcdShowStr(0, y, "/"); break; default: break; } oprt = type; } void OprtKeyAction(u8 type) { u8 len; u8 buf[12]; if(step == 0) { step = 1; ShowOprt(1, type); len = LongToStr(buf, num1); LcdShowStr(16-len, 0, buf); LcdShowStr(15, 1, "0"); LcdAreaClear(1, 1, 14); } } void GetResult() { u8 len; u8 buf[12]; if(step == 1) //最好加上这个! { switch(oprt) { case 0: result = num1 + num2; break; case 1: result = num1 - num2; break; case 2: result = num1 * num2; break; case 3: result = num1 / num2; break; default: break; } step = 2; ShowOprt(0, oprt); LcdShowStr(0, 1, "="); len = LongToStr(buf, result); LcdAreaClear(1, 1, 15-len); LcdShowStr(16-len, 1, buf); } } void KeyAction(u8 keycode) { if((keycode >= '0') && (keycode <= '9')) { NumKeyAction(keycode - '0'); } else if(keycode == 0x26) { OprtKeyAction(0); } else if(keycode == 0x28) { OprtKeyAction(1); } else if(keycode == 0x25) { OprtKeyAction(2); } else if(keycode == 0x27) { OprtKeyAction(3); } else if(keycode == 0x1B) { Reset(); LcdShowStr(15, 1, "0"); } else if(keycode == 0x0D) { GetResult(); } } void ConfigTimer0(u16 ms) { u32 tmp; tmp = 11059200 / 12; tmp = (tmp * ms) / 1000; tmp = 65536 - tmp; T0RH = (u8)(tmp >> 8); T0RL = (u8)tmp; TMOD &= 0xF0; TMOD |= 0x01; TH0 = T0RH; TL0 = T0RL; ET0 = 1; TR0 = 1; } void InterruptTimer0() interrupt 1 { TH0 = T0RH; TL0 = T0RL; KeyScan(); }由KeyAction 引出的几个函数,NumKeyAction 、OprtKeyAction、Reset 以及 GetResult 分别实现即可。 总体来看也就那么回事,就是实现的细节一不留神就出错了,务必谨慎谨慎再谨慎!
另外,我定义了两个全部变量step 和 oprt 来标记当前的输入状态(第一个数还是第二个数)以及 所要进行的运算类型。(因为这里是一次运算,所以直接定义了全局,相对方便。)
step 的变化是在输入符号 加减乘除或者等于号变的!因为一次运算,一旦按完等号我么那就让step = 2 对应的操作是 Reset。 还有一次运算放置连续运算出错我们只在OprtKeyAction 中处理step == 1 的情形,其他都不管。
代码需要注意的也就这么多,这种模块化思想是不是又更深入你心了呢?
ReCclay 认证博客专家 嵌入式软件开发 机器/深度学习 全栈技术学习者 大家好,我是博主ReCclay,目前处于研究生阶段,就读于电子科技大学,主攻方向为汽车辅助驾驶算法研究。入站以来,凭借坚持与热爱,以博文的方式分享所学,截止目前累计博文数量达800余篇,累计受益人次达130w+次,涉及领域包括但不限于物联网开发、单片机开发、Linux驱动开发、FPGA开发、前/后端软件开发等。在未来我将继续专注于嵌入式相关领域,学习更多的科技知识,输出更高质量的博文。