【蓝桥杯单片机第十三届国赛真题】

【蓝桥杯单片机第十三届国赛真题】

文章目录

  • 【蓝桥杯单片机第十三届国赛真题】
  • 前言
  • 一、真题
  • 二、源码


前言

在这里插入图片描述

有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^

下面为蓝桥杯单片机第十三届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,有需完整工程的小伙伴可自行下载。

在这里插入图片描述

注意

这届国赛中使用到的资源比较多,频率,超声波都有同时使用到,一般来说都是用定时器0来进行超声波测距和频率的发生,很显然这次不行,在该工程中超声波测距使用的是PCA方式,频率还是使用定时器0,定时器2则用于数码管刷新以及其他数据周期刷新处理。定时器1也可用作超声波测距,但该题目中还有pwm输出,虽然定时器1我用作了pwm输出。具体定时器的分配可根据题目功能需求以及个人习惯来进行合理的分配使用即可。

1.PCA测距方式

/*==========================PCA方式进行超声波测距=========================*/
sbit TX = P1^0;
sbit RX = P1^1;
uint time_us = 0;
bit flag_over = 0;void PCA_Init(void)
{CCON = 0;CMOD = 0x01;CCAPM0 = 0x11;
}void PAC_Server() interrupt 7
{CR = 0;if(CCF0){CCF0 = 0;time_us = (uint)(CCAP0H << 8)|CCAP0L;flag_over = 0;}else if(CF){CF = 0;flag_over = 1;}
}void Delay12us()		//@12.000MHz
{unsigned char i;_nop_();_nop_();i = 33;while (--i);
}void Send_Wave(void)
{uchar i = 0;for(i = 0;i<8;i++){TX = 0;Delay12us();TX = 1;Delay12us();}
}uint Get_Distance(void)
{uint dis = 0;Send_Wave();CH = CL = 0;CCF0 = CF = 0;CR = 1;if(flag_over){dis = 999;}else{dis = time_us * 0.017 + 0.5;}return dis;
}

2.定时器1pwm输出

根据题目要求输出1khz 也及时1000us,这里定时中断设置为200us,整个周期分为5分,当所测频率大于频率参数时输出80%占空比,也就是4份,否则输出20%占空比也就是1份。

void Timer1Init(void)		//200微秒@12.000MHz
{AUXR |= 0x40;		//定时器时钟1T模式TMOD &= 0x0F;		//设置定时器模式TL1 = 0xA0;		//设置定时初始值TH1 = 0xF6;		//设置定时初始值TF1 = 0;		//清除TF1标志TR1 = 1;		//定时器1开始计时ET1 = 1;EA = 1;
}
//定时器1中断用于产生PWM输出 200us中一次中断
void Timer1_Server() interrupt 3
{static uchar pwm_count = 0;pwm_count++;if(pwm_count > 0 && pwm_count <= pwm_duty_value){motor = 1; }else if(pwm_count > pwm_duty_value){motor = 0;}else if(pwm_count == 5)  //一个周期{pwm_count = 0;}
}

工程链接

链接: https://pan.baidu.com/s/1bDhoTTWmTVtBvJlEvwI18g?pwd=87ih 提取码: 87ih 复制这段内容后打开百度网盘手机App,操作更方便哦 
--来自百度网盘超级会员v5的分享

一、真题

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、源码

