文章目录

前言一、陷阱分析二、代码相关定义、声明1.变量声明2.函数声明

三、主要函数1.函数初始化 :关闭蜂鸣器、定时器初始化、设置时间、消除85℃影响、开启总中断2.按键扫描:长按松开清除数据,短按切换界面,加减参数3.数据采集与处理:有效性判断、禁止连续采集、3s返回界面、储存数据、比较最大值、求平均值4.数码管显示:无效字符、位不足补0、采集次数为0时要求位熄灭6.LED显示:点亮、熄灭、闪烁7.中断服务函数8.延时函数

四、经验与感受 细节剖析(后续补充)五、链接1.第十四届蓝桥杯单片机省赛真题PDF2.第十三届蓝桥杯嵌入式国赛真题(基于HAL库的巨简代码+超级详解)3.第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)4.第十三届蓝桥杯嵌入式省赛第二场真题(基于HAL库的巨简代码+超级详解)5.第十二届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

前言

相关说明:

开发板:CT107D——IAP15F2K61S2 开发环境: Keil5 涉及题目:第十四届蓝桥杯单片机省赛真题

一、陷阱分析

数码管忘记不足2位左侧补0;采集的湿度无效时,温湿度、采集次数、采集时间不统计,更不参与计算平均值;温度参数有边界条件;在时间回显子界面长按松开后才能清零,不松开不能清零,且采集时间、次数、平均值、最大值、储存的数据都需清零;采集湿度无效时,温度需正常显示,但不能储存;L4闪烁时,如果长按清零数据,此时无采集的温度,L4应停止闪烁;L6点亮时,如果长按清零数据,由于采集次数变为0,题目要求为≥2,L6应熄灭;触发采集后经历3s应返回原来的界面,不能返回到固定的任意界面,且3s不能内重复采集,按键操作无效;进入温湿度界面时,L1、L2应熄灭,L3点亮。

二、代码相关定义、声明

1.变量声明

xdata unsigned long uwTick,cjTick,kTick;//单片机上电后每1ms uwTick+1,cjTick用于记录采集时间,kTick记录按键长按时间。

xdata unsigned int Key_Slow_Down,Seg_Slow_Down,Led_Slow_Down;//减速变量,Led_Slow_Down也可用于led的0.1s闪烁

