微信搜索:ReCclay,也可免费阅读博主蓝桥系列所有文章,后台回复“代码”即可获取蓝桥所有备赛代码!关注博主公众号,还可拥有加入博主粉丝群实时沟通技术难题、免费下载CSDN资源等多项福利,还在等什么呢?快快扫码关注,学习才不会迷路。
这里再向各位同学推荐一个CSDN博主 ReRrain 的蓝桥备赛博客,博主秉持初学者思路,向你讲述自己蓝桥备赛的心路历程,娓娓道来蓝桥备赛经验,个人觉得非常不错,值得细细品读。
导读:《蓝桥杯单片机组》专栏文章是博主2018年参加蓝桥杯的单片机组比赛所做的学习笔记,在当年的比赛中,博主是获得了省赛一等奖,国赛二等奖的成绩。成绩虽谈不上最好,但至少问心无愧。如今2021年回头再看该系列文章,仍然感触颇多。为了能更好地帮助到单片机初学者,今年特地抽出时间对当年的文章逻辑和结构进行重构,以达到初学者快速上手的目的。需要指出的是,由于本人水平有限,如有错误还请读者指出,非常感谢。那么,接下来让我们一起开始愉快的学习吧。
不积跬步无以至千里,不积小流无以成江海。
一、前言
学习完毕基础模块后,接下来就是一系列的小项目实战了。在该系列实战中,希望读者可以仔细研究每个实战项目的代码细节,力求吃透每一个小知识点,这样之后做起来省赛题目会感觉非常的得心应手!
本节我们将基于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,即可免费阅读博主蓝桥系列所有文章,后台回复“代码”即可获取蓝桥所有备赛代码!关注博主公众号,还可拥有加入博主粉丝群实时沟通技术难题、免费下载CSDN资源等多项福利,还在等什么呢?快快扫码关注,学习才不会迷路。