在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*=========================第十三届国赛===========================
@Author:小殷同学
@Date:2023.5.31
==================================================================*/
#include "public.h"
#include "iic.h"
/*===========================下面为变量和宏定义====================*/
//数码管段码(0~9、shut-off、"-"、)
code uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x8e,0x89,0x88,0x8c};//初始化,使所有数码管熄灭(必须是9个元素)uchar relay = 0;                                                       //继电器
uchar motor = 0;                                                       //电机
uchar pwm_duty_value = 0;                                              //电机PWM占空比
uchar L[9];                                                           //LED
xdata uchar smg_bit[11] = {10,10,10,10,10,10,10,10,10};               //数码管位
xdata uint feq_value = 0;                                             //频率值 hz
xdata uint feq_value_khz = 0;                                         //频率值 khz
uchar relay_count = 0;                                                //继电器开关次数
uint param_feq_value_khz = 9*10;                                      //频率参数 khz
uchar param_humi_value = 40;                                           //湿度参数
uchar param_dis_value = 6;                                            //距离参数
xdata uint dis_value_cm = 0;                                          //距离值 cm
xdata uint dis_value_m = 0;                                          //距离值 m
uint humi_value = 0;                                                 //湿度值
uchar data_interface = 1;                                             //数据界面
uchar param_interface = 1;                                            //参数界面
uchar f_index = 1;                                                    //频率索引
uchar dis_index = 1;                                                  //距离索引
uint adc_value = 0;                                                  //adc值
bit l1_flash = 0,l2_flash = 0,l3_flash = 0;                          //L1 L2 L3闪烁标志位
uchar adc_feq = 0;                                                    //adc 采集刷新频率
uchar key_feq = 0;                                                    //按键刷新频率
uchar led_feq = 0;                                                    //LED刷新频率
uchar dis_feq = 0;                                                    //超声波刷新频率/*===========================下面为函数相关声明=====================*/
void data_task(void);
void logical_task(void);
void smg_task(void);
void key_task(void);
void Init_System(void);
/*============================下面为函数实现=========================*/void data_task(void)
{if(T2H < 0xd9){if(adc_feq > 120){adc_feq = 1;adc_value = Raed_ADC(0x43);adc_value = adc_value * (5.0/255)*100;}if(led_feq > 50){led_feq = 1;Control_IO(0x80,~(L[1] << 0|L[2] << 1 |L[3] <<2|L[4] << 3|L[5] << 4|L[6] << 5  | L[7]<<6|L[8] << 7));Control_IO(0xa0,relay << 4 | motor << 5);}//测距if(dis_feq > 150){dis_feq = 1;dis_value_cm = Get_Distance_PCA();dis_value_m =  dis_value_cm;}}
}void logical_task(void)
{static old_flag = 0,flag = 0;//下面为湿度值逻辑计算 y = 20xif(adc_value < 500){humi_value = (20 * adc_value)/100.0;}else{humi_value = 99;}//下面为DAC输出if(humi_value >= 0 && humi_value < 16){Write_DAC(51);     //1V}else if(humi_value >=16 && humi_value <= 80){//y = 1/16*xWrite_DAC(51 * (1/16.0 * humi_value));  }else{Write_DAC(255);   //5V}//下面为LED逻辑判断L[1] = (l1_flash == 1 && data_interface == 1)?(1):(0);L[2] = (l2_flash == 1 && data_interface == 2)?(1):(0);L[3] = (l3_flash == 1 && data_interface == 3)?(1):(0); L[4] = (feq_value > param_feq_value_khz*100 || feq_value_khz > param_feq_value_khz)?(10):(0);L[5] = (humi_value > param_humi_value)?(1):(0);L[6] = (dis_value_cm > param_dis_value * 10)?(1):(0);L[7] = 0;L[8] = 0;//下面为继电器逻辑判断if(dis_value_cm > param_dis_value * 10){flag = 1;old_flag = flag;}else{flag = 0;}relay = (flag == 1)?(1):(0);if(old_flag == 1 && flag == 0)  //开关一次{relay_count++;old_flag = 0;Write_AT24C02(0x00,relay_count);Delay5ms();}//下面为脉冲输出功能if(feq_value > param_feq_value_khz*100){	//输出 1khz 80%  1000us 200us一次中断pwm_duty_value = 4;}else{//输出 1khz 20%pwm_duty_value = 1;}
}void smg_task(void)
{//频率界面if(data_interface == 1){//Hzif(f_index == 1){smg_bit[1] = 12; //F 0111 0001 0x8esmg_bit[2] = 10;smg_bit[3] = (feq_value > 99999)?(feq_value/100000):(10);smg_bit[4] = (feq_value > 9999)?(feq_value/10000%10):(10);smg_bit[5] = (feq_value > 999)?(feq_value/1000%10):(10);smg_bit[6] = (feq_value > 99)?(feq_value/100%10):(10);smg_bit[7] = (feq_value > 9)?(feq_value/10%10):(10);smg_bit[8] = feq_value%10;}//khxelse if(f_index == 2){	smg_bit[1] = 12; //F 0111 0001 0x8esmg_bit[2] = 10;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = (feq_value_khz > 99)?(feq_value_khz/100):(10);smg_bit[7] = (feq_value_khz > 9)?(feq_value_khz/10%10):(0);smg_bit[8] = feq_value_khz%10;	}}//湿度界面else if(data_interface == 2){smg_bit[1] = 13; //H 1001 0001 0x89smg_bit[2] = 10;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = 10;smg_bit[7] = humi_value/10;smg_bit[8] = humi_value%10;	}//测距界面else if(data_interface == 3){//cm 单位if(dis_index == 1){smg_bit[1] = 14; //R 0001 0001 0x88smg_bit[2] = 10;smg_bit[3] = relay_count/10;smg_bit[4] = relay_count%10;smg_bit[5] = 10;smg_bit[6] = (dis_value_cm > 99)?(dis_value_cm/100):(10);smg_bit[7] = (dis_value_cm > 9)?(dis_value_cm/10%10):(10);smg_bit[8] = dis_value_cm%10;	}//m 单位else if(dis_index == 2){smg_bit[1] = 14; //R 0001 0001 0x88smg_bit[2] = 10;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = (dis_value_m > 99)?(dis_value_m/100):(0);smg_bit[7] = (dis_value_m > 9)?(dis_value_m/10%10):(10);smg_bit[8] = dis_value_m%10;	}}//参数界面else if(data_interface == 4){//频率参数if(param_interface == 1){smg_bit[1] = 15; //P 0011 0001 0x8csmg_bit[2] = param_interface;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = (param_feq_value_khz > 99)?(param_feq_value_khz/100):(10);smg_bit[7] = (param_feq_value_khz > 9)?(param_feq_value_khz/10%10):(0);smg_bit[8] = param_feq_value_khz%10;	}//湿度参数else if(param_interface == 2){smg_bit[1] = 15; //P 0011 0001 0x8csmg_bit[2] = param_interface;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = 10;smg_bit[7] = param_humi_value/10;smg_bit[8] = param_humi_value%10;	}//距离参数else if(param_interface == 3){smg_bit[1] = 15; //P 0011 0001 0x8csmg_bit[2] = param_interface;smg_bit[3] = 10;smg_bit[4] = 10;smg_bit[5] = 10;smg_bit[6] = (param_dis_value > 99)?(param_dis_value/100):(10);smg_bit[7] = (param_dis_value > 9)?(param_dis_value/10%10):(0);smg_bit[8] = param_dis_value%10;	}}	
}void key_task(void)
{uchar key_value = 0;if(key_feq >20){key_feq = 1;key_value = Read_Key();}switch(key_value){//界面切换 频率、湿度、测距、参数case 4:if(++data_interface > 4){data_interface = 1;}break;//参数切换 频率、湿度、距离case 5:if(data_interface == 4){if(++param_interface > 3){param_interface = 1;}}break;//参数加 特定界面下case 6:if(data_interface == 4){switch(param_interface){//频率加 0.5khz  范围 1-12khz 10-120case 1:if(param_feq_value_khz < 120) //扩大了10倍方便显示{param_feq_value_khz += 5;}else{param_feq_value_khz = 10;}break;//湿度加 10   范围10-60case 2:if(param_humi_value < 60){param_humi_value += 10;}else{param_humi_value = 10;}break;//距离加 0.1m 范围0.1-1.2m   1-12case 3:if(param_dis_value < 12)  //扩大10倍方便显示和计算{param_dis_value += 1;}else{param_dis_value = 1;}break;}}//在距离界面下 进行cm 和m的切换if(data_interface == 3){if(++dis_index > 2){dis_index = 1;}}break;//参数减 特定界面下case 7:if(data_interface == 4){switch(param_interface){//频率加 0.5khz  范围 1-12khzcase 1:if(param_feq_value_khz > 1) //扩大了10倍方便显示{param_feq_value_khz -= 5;}else{param_feq_value_khz = 120;}break;//湿度加 10   范围10-60case 2:if(param_humi_value > 10){param_humi_value -= 10;}else{param_humi_value = 60;}break;//距离加 0.1m 范围0.1-1.2mcase 3:if(param_dis_value > 1)  //扩大10倍方便显示和计算{param_dis_value -= 1;}else{param_dis_value = 12;}break;}}//在频率界面下 进行hz 和khz显示切换if(data_interface == 1){if(++f_index > 2){f_index = 1;}}break;default:break;}}
void Init_System(void)
{Control_IO(0x80,0xff);Control_IO(0xa0,0x00);Control_IO(0xc0,0x00);Timer0Init();PCA_Init();Timer1Init();Timer2Init();relay_count = Read_AT24C02(0x00);Delay5ms();
}void main(void)
{Init_System();while(1){data_task();logical_task();smg_task();key_task();}
}/*=============================下面为中断处理=========================*/
void Timer2_Server() interrupt 12
{static uchar dsp_smg = 1;static uint feq_count = 0;static uint l1_t = 0,l2_t = 0,l3_t = 0;if(++feq_count == 500){feq_count = 0;TR0 = 0;feq_value =(((uint)TH0 << 8)|TL0) * 2;feq_value_khz = feq_value/1000.0*10; //保留一位小数TH0 = TL0 = 0;TR0 = 1;}Control_IO(0xc0,0x00);if((data_interface == 1 && f_index == 2 && dsp_smg == 7) || (data_interface == 3 && dis_index == 2 && dsp_smg == 6) || (data_interface == 4 && param_interface == 1 && dsp_smg == 7)|| (data_interface == 4 && param_interface == 3 && dsp_smg == 7)){Control_IO(0xe0,smg_data[smg_bit[dsp_smg]] & 0x7f);}else{Control_IO(0xe0,smg_data[smg_bit[dsp_smg]]);}Control_IO(0xc0,1 << (dsp_smg - 1)); if(++dsp_smg > 8){dsp_smg = 1;}//频率界面if(data_interface == 1)  {if(l1_t++ == 100)  //0.1 {l1_t = 0;     l1_flash = ~l1_flash;}}//湿度界面if(data_interface == 2){if(l2_t++ == 100) //0.1{l2_t = 0;l2_flash = ~l2_flash;}}//距离界面if(data_interface == 3){if(l3_t++ == 100) //0.1{l3_t = 0;l3_flash = ~l3_flash;}}//下面为数据刷新频率key_feq++;adc_feq++;led_feq++;dis_feq++;
}//定时器1中断用于产生PWM输出 200us中一次中断
void Timer1_Server() interrupt 3
{static uchar pwm_count = 0;pwm_count++;if(pwm_count > 0 && pwm_count <= pwm_duty_value){motor = 1; }else if(pwm_count > pwm_duty_value){motor = 0;}else if(pwm_count == 5)  //一个周期{pwm_count = 0;}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部