第十二届蓝桥杯单片机国赛试题与代码解析
时间:2023-10-10 02:07:02
??相信大家一直在寻找12届蓝桥杯单片机国赛的试题和答案。以下小系列将展示12届单片机试题和个人代码。
试题展示
设计说明
??此次的国赛,从模块上看,是五大基本模块:按键模块、数码管模块、LED模块、IIC模块、ds1302模块,另外,再加上一个小编不太熟悉的超声波模块,在这六个模块中,在这六个模块中写一些东西。不要说太多。详细设计请查看以下代码。
代码解析
main函数:
#include "config.h" extern unsigned char segbuff[],second; unsigned char key_num = 16;//按键值 unsigned char flag_L6;//LED的L6点亮的分别标识 unsigned char distan = 0;///记录红外测量的距离 unsigned char flag_S8 = 0;///触发模式 定时模式 模式切换表示 extern unsigned char flag_S4 ,flag_S5;//S4 S5按键 unsigned char time_count = 2,distance_count = 20;//时间参数 距离参数 unsigned char max_distance = 0,min_distance = 0;//记录测得距离的最大值 最小值 unsigned int ave_distance = 0;//平均值 unsigned char flag_L5 = 0;///记录实时测量的距离符合条件的次数 unsigned char light = 120;//记录测得的光照强度 unsigned char s;//记录上次的时间 秒 unsigned int count = 0;//记录中断次数 相当于定时时间 unsigned char VV = 0;///记录本次测距的电压值(0-255) void main(){
sysinit
(
)
;
//关闭外设
Timer1Init
(
)
;
//开启定时器1
Timer0Init
(
)
;
//开启定时器0
ds1302_init
(
0x20
,
0x20
,
0x00
)
;
//设置初试时间
while
(
1
)
{
key_num
=
scankbd
(
)
;
switch
(key_num
)
{
case
0
:
//S4
if
(
++flag_S4
==
2
) flag_S4
=
0
;
break
;
case
1
:
//S5
if
(
++flag_S5
==
3
) flag_S5
=
0
;
break
;
case
4
:
//S8
if
(
++flag_S8
==
3
) flag_S8
=
0
;
break
;
case
5
:
//S9
if
(flag_S5
%
2
==
0
&& flag_S4
==
1
)
{
//时间参数
if
(time_count
==
2
)
{
time_count
++
;
}
else
if
(time_count
==
9
)
{
time_count
=
2
;
}
else
{
time_count
+=
2
;
}
}
else
if
(
(flag_S5
%
2
==
1
&& flag_S4
==
1
)
)
{
//距离参数 distance_count
+=
10
;
if
(distance_count
==
90
) distance_count
=
10
;
}
break
;
}
if
(flag_S8
%
2
==
0
)
{
//定时模式 测距离
if
(s
!= second
)
{
distan
=
wave_recv
(
)
;
distance_compare
(
)
; s
= second
;
}
}
else
{
//触发模式 测距离
if
(count
%
50
==
0
)
{
light
=
adc_read
(
0x01
)
;
//读取光敏电阻
}
if
(light
<
130
)
{
//暗状态
if
(count
%
5
==
0
)
{
distan
=
wave_recv
(
)
;
distance_compare
(
)
;
} flag_L6
=
1
;
//LED6熄灭
}
else
{
//亮状态 flag_L6
=
0
;
//LED6点亮
}
}
if
(distan
<=
10
)
{
//DAC输出 图表第1段
dac_out
(
51.0
)
;
}
else
if
(distan
>=
80
)
{
//DAC输出 图表第3段
dac_out
(
255.0
)
;
}
else
{
//DAC输出 图表第2段 VV
= distan
*
4.0
/
70
*
51.0
;
dac_out
(VV
)
;
}
if
(distan
>distance_count
-
6
&& distan
<distance_count
+
6
)
{
//用于判断L5是否点亮 flag_L5
++
;
//本次测得距离符合条件,积累次数加1
}
else
{
flag_L5
=
0
;
//本次测得的距离不符合条件,积累次数直接变成0
}
S5_play
(
)
;
//数码管显示
}
}
void
time1
(
) interrupt
3
{
count
++
;
if
(count
%
2
==
0
)
{
segs
(
)
;
//数码管显示
led
(
)
;
//LED点亮
}
if
(count
%
2000
==
0
)
{
ds1302_read
(
)
;
//读取时间
}
}
config.h文件:
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include
#include "iic.h"
#include "ds1302.h"
#include "ultrasonic.h"
void sysinit();//关闭外设函数
void segs();//数码管显示函数
void led();//LED函数
unsigned char scankbd();//按键函数
void Timer1Init(void);//定时器函数
void S5_play();
void distance();
void data_paly();
void led();
void distance_compare();
#endif
config.c文件:
#include "config.h" #define kbd_io P3 #define kbd_maskrow 0x0f sbit L1 = P0^0; sbit L2 = P0^1; sbit L3 = P0^2; sbit L4 = P0^3; sbit L5 = P0^4; sbit L6 = P0^5; sbit realy = P0^4; sbit buzzer = P0^6; extern unsigned char flag_L5,flag_L6;//LED的L5 L6点亮的分别标识 extern unsigned char max_distance,min_distance;//记录测得距离的最大值 最小值 extern unsigned int ave_distance;//平均值 extern unsigned char distan;//记录红外测得的距离 extern unsigned char flag_S8;//触发模式 定时模式 模式切换表示 unsigned char flag_S4 = 0;//按下S4模式切换控制标志 unsigned char flag_S5 = 0;//按下S5切换控制标志 extern unsigned char time_count,distance_count;//时间参数 距离参数 extern unsigned char hour,minute,second;//时间的时 分 秒 unsigned char segbuff[] = { 10,10,10,10,10,10,10,10}; code unsigned char segtab[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff, 0xc0&0x7f,0xf9&0x7f,0xa4&0x7f,0xb0&0x7f,0x99&0x7f,0x92&0x7f,0x82&0x7f,0xf8&0x7f,0x80&0x7f,0x90&0x7f,0xbf,0xff, 0xc7,0xc6,0x8e,0x8c,0x89,0xfe,0xbf,0xf7};//L C F P H 最大值标志 平均值表示 最小值表示 void sysinit(){ //关闭外设函数 P2 = P2&0x1f|0x80;P0 = 0xff;P2 = P2&0x1f;//关闭LED灯 P2 = P2&0x1f|0xa0;realy = 0;buzzer = 0;P2 = P2&0x1f;//关闭
蜂鸣器与继电器 P2 = P2&0x1f|0xe0;P2 = 0xff;P2 = P2&0x1f;//关闭数码管的段选; P2 = P2&0x1f|0xc0;P2 = 0x00;P2 = P2&0x1f;//关闭数码管的位选 } void segs(){ //数码管显示函数 static unsigned char segaddr = 0; P2 = P2&0x1f|0xe0;P0 = 0xff;P2 = P2&0x1f;//段选消影 P2 = P2&0x1f|0xc0;P0 = 1<<segaddr;P2 = P2&0x1f;//位选 P2 = P2&0x1f|0xe0;P0 = segtab[segbuff[segaddr]];P2 = P2&0x1f;//段选 if(++segaddr == 8) segaddr = 0; } unsigned char scankbd(){ //按键函数 unsigned char key_num = 16; static unsigned char kbd_state = 0; unsigned char kbd_press; switch(kbd_state){ case 0: kbd_io = 0x0f;P42 =0;P44 = 0;kbd_press = kbd_io; if(kbd_press != kbd_maskrow){ kbd_state = 1; } break; case 1: kbd_press = kbd_io; if(kbd_press != kbd_maskrow){ if((kbd_io&0x08)==0) key_num = 0; if((kbd_io&0x04)==0) key_num = 1; if((kbd_io&0x02)==0) key_num = 2; if((kbd_io&0x01)==0) key_num = 3; kbd_io = 0xf0;P42 = 1;P44 = 1; if(P44 == 0) key_num += 0; if(P42 == 0) key_num += 4; if((kbd_io&0x20)==0) key_num += 8; if((kbd_io&0x10)==0) key_num += 12; kbd_state = 2; }else{ kbd_state = 0; } break; case 2: kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io; if(kbd_press == kbd_maskrow){ kbd_state = 0; } break; default: break; } return key_num; } void Timer1Init(void) //1毫秒@12.000MHz { AUXR &= 0xBF; //定时器时钟12T模式 TMOD &= 0x0F; //设置定时器模式 TL1 = 0x18; //设置定时初始值 TH1 = 0xFC; //设置定时初始值 TF1 = 0; //清除TF1标志 TR1 = 1; //定时器1开始计时 EA = 1; ET1 = 1; } void S5_play(){ if(flag_S5%3==0 && flag_S4==0){ //数据显示 时间显示 segbuff[0] = hour/16; segbuff[1] = hour%16; segbuff[2] = 10; segbuff[3] = minute/16; segbuff[4] = minute%16; segbuff[5] = 10; segbuff[6] = second/16; segbuff[7] = second%16; }else if(flag_S5%3==1 && flag_S4==0){ //数据显示 距离显示 distance(); }else if(flag_S5%3==2 && flag_S4==0){ //数据显示 数据记录显示 data_paly(); } if(flag_S5%2==0 && flag_S4==1){ //参数显示 时间参数 segbuff[0] = 27; segbuff[1] = 1; segbuff[2] = 11; segbuff[3] = 11; segbuff[4] = 11; segbuff[5] = 11; segbuff[6] = time_count/10; segbuff[7] = time_count%10; }else if(flag_S5%2==1 && flag_S4==1){ //参数显示 距离参数 segbuff[0] = 27; segbuff[1] = 2; segbuff[2] = 11; segbuff[3] = 11; segbuff[4] = 11; segbuff[5] = 11; segbuff[6] = distance_count/10; segbuff[7] = distance_count%10; } } //距离显示函数 void distance(){ if(flag_S8%2 == 0){ //定时器模式下 segbuff[0] = 24; segbuff[1] = 26;//F segbuff[2] = 11; segbuff[3] = 11; segbuff[4] = 11; if(distan>=100){ segbuff[5] = distan/100; }else{ segbuff[5] = 11; 元器件数据手册、IC替代型号,打造电子元器件IC百科大全!