蓝桥杯单片机第六届省赛题详细讲解(温度记录器)
创始人
2024-04-02 07:59:08
0

看之前强烈建议先自己做一遍!!!

    • 演示效果
    • 题目讲解
    • 代码
      • main.c
      • ds1302.c
      • ds1302.h
      • onewire.c
      • onewire.h
    • 工程文件

演示效果

题目讲解

首先我们从系统框图看起:
在这里插入图片描述
做题之前要做的是把系统框图里面的各个模块先提前调试好!!!
调试完成后进一步看题目:
在这里插入图片描述
然后按照如图数码管显示界面进行显示。

uchar SMG_mode=0,temp; //数码管模式定义 温度定义
uchar time_gap=1; //采集间隔时间定义
void main(void)
{init(); //初始开发板while(1){temp=rd_temperature();if(SMG_mode==0) //界面1,设置界面{get_time(); //时间获取SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; //数码管全熄SMG[5]=21;SMG[6]=time_gap/10;SMG[7]=time_gap%10; //显示采集间隔}else if(SMG_mode==1)//界面2,时钟显示界面{SMG[0]=time[2]/10;SMG[1]=time[2]%10; //显示时SMG[3]=time[1]/10;SMG[4]=time[1]%10;  //显示分SMG[6]=time[0]/10;SMG[7]=time[0]%10; //显示秒}SMG_output();Dkey_scan();}
}

注意要求:时钟界面,提示符1,2以1秒为间隔闪烁。
所以提示符要放在定时器里面进行赋值显示。

//定时器初始化
void Timer0Init(void)		//5毫秒@11.0592MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TL0 = 0x00;		//设置定时初值TH0 = 0x28;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时EA=1;ET0=1; //打开定时器0中断
}uchar t,state=0; //中断计数 显示状态
//定时器0中断服务函数
void time0() interrupt 1
{if(SMG_mode==1){t++;if(t>=200) //200*5 以一秒为间隔{t=0;if(state==1){state=0;SMG[2]=SMG[5]=20; //熄灭}else{state=1;SMG[2]=SMG[5]=21; //亮}}}
}

由于是按下S5,从设置界面进入时间显示界面,所以按键扫描对应的程序也要修改。由于时间要在按键按下才开始计时,所以初始化时间一定要在按键中初始化!!!按下S4。设置界面由1s,5s,30s,60s来回切换

void Dkey_scan(void)
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:break;case 0x0d:break;case 0x0b: //S5if(SMG_mode==0){SMG_mode=1;ds1302_init();} //按下S5进入时间显示,并初始化时间break;case 0x07:if(SMG_mode==0) //间隔时间只能设置模式改变{ //时间间隔切换if(time_gap==1)time_gap=5;else if(time_gap==5)time_gap=30;else if(time_gap==30)time_gap=60;else if(time_gap==60)time_gap=1;}break;}keybyte=0;}}
}

然后接着往下看题目。
在这里插入图片描述
由于要进行时间采集,所以定时器的使用,在定时器内进行采集。

bit enable=0; //控制采集打开和关闭
uchar Temp_stat[10]={0,0,0,0,0,0,0,0,0,0};//温度数据保存
uchar count=0;//定义采集次数
uint stat_t=0; //采集定时器计数
//定时器0中断服务函数
void time0() interrupt 1
{if(enable==1){stat_t++;if((stat_t*5)>=(time_gap*1000)) //5*s >=采集时间进行采集*1000ms{stat_t=0;Temp_stat[count]=temp; //采集count++; //计数if(count>=10){P2=0X80;P0=0Xfe; //点亮L1count=0;enable=0;SMG_mode=2;} //采集完10次关闭,数码管显示切换}}if(SMG_mode==1){t++;if(t>=200) //200*5 以一秒为间隔{t=0;if(state==1){state=0;SMG[2]=SMG[5]=20; //熄灭}else{state=1;SMG[2]=SMG[5]=21; //亮}}}
}

采集完成后的温度显示。

		else if(SMG_mode==2) //采集完成后的温度显示{SMG[0]=21;SMG[1]=count/10; //-00 SMG[2]=count%10;SMG[3]=SMG[4]=20;  SMG[6]=Temp_stat[count]/10;SMG[7]=Temp_stat[count]%10; }

然后就是对按键进行修改。
S6, L1 熄灭,按照时间先后顺序,切换显示设备内存储的温度数据;
S7 按键进入参数设置界面(图 1),待用户输入温度采集间隔之后,可以进行
下一次的温度采集工作。

void Dkey_scan(void)
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:if(SMG_mode==2){SMG_mode=0;count=0;time_gap=1;}//S7重新设置break;case 0x0d:if(SMG_mode==2){P2=0X80;P0=0Xff; //熄灭L1count++;if(count==10)count=0;} //按顺序切换break;case 0x0b: //S5if(SMG_mode==0){SMG_mode=1;ds1302_init();enable=1;} //按下S5进入时间显示,并初始化时间,打开温度捕获使能break;case 0x07:if(SMG_mode==0) //间隔时间只能设置模式改变{ //时间间隔切换if(time_gap==1)time_gap=5;else if(time_gap==5)time_gap=30;else if(time_gap==30)time_gap=60;else if(time_gap==60)time_gap=1;}break;}keybyte=0;}}
}

在这里插入图片描述
最后按照如图要求进行微调就做完了。

代码

main.c

#include 
#include "intrins.h"
#include "onewire.h"
#include "ds1302.h"#define uchar unsigned char
#define uint unsigned intvoid SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Dkey_scan(void);
void Timer0Init(void);extern uchar time[7]; //ds1302.c中定义的存储时间的数组uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管uchar SMG_mode=0,temp; //数码管模式定义 温度定义
uchar time_gap=1; //采集间隔时间定义
uchar t,state=0; //中断计数 显示状态bit enable=0; //控制采集打开和关闭
uchar Temp_stat[10]={0,0,0,0,0,0,0,0,0,0};//温度数据保存
uchar count=0;//定义采集次数
uint stat_t=0; //采集定时器计数
void main(void)
{init(); //初始开发板Timer0Init();while(1){temp=rd_temperature();if(SMG_mode==0) //界面1,设置界面{SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; //数码管全熄SMG[5]=21;SMG[6]=time_gap/10;SMG[7]=time_gap%10; //显示采集间隔}else if(SMG_mode==1)//界面2,时钟显示界面{get_time(); //时间获取SMG[0]=time[2]/10;SMG[1]=time[2]%10; //显示时SMG[3]=time[1]/10;SMG[4]=time[1]%10;  //显示分SMG[6]=time[0]/10;SMG[7]=time[0]%10; //显示秒}else if(SMG_mode==2) //采集完成后的温度显示{SMG[0]=21;SMG[1]=count/10; //-00 SMG[2]=count%10;SMG[3]=SMG[4]=20;  SMG[6]=Temp_stat[count]/10;SMG[7]=Temp_stat[count]%10; }SMG_output();Dkey_scan();}
}void Dkey_scan(void)
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:if(SMG_mode==2){SMG_mode=0;count=0;time_gap=1;}//S7重新设置break;case 0x0d:if(SMG_mode==2){P2=0X80;P0=0Xff; //熄灭L1count++;if(count==10)count=0;} //按顺序切换break;case 0x0b: //S5if(SMG_mode==0){SMG_mode=1;ds1302_init();enable=1;} //按下S5进入时间显示,并初始化时间,打开温度捕获使能break;case 0x07:if(SMG_mode==0) //间隔时间只能设置模式改变{ //时间间隔切换if(time_gap==1)time_gap=5;else if(time_gap==5)time_gap=30;else if(time_gap==30)time_gap=60;else if(time_gap==60)time_gap=1;}break;}keybyte=0;}}
}//定时器0中断服务函数
void time0() interrupt 1
{if(enable==1){stat_t++;if((stat_t*5)>=(time_gap*1000)) //5*200s >=采集时间进行采集*1000ms{stat_t=0;Temp_stat[count]=temp; //采集count++; //计数if(count>=10){P2=0X80;P0=0Xfe; //点亮L1count=0;enable=0;SMG_mode=2;} //采集完10次关闭,数码管显示切换}}if(SMG_mode==1){t++;if(t>=200) //200*5 以一秒为间隔{t=0;if(state==1){state=0;SMG[2]=SMG[5]=20; //熄灭}else{state=1;SMG[2]=SMG[5]=21; //亮}}}
}void Timer0Init(void)		//5毫秒@11.0592MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TL0 = 0x00;		//设置定时初值TH0 = 0x28;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时EA=1;ET0=1; //打开定时器0中断
}void SMG_output(void)
{uchar i;for(i=0;i<8;i++){P2=(P2&0X1F)|0Xc0;P0=(1<P2=(P2&0X1F)|0XA0;P0=0X00;P2=(P2&0X1F)|0X80;P0=0Xff;P2=(P2&0X1F)|0Xc0;P0=0Xff;P2=(P2&0X1F)|0Xe0;P0=0Xff;	
}void Delay1ms(void)		//@11.0592MHz
{unsigned char i, j;_nop_();_nop_();_nop_();i = 11;j = 190;do{while (--j);} while (--i);
}void delay5ms(void)		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}

ds1302.c

#include "ds1302.h"  									uchar time[7]={50,59,23,0,0,0,0};void ds1302_init(void)
{uchar i,j=0x80;Write_Ds1302_Byte(0x8e,0x00);for(i=0;i<7;i++){Write_Ds1302_Byte(j,time[i]);j +=2;}Write_Ds1302_Byte(0x8e,0x80);
}void get_time(void)
{uchar i,j=0x81;Write_Ds1302_Byte(0x8e,0x00);for(i=0;i<7;i++){time[i]=Read_Ds1302_Byte(j);j +=2;}Write_Ds1302_Byte(0x8e,0x80);
}//
void Write_Ds1302(unsigned  char temp) 
{unsigned char i;for (i=0;i<8;i++)     	{ SCK = 0;SDA = temp&0x01;temp>>=1; SCK=1;}
}   //
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{RST=0;	_nop_();SCK=0;	_nop_();RST=1; 	_nop_();  Write_Ds1302(address);	Write_Ds1302(((dat/10)<<4)|(dat%10));		RST=0; 
}unsigned char Read_Ds1302_Byte ( unsigned char address )
{unsigned char i,temp=0x00;RST=0;	_nop_();SCK=0;	_nop_();RST=1;	_nop_();Write_Ds1302(address);for (i=0;i<8;i++) 	{		SCK=0;temp>>=1;	if(SDA)temp|=0x80;	SCK=1;} RST=0;	_nop_();SCK=0;	_nop_();SCK=1;	_nop_();SDA=0;	_nop_();SDA=1;	_nop_();return (((temp/16)*10)+(temp%16));			
}

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H#include 
#include 
#define uchar unsigned char
#define uint unsigned int
sbit SCK = P1^7;		
sbit SDA = P2^3;		
sbit RST = P1^3; 
void ds1302_init(void);
void get_time(void);
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );#endif

onewire.c

#include "onewire.h"unsigned char rd_temperature(void)
{unsigned char de,gao;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);	de=Read_DS18B20();gao=Read_DS18B20();return((de >>4)|(gao<<4));
}//
void Delay_OneWire(unsigned int t)  
{t=t*8;while(t--);
}//
void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i=0;i<8;i++){DQ = 0;DQ = dat&0x01;Delay_OneWire(5);DQ = 1;dat >>= 1;}Delay_OneWire(5);
}//
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;if(DQ){dat |= 0x80;}	    Delay_OneWire(5);}return dat;
}//
bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ;     Delay_OneWire(5);return initflag;
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H#include sbit DQ = P1^4;  unsigned char rd_temperature(void);  //; ;
void Delay_OneWire(unsigned int t);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void Write_DS18B20(unsigned char dat);#endif

工程文件

有注释的工程文件

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...