锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

第十二届蓝桥杯单片机国赛试题与代码解析

时间:2023-10-10 02:07:02 s9电阻器定时器

??相信大家一直在寻找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百科大全!
          

相关文章