蓝桥杯单片机第十四届省赛程序题

前言:省赛之前第一次把全部模块学完后以后第一次挑战的真题就是第十四届的省赛题,当时我的代码习惯和风格并不好,就把我的程序整出了很多bug(在资源里有我之前写的两版,均多多少少有些bug,第一次做全崩了,第二次有bug,那个14省是最新的)。现在我做过的题多了,代码风格有所改善。我选择再做一次第十四届的省赛题,因为我感觉这种糅合了许多模块和别样触发方式的题目很值得一刷再刷,可以练练自己的编程速度和改进自己的代码风格。

题目

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

个人理解与感受

首先这道题目把三个底层驱动文件都用上了,这在之前的省赛以及第十五届省赛都是没有的,乃至之前的国赛将全部底层驱动文件都用上的也少见。但从这一点可见其难度,这就能打退很多在省赛之前没把所有模块学会的选手。还有光敏触发跳转页面,以及数据有无效的判断,这些如果没有经过一定的练习并形成比较好的代码风格都是容易出问题。
在获取数据方面,我是选择实时获取数据,然后在触发之后用一个新数据(比如后面将会出现的tempcurrent)来获取触发时刻的温度、时间、湿度(频率)。在我的前两次编写中是使用触发后再获取数据。
温度方面,我尝试了只在初始化的时候进行延时读取,后续把不用延时,发现这样的温度读取也更稳定,也不容易对其他数据的读取造成大的影响。
频率转湿度方面,我将湿度直接的值放大了100倍,这样更加精确。
这是我在4T官网进行的测评(我的板子用的是S12 S13,上传用的就是题目要求的S8 S9)它对实时时钟的上电没有明确说明,导致我丢掉这一分。
还有我明明都再回显界面有显示啊,什么垃圾测评啊啊啊啊啊啊啊
还好最后分数还是比较可观,毕竟也是走过一轮省赛的人了。
在这里插入图片描述

垃圾4T测评

底层驱动代码

全部都用了,但每个都是浅尝辄止

IIC

unsigned char guangmin(){
	unsigned char ret;
	
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	ret = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
	return ret;
}

DS18B20

void cewen(){
	unsigned char LSB,MSB;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	if(ce){//这里的意思是测完第一次后就不再延时了
		delaysmg(100);
		ce = 0;
	}
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	
	temp = (MSB << 8) | LSB;
	temp = temp * 0.0625;
}

DS1302实时时钟

void ds1302config(){
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i = 0;i < 3;i++){
		Write_Ds1302_Byte(ds1302writeaddr[i],rtctime[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}

void ds1302read(){
	unsigned char i;
	for(i = 0;i < 3;i++){
		rtctime[i] = Read_Ds1302_Byte(ds1302readaddr[i]);
	}
}

主程序代码

#include <STC15F2K60S2.H>
#include "delay.h"
#include "inithc138.h"
#include "ds1302.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 ds1302writeaddr[3] = {0x80,0x82,0x84};
unsigned char ds1302readaddr[3] = {0x81,0x83,0x85};
unsigned char rtctime[3] = {0x30,0x50,0x10};
unsigned char show = 0;//显示功能切换
unsigned char showlast = 0;//记录跳转前的显示界面
unsigned char huixian = 0;//回显模式切换
unsigned int tempmax = 0;//最大温度
unsigned long tempall = 0;//全部温度加起来
unsigned int tempavr = 0;//平均温度
unsigned int wetmax = 0;//最大湿度
unsigned long wetall = 0;//全部湿度加起来
unsigned int wetavr = 0;//平均湿度
unsigned char trigger = 0;//触发次数
unsigned char trigtime[2] = {0x00,0x00};
unsigned int temp = 0;//温度
unsigned int wet;
char tempcanshu = 30;//温度参数
bit ce = 1;//测温标志位
unsigned int hz_count = 0;
unsigned char count = 0;
unsigned int tmp = 0;//频率
bit youxiao = 0;//有效为1,无效为0
bit youxiao2 = 1;
bit keystat = 0;//长短按检测
unsigned char key_count = 0;//长按数秒
unsigned char light = 0;//光照强度
bit caiji = 0;//采集触发
unsigned char xianshishuju = 0;//显示数据三秒
unsigned char ledstat = 0xff;//LED状态
unsigned int tempcurrent,wetcurrent,tmpcurrent;
bit flag = 0;//闪烁标志位
bit tempda = 0;//温度是不是比之前的大
bit wetda = 0;//湿度是不是比之前的大
//************************************DS1302读写
void ds1302config(){
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i = 0;i < 3;i++){
		Write_Ds1302_Byte(ds1302writeaddr[i],rtctime[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}

void ds1302read(){
	unsigned char i;
	for(i = 0;i < 3;i++){
		rtctime[i] = Read_Ds1302_Byte(ds1302readaddr[i]);
	}
}
//************************************
//************************************温度测量
void showselect();
void delaysmg(unsigned int xms){
	while(xms--){
		Delay(1);
		showselect();
		//scankey();
	}
}

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

//************************************
//************************************湿度测量
void Timer0_Isr(void) interrupt 1
{
	hz_count++;
}

void Timer1_Isr(void) interrupt 3
{
	count++;
	if(count == 20){
		tmp = hz_count;
		hz_count = 0;
		count = 0;
	}
	
	if(keystat){
		key_count++;
	}
	
	if(caiji){
		xianshishuju++;
	}
	if(xianshishuju == 60){
		show = showlast;
		caiji = 0;
		xianshishuju = 0;
	}
	if((count % 2) == 0){
		flag = ~flag;
	}
}

void Timer_Init(void)		//50毫秒@12.000MHz
{
	AUXR &= 0xBF;			//定时器时钟12T模式
	TMOD = 0x07;			//设置定时器模式
	//数数
	TL0 = 0xFF;				//设置定时初始值
	TH0 = 0xFF;				//设置定时初始值
	TF0 = 0;				//清除TF1标志
	TR0 = 1;				//定时器1开始计时
	ET0 = 1;				//使能定时器1中断
	//读秒
	TL1 = 0xB0;				//设置定时初始值
	TH1 = 0x3C;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	ET1 = 1;				//使能定时器1中断
	EA = 1;
}

void pinlvzhuanhuashidu(){//频率转换成湿度
	if((tmp < 200) || (tmp > 2000)){
		youxiao = 0;
	}else{
		youxiao = 1;
		wet = 4.4444 * tmp + 111.112;
	}
}
//************************************
//************************************显示功能
void shijianjiemian(){//时间界面
	showsmg(1,Seg_Table[rtctime[2] / 16]);
	showsmg(2,Seg_Table[rtctime[2] % 16]);
	showsmg(3,Seg_Table[16]);
	showsmg(4,Seg_Table[rtctime[1] / 16]);
	showsmg(5,Seg_Table[rtctime[1] % 16]);
	showsmg(6,Seg_Table[16]);
	showsmg(7,Seg_Table[rtctime[0] / 16]);
	showsmg(8,Seg_Table[rtctime[0] % 16]);
}
void wenduhuixian(){//温度回显
	showsmg(1,Seg_Table[12]);
	if(trigger){
		showsmg(3,Seg_Table[tempmax / 10]);
		showsmg(4,Seg_Table[tempmax % 10]);
		showsmg(5,Seg_Table[16]);
		showsmg(6,Seg_Table[tempavr / 100]);
		showsmg(7,Seg_Table[tempavr / 10 % 10] & 0x7f);
		showsmg(8,Seg_Table[tempavr % 10]);
	}
}

void shiduhuixian(){//湿度回显
	showsmg(1,0x89);
	if(trigger){
		showsmg(3,Seg_Table[wetmax / 1000]);
		showsmg(4,Seg_Table[wetmax / 100 % 10]);
		showsmg(5,Seg_Table[16]);
		showsmg(6,Seg_Table[wetavr / 100]);
		showsmg(7,Seg_Table[wetavr / 10 % 10] & 0x7f);
		showsmg(8,Seg_Table[wetavr % 10]);
	}
}

void shijianhuixian(){//时间回显
	showsmg(1,Seg_Table[15]);
	showsmg(2,Seg_Table[trigger / 10]);
	showsmg(3,Seg_Table[trigger % 10]);
	if(trigger){
		showsmg(4,Seg_Table[trigtime[1] / 16]);
	showsmg(5,Seg_Table[trigtime[1] % 16]);
	showsmg(6,Seg_Table[16]);
	showsmg(7,Seg_Table[trigtime[0] / 16]);
	showsmg(8,Seg_Table[trigtime[0] % 16]);
	}
}

void huixianjiemian(){//回显界面选择
	switch(huixian){
		case 0:wenduhuixian();break;
		case 1:shiduhuixian();break;
		case 2:shijianhuixian();break;
	}
}

void wenducanshujiemian(){//温度参数界面
	showsmg(1,0x8c);
	showsmg(7,Seg_Table[tempcanshu / 10]);
	showsmg(8,Seg_Table[tempcanshu % 10]);
}

void wenshidujiemian(){//温湿度界面
	showsmg(1,Seg_Table[14]);
	showsmg(4,Seg_Table[temp / 10]);
	showsmg(5,Seg_Table[temp % 10]);
	showsmg(6,Seg_Table[16]);
	if(youxiao){
		showsmg(7,Seg_Table[wet / 1000 % 10]);
		showsmg(8,Seg_Table[wet  / 100 % 10]);
	}else{
		showsmg(7,Seg_Table[10]);
		showsmg(8,Seg_Table[10]);
	}
}
//************************************
void showselect(){
	switch(show){
		case 0:shijianjiemian();break;
		case 1:huixianjiemian();break;
		case 2:wenducanshujiemian();break;
		case 3:wenshidujiemian();break;
	}
}
//************************************
//************************************采集触发
void caijishuju(){//采集数据
	trigtime[0] = rtctime[1];
	trigtime[1] = rtctime[2];//记录时间
	tempcurrent = temp;wetcurrent = wet;
	tmpcurrent = tmp;
	if((tmpcurrent < 200) || (tmpcurrent > 2000)){
		youxiao2 = 0;
	}else{
		youxiao2 = 1;
	}
	if(youxiao2){
		trigger++;
		if(trigger){
			wetall = (wetcurrent / 100 *10) + wetall;//求和
			wetavr = wetall / trigger;//计算湿度平均值
			tempall = (tempcurrent * 10) + tempall;//求和
			tempavr = tempall / trigger;//计算温度平均值
		}
		if(temp > tempmax){//看看这次数据有没有比之前大
			if(trigger >= 2){
				tempda = 1;
			}
			tempmax = temp;
		}else{
			tempda = 0;
		}
		if(wet > wetmax){//看看这次数据有没有比之前大
			if(trigger >= 2){
				wetda = 1;
			}
			wetmax = wet;
		}else{
			wetda = 0;
		}
	}
}

void caijichufa(){//光敏判断
	light = guangmin();
	Delay(1);
	if(light < 10){
		if(caiji == 0){
			//触发次数增加一次
			caijishuju();
		}
		caiji = 1;
	}
}

void tiaozhuan(){//跳转
	if(caiji){
		show = 3;
	}
}
//************************************
//************************************
void scankey(){//我的S8虚焊,S8换成S12 S9换成S13
	P33 = 0;P32 = 1;P44 = 1;P35 = 1;
	if(P44 == 0){Delay(de);while(P44 == 0){showselect();}
		show++;//S4
		show %= 3;
		showlast = show;
		huixian = 0;
	}
	if(show == 2){//S13
		if(P35 == 0){Delay(de);while(P35 == 0){showselect();}
			tempcanshu++;
			if(tempcanshu > 99){
				tempcanshu = 0;
			}
		}
	}
	
	P33 = 1;P32 = 0;P44 = 1;P35 = 1;
	if(show == 1){
		if(P44 == 0){Delay(de);while(P44 == 0){showselect();}
			huixian++;
			huixian %= 3;
		}
	}
	if(P35 == 0){Delay(de);//S13
		while(P35 == 0){
			keystat = 1;showselect();
		}
		keystat = 0;
		if((show == 1) && (huixian == 2)){
			if(key_count >= 40){
				trigger = 0;
				trigtime[0] = 0;trigtime[1] = 0;
				tempall = 0;tempavr = 0;
				wetall = 0;wetavr = 0;
			}
		}
		if(show == 2){
			tempcanshu--;
			if(tempcanshu < 0){
				tempcanshu = 99;
			}
		}
		key_count = 0;
	}
}
//************************************
//************************************LED
void LED(){
	if(show == 0){
		ledstat = ledstat & ~0x01;
	}else{
		ledstat = ledstat | 0x01;
	}
	
	if(show == 1){
		ledstat = ledstat & ~0x02;
	}else{
		ledstat = ledstat | 0x02;
	}
	
	if(show == 3){
		ledstat = ledstat & ~0x04;
	}else{
		ledstat = ledstat | 0x04;
	}
	
	if((tempcurrent > tempcanshu) && (flag == 1)){
		ledstat = ledstat & ~0x08;
	}else{
		ledstat = ledstat | 0x08;
	}
	
	if(youxiao2 == 0){
		ledstat = ledstat & ~0x10;
	}else{
		ledstat = ledstat | 0x10;
	}
	
	if((tempda == 1) && (wetda == 1)){
		ledstat = ledstat & ~0x20;
	}else{
		ledstat = ledstat | 0x20;
	}
	outputp0(4,ledstat);
}
//************************************
void main(){
	cewen();
	ds1302config();
	Timer_Init();
	initsys();
	while(1){
		cewen();
		ds1302read();
		pinlvzhuanhuashidu();
		showselect();
		LED();
		if(caiji == 0){//采集过程中键盘锁定
			scankey();
		}
		caijichufa();
		tiaozhuan();
	}
}

展示视频

注:我的板子S8有问题,换成了S12,对应地,S9换成S13

S014

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 蓝桥杯单片机第九届省赛的hex文件是一种十六进制文件格式,用于将程序代码转换成可供单片机读取的机器码。这个hex文件是由编译器生成的,其中包含了程序的指令、数据和地址信息。 hex文件可以在单片机上烧写,将程序加载到单片机内存中运行。通过烧写hex文件,可以将代码部署到硬件设备上,完成各种功能和任务。 对于蓝桥杯单片机比赛的参赛选手来说,拿到hex文件后需要将其烧写到指定的单片机上。具体的步骤是:将单片机与计算机通过编程器连接,打开编程软件,选择hex文件并将其下载到单片机中。下载完成后,可以进行功能测试和调试。如果hex文件没有问单片机将按照程序设计的逻辑正常运行。 蓝桥杯单片机比赛的hex文件通常包含了多个功能和子程序,选手需要根据竞赛规定的目要求进行相应的改动和优化。参赛选手可以对hex文件进行反汇编,分析其中的机器码,理解程序的运行原理和逻辑。通过对hex文件的修改和调试,选手可以实现各种功能和算法,完成比赛的要求。 总结来说,蓝桥杯单片机第九届省赛的hex文件是参赛选手完成竞赛过程中重要的载体,通过烧写hex文件到单片机上,选手可以完成编程任务,展示自己的技能和创造力。 ### 回答2: 蓝桥杯单片机第九届省赛的hex文件是一种用于嵌入式系统的程序文件格式。它包含了由汇编或C语言编写的单片机代码,经过编译和链接之后生成的可执行文件。 hex文件以文本的形式呈现,每一行都包含了十六进制的地址和对应的机器码。这些机器码是单片机执行的指令,用于实现特定的功能。 在单片机比赛中,参赛选手需要下载并烧录hex文件到单片机上,以便将程序加载到内存中,使得单片机能够按照代码的要求进行运算和控制。 通过阅读hex文件,我们可以了解程序的整体结构、函数的调用关系以及数据的存储方式。这有助于我们分析代码的逻辑和调试可能出现的错误。 蓝桥杯单片机第九届省赛的hex文件是经过编译的参赛选手提交的作品。为了保证公平性和保密性,比赛组委会在竞赛开始前会提供一个统一的下载接口,选手需要将自己的hex文件上传至该接口,由组委会进行验证和烧录。 总而言之,hex文件是蓝桥杯单片机竞赛中非常重要的一部分,它承载着选手的智慧和努力。通过对hex文件的研究和分析,我们能够更好地理解和掌握单片机编程的技术,提高自己的竞赛水平。 ### 回答3: 蓝桥杯是一个面向高中生和大学生的计算机竞赛,单片机是其中的一个竞赛类别。而第九届省赛中提到的hex文件是单片机程序在编译后生成的二进制文件,该文件存储了程序的机器指令。 hex文件通常以文本格式保存,每一行包含16个字符,其中包括8个十六进制数字、一个标识符和16进制校验和。这些数字表示了相应地址的机器指令或数据。 在蓝桥杯单片机竞赛中,参赛选手需要根据目要求编写相应的单片机程序,并将其编译生成hex文件。这个文件需要在比赛中使用,以将程序烧录到实际的单片机芯片中,从而使其运行。 hex文件的生成通常由编译器自动完成,选手只需将生成的文件保存并在比赛中使用。烧录hex文件到单片机芯片可以使用专门的烧录工具或者调试器进行。 比赛官方会提供相应的参赛规则和操作说明,选手需要按照要求正确操作,将hex文件烧录到单片机中,并保证程序的正常运行。 因此,蓝桥杯单片机第九届省赛中提到的hex文件是指参赛选手需要编写的单片机程序经过编译后生成的二进制文件。选手需要正确生成和使用这个文件,使得程序能够在实际的单片机上正确运行,以完成竞赛任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值