蓝桥杯单片机学习记录3——第11届省赛真题练习1
前言
上一篇我们练习了第5届的省赛题,虽然这一届用的外设还挺多的,有ADC,RTC,EEPROM及基础外设全用上,但难度依然不是很高。
这次我们来练习第11届的省赛题,这一届的赛题有两题,温度采集与输出和模拟电压计数,这两题我都会出一篇讲解。这两题用的外设和功能要求都不是很多,但拿来练手还是可以的。
赛题要求
硬件框图
基础外设这部分数码管和LED两题都有用到,区别是按键,这里用的是BTN独立按键。
这里还用了温度测量和DAC的功能
功能描述
- 显示功能
- 按键功能
- DAC输出功能和LED指示灯功能
- 初始状态说明
初始状态上电默认处于数据显示界面。
温度上限参数 TMAX = 30℃
温度下限参数 TMIN = 20℃
设计思路
功能逻辑框图
yysy这个功能要求的确实少…对比第五届就显得过于简单了一点吧…
代码实现框图
依旧是四线一区的框架
代码分析
main.c
#include <STC15F2K60S2.H>
#include "hardware.h"
#include "iic.h"
#include "onewire.h"
bit StateFlag=0,TSFalg=0,TFlag=1,addFlag=0,subFlag=0;
u8 KeyNum, T, State=0, Page=0, TSelect=0;
u8 TMAX=30, TMIN=20;
void main()
{
InitInterrupt();
InitSystem();
DS18B20_ConvertT();
while(1)
{
Date_Task();
Key_Task();
Logic_Task();
Seg_Task();
}
}
- 定时器功能函数
void InitInterrupt(void)
{
TMOD = 0x01;
TH0 = (65535 - 10000) / 256;
TL0 = (65535 - 10000) % 256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
void Timer0() interrupt 1
{
static u8 cnt;
TL0 = (65535 - 10000) / 256;
TH0 = (65535 - 10000) % 256;
cnt++;
if(cnt >= 1)
{
KeyLoop();
cnt = 0;
}
}
- 数据更新函数
void Date_Task(void)
{
T = DS18B20_ReadT(); //读取DS18B20测量的温度
KeyNum = Key(); //读取按键键值
}
- 按键任务函数
void Key_Task(void)
{
if(KeyNum == 4) //按键S4功能
{
StateFlag = 1;TFlag = 1; //状态和温度选择标志位打开
}
if(KeyNum == 5) //按键S5功能
{
if(Page == 1) //设置页面时温度选择标志位打开
{
TSFalg = 1;
}
}
if(KeyNum == 6) //按键S6功能
{
if(Page == 1) //设置页面时温度加1标志位打开
{
addFlag = 1;
}
}
if(KeyNum == 7) //按键S7功能
{
if(Page == 1) //设置页面时温度减1标志位打开
{
subFlag = 1;
}
}
}
- 显示任务函数
void Seg_Task(void)
{
switch(Page) //0为显示页面,1为设置页面
{
case 0:
Nixie(1,10);
Nixie(7,T/10);
Nixie(8,T%10);
break;
case 1:
Nixie(1,11);
Nixie(4,TMAX/10);
Nixie(5,TMAX%10);
Nixie(7,TMIN/10);
Nixie(8,TMIN%10);
break;
}
}
-逻辑任务函数
void Logic_Task(void)
{
Page_Task();
DAC_Task();
LED_Task();
}
//页面任务函数
void Page_Task(void)
{
if(StateFlag) //当状态标志位打开,选择状态
{
switch(State)
{
case 0:Page=0;State=1;StateFlag=0;break; //显示页面,状态标志位关闭
case 1:Page=1;State=0;StateFlag=0;break; //设置页面,状态标志位关闭
}
}
if(TSFalg) //当温度标志位打开,选择温度
{
switch(TSelect)
{
case 0:TFlag=0;TSelect=1;TSFalg=0;break; //选择TMAX,温度标志位关闭
case 1:TFlag=1;TSelect=0;TSFalg=0;break; //选择TMIN,温度标志位关闭
}
}
if(TFlag==0&&addFlag==1) //TMAX+1
{
++TMAX;
addFlag = 0;
}
if(TFlag==1&&addFlag==1) //TMIN+1
{
++TMIN;
addFlag = 0;
}
if(TFlag==0&&subFlag==1) //TMAX-1
{
--TMAX;
subFlag = 0;
}
if(TFlag==1&&subFlag==1) //TMIN-1
{
--TMIN;
subFlag = 0;
}
if(TMAX > 99) TMAX = 1; //使TMAX和TMIN在一个合理的数值范围间调节
else if(TMAX < 1) TMAX = 99;
if(TMIN > 99) TMIN = 1;
else if(TMIN < 1) TMIN = 99;
if(Page == 0) //在返回显示页面时当TMAX<TMIN,不能返回显示页面
{
if(TMAX < TMIN)
{
Page=1;State=0;
}
}
}
//DAC任务函数
void DAC_Task(void)
{
if(T > TMAX) DAC(204); //输出4.0V,0xcc
else if((T<=TMAX) && (T>=TMIN)) DAC(156); //输出3.0V,0x99
else if(T < TMIN) DAC(102); //输出2.0V,0x66
}
//LED任务函数
void LED_Task(void)
{
if(TMAX < TMIN) OutputP0(4,~0x08);
else
{
if(T > TMAX) OutputP0(4,~0x01);
else if((T<=TMAX) && (T>=TMIN)) OutputP0(4,~0x02);
else if(T < TMIN) OutputP0(4,~0x04);
}
}
harwdare.c,iic.c,OneWire.c这些文件的API函数我就不放出来了跟之前发过的一样,后面也是会考虑出一个合集的。
小结
总结一下就是非常简单,基本上是没什么难度的,任务要求我也是全部都完成了。
后面会接着更新第二题,觉得对你有帮助的话记得点赞加关注哦 >_< !