xdata unsigned char seg_buf[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//数码管缓存数组,用于记录段选值

xdata unsigned char wd,cjwd[255]={0},cjsd[255];//wd为当前采集的温度,后两个数组用来储存采集的数据

unsigned char uled;//Led显示的参数

unsigned char rtc[3]={13,03,05};//时间数组

unsigned char cjsj[2]={0,0};//记录发生采集的时间

unsigned char jiemian;//界面参数 0为时间界面 1为回显界面 2为参数界面

unsigned char hxjm;//回显界面参数 0为温度回显界面 1为湿度回显界面 2为时间回显界面

unsigned char flag;//采集标志位 0为未进行采集,按键操作无效 1为正在进行采集,按键操作无效

unsigned char sjwx;//数据无效标志位 0为数据有效,将采集的温度湿度写入数组 1为数据无效,不进行操作

unsigned char tmax,hmax,n;//分别为采集温度的最大值,采集湿度的最大值,采集次数

unsigned char wdcs=30;//温度参数,初始化为30

unsigned char gmdz;//AD光敏通道读取值

unsigned int freq;//当前测量555信号发生器的频率

unsigned int wd_sum,sd_sum;//已测所有温度(湿度)数据的总和

float wdpj,sdpj;//已测所有温度(湿度)数据的平均值

2.函数声明

void Key_Proc();

void Data_Proc();

void Seg_Proc();

void Led_Proc();

三、主要函数

1.函数初始化 :关闭蜂鸣器、定时器初始化、设置时间、消除85℃影响、开启总中断

void main(void)

{

close();//关闭蜂鸣器,熄灭数码管

Timer1Init();//定时器1初始化

EA = 1;//开启总中断

Set_Rtc(rtc);//设置时间

Freqinit();//测频初始化

rd_temperature();//消除85℃影响

Delay750ms();

while(1)

{

Key_Proc();

Data_Proc();

Seg_Proc();

Led_Proc();

}

}

2.按键扫描:长按松开清除数据,短按切换界面,加减参数

void Key_Proc(void)

{

static unsigned char key_old;

unsigned char key_value, key_down,key_up;

unsigned char i;

if(Key_Slow_Down) return;

Key_Slow_Down = 1;

key_value = Key_Read();

key_down = key_value & (key_old ^ key_value);

key_up = ~key_value & (key_old ^ key_value);

key_old = key_value;

if(flag==0)//采集标志位为0,处于未采集状态,按键操作有效

{

if(key_down)

kTick=uwTick;//有按键按下开始计时

if(uwTick-kTick>2000)//长按超过2s

{

switch(key_up)//松开

{

case 9:

if((jiemian==1)&&(hxjm==2))//时间回显子界面

{

for(i=0;i<=n;i++)//采集数据清零

{

cjwd[i]=0;

cjsd[i]=0;

}

tmax=0;hmax=0;//最大值清零

wdpj=0;sdpj=0;//平均值清零

cjsj[0]=cjsj[1]=0;//采集时间清零

n=0;//采集次数清零

}

break;

}

}

else//短按

{

switch(key_up)

{

case 4:

if(++jiemian==3)//切换界面

jiemian=0;

if(jiemian==1)//时间界面切换到回显界面

hxjm=0;//处于温度回显子界面

break;

case 5:

if(jiemian==1)//回显界面

if(++hxjm==3)//回显子界面切换

hxjm=0;

break;

case 8:

if(jiemian==2)//参数界面

if(++wdcs==100)//钳制在99

wdcs=99;

break;

case 9:

if(jiemian==2)//参数界面

if(--wdcs>200)//钳制在0

wdcs=0;

break;

}

}

}

}

3.数据采集与处理:有效性判断、禁止连续采集、3s返回界面、储存数据、比较最大值、求平均值

void Data_Proc(void)

{

unsigned char i;

if(Data_Slow_Down) return;

Data_Slow_Down = 1;

Read_Rtc(rtc);//读取时间

gmdz=Pcf8591_Adc(0x41);//读取光敏通道值

if((gmdz<30)&&(flag==0))//采集标志位为0,处于未采集状态,且光敏值较小,由明变暗

{

flag=1;//采集标志位设1,处于采集状态,3秒内无法再触发采集

cjTick=uwTick;//开始计时

wd=rd_temperature()/16;//读取当前温度

if((freq>=200)&&(freq<=2000))//频率有效,湿度数据有效

{

n++;//采集次数+1

cjsd[n]=(unsigned char)(80/1800.0*(freq-200)+10);//湿度换算并储存

cjwd[n]=wd;//储存温度

cjsj[0]=rtc[0];cjsj[1]=rtc[1];//储存触发时间

sjwx=0;//数据无效标志位设0

}

else//频率无效,湿度数据无效

sjwx=1;//数据无效标志位设1

}

if(uwTick-cjTick>3000)//超过3秒

flag=0;//采集标志位设0,处于未采集状态,可以进行下一次采集

for(i=1;i<=n;i++)

{

if(cjwd[i]>tmax)//比较出温度最大值

tmax=cjwd[i];

wd_sum+=cjwd[i];//求出温度数据总和

if(cjsd[i]>hmax)//比较出湿度最大值

hmax=cjsd[i];

sd_sum+=cjsd[i];//求出湿度数据总和

}

wdpj=1.0*wd_sum/n;//求出温度平均值

sdpj=1.0*sd_sum/n;//求出湿度平均值

wd_sum=0;sd_sum=0;//数据总和清零,否则影响下一次计算

}

4.数码管显示:无效字符、位不足补0、采集次数为0时要求位熄灭

void Seg_Proc(void)

{

unsigned char seg_string[10];//储存显示的字符

if(Seg_Slow_Down) return;

Seg_Slow_Down = 1;

if(flag==1)//触发采集进入温湿度界面

{

if(sjwx)//数据无效

sprintf(seg_string,"E %2d-AA",(unsigned int)wd);//显示暂存的当前温度和无效字符AA

else//数据有效

sprintf(seg_string,"E %2d-%2d",(unsigned int)cjwd[n],(unsigned int)cjsd[n]);//显示储存的数据

}

else//时间界面、回显界面、参数界面

{

if(jiemian==0)//时间界面

sprintf(seg_string,"%02d-%02d-%02d",(unsigned int)rtc[0],(unsigned int)rtc[1],(unsigned int)rtc[2]);//不足2位左侧补0

else if(jiemian==1)//回显界面

{

if(hxjm==0)//温度回显界面

{

if(n==0)//采集次数为0

sprintf(seg_string,"C ");//除标识符外其他位熄灭

else//采集次数不为0

sprintf(seg_string,"C %2d-%4.1f",(unsigned int)tmax,wdpj);

}

else if(hxjm==1)//湿度回显界面

{

if(n==0)//采集次数为0

sprintf(seg_string,"H ");//除标识符外其他位熄灭

else//采集次数不为0

sprintf(seg_string,"H %2d-%4.1f",(unsigned int)hmax,sdpj);

}

else//时间回显界面

{

if(n==0)//采集次数为0

sprintf(seg_string,"F%02d ",(unsigned int)n);//时、间隔、分位置熄灭,采集次数不足2位左侧补0

else//采集次数不为0

sprintf(seg_string,"F%02d%02d-%02d",(unsigned int)n,(unsigned int)cjsj[0],(unsigned int)cjsj[1]);//采集次数不足2位左侧补0

}

}

else//参数界面

sprintf(seg_string,"P %2d",(unsigned int)wdcs);

}

Seg_Tran(seg_string, seg_buf);

}

6.LED显示:点亮、熄灭、闪烁

void Led_Proc(void)

{

if(Led_Slow_Down) return;

Led_Slow_Down = 1;

if((jiemian==0)&&(flag==0))//时间界面,且未进入温湿度界面

uled|=0x01;

else//其他界面

uled&=~0x01;

if((jiemian==1)&&(flag==0))//回显界面,且未进入温湿度界面

uled|=0x02;

else//其他界面

uled&=~0x02;

if(flag)//温湿度界面

uled|=0x04;

else//其他界面

uled&=~0x04;

if(cjwd[n]>wdcs)//当前采集温度大于温度参数

uled^=0x08;//L4 0.1秒闪烁

else//不满足条件

uled&=~0x08;//L4熄灭

if(sjwx)//湿度数据无效

uled|=0x10;

else//下一次湿度数据有效

uled&=~0x10;

if(n>=2)//采集次数大于2时

{

if((cjwd[n]>cjwd[n-1])&&(cjsd[n]>cjsd[n-1]))//本次采集的温度、湿度相比上一次均升高

uled|=0x20;

else//不满足条件

uled&=~0x20;

}

else

uled&=~0x20;

}

7.中断服务函数

void tm1_isr() interrupt 3

{

static unsigned char pos;//位选变量

uwTick++;//按ms++

if(++Key_Slow_Down == 10) Key_Slow_Down = 0;

if(++Data_Slow_Down == 200) Data_Slow_Down = 0;

if(++Seg_Slow_Down == 200) Seg_Slow_Down = 0;

if(++Led_Slow_Down == 100) Led_Slow_Down = 0;

if((uwTick%1000) == 0)//每1s进入一次

{

freq = ((TH0<<8)|TL0);//计算出555信号频率

TH0 = 0;//重置计数高8位

TL0 = 0;//重置计数低8位

}

Seg_Disp(seg_buf, pos);//数码管位选函数

if(++pos == 8) pos = 0;

Led_Disp(uled);//LED显示函数

}

8.延时函数

void Delay750ms() //@12.000MHz

{

unsigned char i, j, k;

_nop_();

_nop_();

i = 35;

j = 51;

k = 182;

do

{

do

{

while (--k);

} while (--j);

} while (--i);

}

四、经验与感受 细节剖析(后续补充)

五、链接

1.第十四届蓝桥杯单片机省赛真题PDF

2.第十三届蓝桥杯嵌入式国赛真题(基于HAL库的巨简代码+超级详解)

3.第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

4.第十三届蓝桥杯嵌入式省赛第二场真题(基于HAL库的巨简代码+超级详解)

5.第十二届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: