第十四届蓝桥杯单片机国赛程序设计题

前言:感觉那一年的省赛选手看到这个题目后,会感叹比那年省赛难不了多少。

目录

  • 题目
  • 个人感受与理解
  • 底层驱动代码
    • IIC
    • onewire
  • 主程序核心代码
  • 展示视频:

题目

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

个人感受与理解

难度可以,对得起分值,但是没考串口。
今年大概率要考串口了吧。。。
其他就没什么好说的了,祝我自己国赛顺利

底层驱动代码

IIC

void DAC(unsigned char dat){
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
}

onewire

void showselect();
void delaysmg(unsigned char xms){
	while(xms--){
		Delay(1);
		showselect();
	}
}

void cewen(){
	unsigned char LSB,MSB;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	if(ce){
		ce = 0;
		delaysmg(100);
	}
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	
	temp = ((MSB << 8)| LSB) * 0.625;
}

主程序核心代码

#include <STC15F2K60S2.H>
#include "delay.h"
#include "inithc138.h"
#include "intrins.h"
#include "onewire.h"
#include "iic.h"

#define de 5

code unsigned char Seg_Table[17] = 
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xbf
};
unsigned char show = 0;//显示模式切换
bit canshu = 0;//参数界面切换
unsigned char gongchang = 0;//工厂模式切换
unsigned int time = 0;
unsigned long distance = 0;//距离值
bit danwei = 0;//测距单位
unsigned int shengsu = 340;//声速
char disjiao = 0;//距离校准值
long disshow = 0;//校准之后的距离
bit ce = 1;
unsigned int temp = 0;//温度测量值
char discan = 40;//距离参数
char tempcan = 30;//温度参数
unsigned char DACxiaxian = 10;//DAC下限
bit keystat = 0;//长按
unsigned char keycount = 0;//长按两秒
double DACzhi = 0;//DAC输出值
unsigned char ledstat = 0;//LED灯状态
bit flag = 0;//闪烁标志位
unsigned char count = 0;//闪烁计时
bit jilu = 0;
int disrecord = 0;
bit s1 = 0;
bit s2 = 0;
//*****************************************超声波
sbit TX = P1^0;
sbit RX = P1^1;
void Delay12us(void)	//@12.000MHz
{
	unsigned char data i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}

void initpca(){
	CMOD = 0x08;
	CCON = 0x00;
	EA = 1;
}

void fangbo(){
	unsigned char i;
	for(i = 0;i < 8;i++){
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}

void ceju(){
	CL = 0x00;				
	CH = 0x00;				
	CF = 0;				
	CR = 0;
	
	fangbo();
	CR = 1;
	while((RX == 1) && (CH < 0xD5));
	CR = 0;
	
	if(RX == 0){
		RX = 1;
		time = (CH << 8) | CL;
		distance = (time * 0.017*(shengsu / 340.000)) / 12.000;
		disshow = distance + disjiao;
	}
}
//*****************************************
//*****************************************测温模块
void showselect();
void delaysmg(unsigned char xms){
	while(xms--){
		Delay(1);
		showselect();
	}
}

void cewen(){
	unsigned char LSB,MSB;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	if(ce){
		ce = 0;
		delaysmg(100);
	}
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	
	temp = ((MSB << 8)| LSB) * 0.625;
}
//*****************************************
//*****************************************
void cejucm(){//测距单位为厘米
	if(disshow < 0){
		showsmg(8,Seg_Table[(~(disshow - 1)) % 10]);
		if(disshow > -9){
			showsmg(7,Seg_Table[16]);
		}
		if(disshow < -9){
			showsmg(6,Seg_Table[16]);
			showsmg(7,Seg_Table[(~(disshow - 1)) / 10 % 10]);
		}
	}else{
		showsmg(8,Seg_Table[disshow % 10]);
		if(disshow > 9){
			showsmg(7,Seg_Table[disshow / 10 % 10]);
		}
		if(disshow > 99){
			showsmg(6,Seg_Table[disshow / 100 % 10]);
		}
	}
}

void cejum(){//测距单位为米
	if(disshow < 0){
		showsmg(8,Seg_Table[(~(disshow - 1)) % 10]);
		showsmg(5,Seg_Table[16]);
		showsmg(6,Seg_Table[(~(disshow - 1)) / 100 % 10] & 0x7f);
		showsmg(7,Seg_Table[(~(disshow - 1)) / 10 % 10]);
		showsmg(8,Seg_Table[(~(disshow - 1)) % 10]);
	}else{
		showsmg(6,Seg_Table[disshow / 100 % 10] & 0x7f);
		showsmg(7,Seg_Table[disshow / 10 % 10]);
		showsmg(8,Seg_Table[disshow % 10]);
	}
}

void cejujiemian(){//测距界面
	showsmg(1,Seg_Table[temp / 100]);
	showsmg(2,Seg_Table[temp / 10 % 10] & 0x7f);
	showsmg(3,Seg_Table[temp % 10]);
	showsmg(4,Seg_Table[16]);
	if(danwei){
		cejum();
	}else{
		cejucm();
	}
}

void canshujiemian(){//参数界面
	showsmg(1,0x8c);
	if(canshu == 0){
		showsmg(2,Seg_Table[1]);
		showsmg(7,Seg_Table[discan / 10]);
		showsmg(8,Seg_Table[discan % 10]);
	}else{
		showsmg(2,Seg_Table[2]);
		showsmg(7,Seg_Table[tempcan / 10]);
		showsmg(8,Seg_Table[tempcan % 10]);
	}
}

void gongchangf1(){//工厂模式F1
	showsmg(2,Seg_Table[1]);
	if(disjiao >= 0){
		showsmg(8,Seg_Table[disjiao % 10]);
		if(disjiao > 9){
			showsmg(7,Seg_Table[disjiao / 10 % 10]);
		}
	}else{
		showsmg(8,Seg_Table[(~(disjiao - 1)) % 10]);
		if(disjiao> -9){
			showsmg(7,Seg_Table[16]);
		}
		if(disjiao < -9){
			showsmg(6,Seg_Table[16]);
			showsmg(7,Seg_Table[(~(disjiao - 1))  / 10 % 10]);
		}
	}
}

void gongchangf2(){//工厂模式F2
	showsmg(2,Seg_Table[2]);
	showsmg(8,Seg_Table[shengsu % 10]);
	if(shengsu > 9){
		showsmg(7,Seg_Table[shengsu /10 % 10]);
	}
	if(shengsu > 99){
		showsmg(6,Seg_Table[shengsu /100 % 10]);
	}
	if(shengsu > 999){
		showsmg(5,Seg_Table[shengsu /1000 % 10]);
	}
}

void gongchangf3(){//工厂模式F3
	showsmg(2,Seg_Table[3]);
	showsmg(7,Seg_Table[DACxiaxian / 10] & 0x7f);
	showsmg(8,Seg_Table[DACxiaxian % 10]);
}

void gongchangmoshi(){//工厂模式
	showsmg(1,Seg_Table[15]);
	switch(gongchang){
		case 0:gongchangf1();break;
		case 1:gongchangf2();break;
		case 2:gongchangf3();break;
	}
}
//*****************************************
//*****************************************
void showselect(){
	switch(show){
		case 0:cejujiemian();break;
		case 1:canshujiemian();break;
		case 2:gongchangmoshi();break;
	}
}
//*****************************************长短按检测
void Timer0_Isr(void) interrupt 1
{
	count++;
	if(count == 120){
		count = 0;
		if(jilu){
			disrecord = disshow;
			jilu = 0;
		}
	}
	if(count % 2 == 0){
		flag = ~flag;
	}
	if(keystat){
		keycount++;
	}
}

void Timer0_Init(void)		//50毫秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0xB0;				//设置定时初始值
	TH0 = 0x3C;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
	EA = 1;
}
//*****************************************
//*****************************************DAC
void DACshuchu(){
	if(disshow <= 10){
		DACzhi = DACxiaxian / 10.00 * 51;
	}else if(disshow >= 90){
		DACzhi = 255;
	}else{
		DACzhi = (((255 - (DACxiaxian*5.100)) / 80.000) * (disrecord - 90.000) +255.000);
	}
	DAC(DACzhi);
	Delay(1);
}
//*****************************************
//*****************************************LED灯与继电器
void LED(){
	if(show == 0){
		if(disshow < 255){
			ledstat = ~disshow;
		}
		if(disshow >= 255){
			ledstat = 0x00;
		}
		outputp0(4,ledstat);
	}
	if(show == 1){
		ledstat = ~0x80;
		outputp0(4,ledstat);
	}
	if(show == 2){
		if(flag){
			ledstat = 0xfe;
		}else{
			ledstat = 0xff;
		}
		outputp0(4,ledstat);
	}
}
void relay(){
	if((disshow <= (discan + 5)) && (disshow > discan - 5)){
		s1 = 1;
	}else{
		s1 = 0;
	}
	if((temp / 10) < tempcan){
		s2 = 1;
	}else{
		s2 = 0;
	}
	
	if((s1 == 1) && (s2 == 1)){
		outputp0(5,0x10);
	}else{
		outputp0(5,0x00);
	}
}
//*****************************************
//*****************************************按键扫描
void scankey(){
	P33 = 1;P32 = 1;P44 = 1;P42 = 0;
	if(P33 == 0){//S12
		Delay(de);
		while(P33 == 0){
			showselect();
			LED();
			while(P32 == 0){
				showselect();
				LED();
				keystat = 1;
			}
			keystat = 0;
		}
		keystat = 0;
		if(show == 0){
			jilu = 1;
		}
		if(show == 1){//参数界面
			if(canshu == 0){//距离参数值
				discan += 10;
				if(discan > 90){discan = 90;}
			}
			if(canshu == 1){//温度参数值
				tempcan++;
				if(tempcan > 80){tempcan = 80;}
			}
		}
		if(show == 2){//工厂模式
			if(gongchang == 0){//校准值设置
				disjiao += 5;
				if(disjiao > 90){disjiao = 90;}
			}
			if(gongchang == 1){//介质设置
				shengsu += 10;
				if(shengsu > 9990){shengsu = 9990;}
			}
			if(gongchang == 2){
				DACxiaxian++;
				if(DACxiaxian > 20){DACxiaxian = 20;}
			}
		}
	}
	if(P32 == 0){//S13
		Delay(de);
		while(P32 == 0){
			showselect();
			LED();
			while(P33 == 0){
				showselect();
				LED();
				keystat = 1;
			}
			keystat = 0;
		}
		keystat = 0;
		if(show == 1){//参数界面
			if(canshu == 0){//距离参数值
				discan -= 10;
				if(discan < 0){discan = 0;}
			}
			if(canshu == 1){//温度参数值
				tempcan--;
				if(tempcan < 0){tempcan = 0;}
			}
		}
		if(show == 2){//工厂模式
			if(gongchang == 0){//校准值设置
				disjiao -= 5;
				if(disjiao < -90){disjiao = -90;}
			}
			if(gongchang == 1){//介质设置
				shengsu -= 10;
				if(shengsu < 10){shengsu = 10;}
			}
			if(gongchang == 2){//DAC输出下限
				DACxiaxian--;
				if(DACxiaxian < 1){DACxiaxian = 1;}
			}
		}
	}
	if(keycount >= 40){
		discan = 40;tempcan = 30;
		disjiao = 0;shengsu = 340;
		DACxiaxian = 0;show = 0;canshu = 0;gongchang = 0;
		delaysmg(10);
	}
	keycount = 0;
	P33 = 1;P32 = 1;P44 = 0;P42 = 1;
	if(P33 == 0){//S4
		Delay(de);while(P33 == 0){LED();showselect();}
		show++;danwei = 0;gongchang = 0;canshu = 0;
		show %= 3;
	}
	if(P32 == 0){//S5
		Delay(de);while(P32 == 0){LED();showselect();}
		if(show == 0){
			danwei = ~danwei;
		}
		if(show == 1){
			canshu = ~canshu;
		}
		if(show == 2){
			gongchang++;
			gongchang %= 3;
		}
	}
}
//*****************************************
//*****************************************
void main(){
	initpca();
	initsys();
	ceju();
	cewen();
	LED();
	Timer0_Init();
	while(1){
		relay();
		ceju();
		showselect();
		cewen();
		if(jilu == 0){
			scankey();
		}
		showselect();
		DACshuchu();
		LED();
	}
}

展示视频:

DAC不太好拍,有意者可以自己烧录试试
但是玛德4T,明明题目要求只保留最后一个数据,但是你DAC输出为什么会变啊???

G014

在这里插入图片描述

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 蓝桥杯单片机国赛历年真加实训指导书(电子类).rar是一份非常有价值的资源,其包含了历年来蓝桥杯单片机国赛的真,同时还提供了详细的实训指导书,对于单片机学习者来说是非常有帮助的。其中的真可以帮助学生了解比赛的难度和方向,同时也可以帮助他们提升编程能力和解决问的能力。而实训指导书则提供了实践操作的详细教程,可以帮助学生更好地掌握单片机的使用技巧和实际应用。 通过研究历年真,学生可以了解到蓝桥杯单片机国赛的出方向,从而更好地准备比赛。同时,也可以整理出常见的考点和难点,帮助自己在学习过程中更加有针对性和效率。另外,实训指导书的详细操作步骤,可以帮助学生更好地学习、实践和巩固知识,提升实际应用的能力。 总之,蓝桥杯单片机国赛历年真加实训指导书(电子类).rar是一份非常有价值的资源,对于单片机学习者来说是一份难得的学习资料。希望广大学生们能够好好利用这份资源,不断探索和学习,提升自己的单片机技能和应用能力,为将来的学习和工作打下坚实的基础。 ### 回答2: 蓝桥杯单片机国赛历年真加实训指导书(电子类).rar是一份非常有价值的单片机学习资源,其中包含了历年蓝桥杯单片机国赛以及相应的解析,能够帮助学生更好地了解比赛型和解思路。同时,该资源还提供了详细的实训指导书,让学生能够通过实践掌握单片机编程技巧和应用实践,提高自己的实际操作能力和编程水平。 学习单片机是电子工程和通信工程等专业的基础课程,也是学生实践能力培养的必修课程。而该资源所包含的历年真和实训指导书,则是学生在单片机课程学习中非常有用的资料,它们可以帮助学生更好地掌握课程知识,提高自己的解能力和实践能力。 需要注意的是,这些真和实训指导书是用于学习和训练的,不应用于比赛作弊等违规行为。同时,在学习的过程中,学生应始终保持诚信,正确参与学习和比赛,做到遵守规则,树立诚信意识,培养正确的学习态度和价值观。 ### 回答3: 蓝桥杯单片机国赛历年真加实训指导书(电子类).rar是一份非常有价值的资料,对于有志于学习单片机的同学们来说,具有非常大的帮助作用。这份资料涵盖了历年的蓝桥杯单片机国赛,可以帮助同学们更好地了解比赛形式与型,并掌握解技巧和思路,从而更好的备战比赛。 此外,这份资料还包括了详细的实训指导书,能够帮助同学们更好地掌握单片机的开发实战技术,提高自己的实际操作能力。指导书中详细介绍了各种常用的电子元器件的使用方法,如LED、LCD等,并给出了大量的例子和实验来帮助学生更好地理解和掌握各个知识点。 总之,这份资料不仅有助于同学们备战蓝桥杯单片机国赛,同时也是学习和掌握单片机开发的绝佳资料。希望同学们能够好好利用这份资料,努力学习和实践,取得更好的成绩和技术能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值