《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)

2022年单片机省赛

  • 有关题目
  • 实现代码
    • main.c
    • onewire.h
    • onewire.c
    • ds1302.h
    • ds1302.c

有关题目

《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第1张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第2张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第3张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第4张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第5张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第6张图片
《蓝桥杯真题》:2022年单片机省赛(第十三 / 13届第一场)_第7张图片

实现代码

注意:
数据处理方面:由于ds1302芯片存储的数据是BCD码,所以我们要进行BCD码与十进制之间的转换,例如0x16 的BCD码为16,十进制为1 * 16 + 6 = 32。
源文件修改方面:官方给onewire.h,ds1302.h中使用的时C51的头件"reg52.h",我们需修改为对应的15系列头文件"STC15F2K60S2.h",这样才可以使用一些特殊位寄存器。

底层代码:需修改驱动代码onewire.c中单总线延时函数,官方给我们是STC89C52RC系列,15系列的单片机速度比51快8~12倍,需要修改对应的延时函数。修改如下
void Delay_OneWire(unsigned int t)
{
char i;
while(t–)
for (i = 0; i < 12; i++);
}

main.c

#include "STC15F2K60S2.h"
#include "onewire.h"
#include "ds1302.h"

#define uchar unsigned char
#define uint unsigned int

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;

uchar jm = 0;//界面初始化温度界面
code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff, 0xc1, 0xbf}; 
//U -  11 12

uchar init_time[3] = {0x40, 0x59, 0x23};//初始化时间秒 分 时
uchar time[3] = { 0 };//秒 分 时

bit mod_flag;//0为温度控制模式
bit rel_flag;//继电器是否闭合标志,为0未闭合
bit flag_5s;
bit led10_flag;//初始化0为led10熄灭
bit L1_flag;//初始化0为L1熄灭
bit L3_flag;//初始化0为L3熄灭

float curr_temp;
uchar para_temp = 23;

void sys_init();
void key_handle();
float rd_temperature();
void rd_time();
void rel_handle();
void led();

void dsp_smg_bit(uchar pos, val);
void display();//显示功能,分四个大块
void dsp_temp();
void dsp_time();
void dsp_para();
void dsp_min_sec();//长按S17显示分秒

void delay_k(uchar t);//延时t * 10us
void Delay1ms();		//[email protected],延时1ms用于给足数码管足够显示时间

void main()
{
	sys_init();
	while(1)
	{
		curr_temp = rd_temperature();
		rd_time();//实时读取时间
		key_handle();
		display();	
		rel_handle();//继电器处理
		led();
	}
}

void led()
{	
	if (time[0] == 0x00 && time[1] == 0x00)
	{
		L1_flag = 1;
	}					   
	if (L1_flag)
	{
		P2 = (P2 & 0x1f) | 0x80;
		L1 = 0;
	}
	else 
	{
		P2 = (P2 & 0x1f) | 0x80;
		L1 = 1;
	}
	
	if (!mod_flag)
	{
		P2 = (P2 & 0x1f) | 0x80;
		L2 = 0;
	}
	else 
	{
	 	P2 = (P2 & 0x1f) | 0x80;
		L2 = 1;
	}
	
	if (led10_flag)
	{
		//继电器吸附,间隔0.1sL3闪烁
		if (L3_flag)
		{
			P2 = (P2 & 0x1f) | 0x80;
			L3 = 0;
		}
		else 
			L3 = 1;
	}

	P0 |= 0xf8;//将L4~L8熄灭
	P2 &= 0x1f;
}

void rel_handle()
{
	uint t = (uchar)(curr_temp * 10);
	if (!mod_flag)
	{
		if (t > para_temp * 10)
		{
			led10_flag = 1;
			P2 = (P2 & 0x1f) | 0xa0;
			P0=0X10;
		}
		else 
		{	
			led10_flag = 0;
			P2 = (P2 & 0x1f) | 0xa0;
			P0 = 0xaf;
		}	
	}
	else if (mod_flag)
	{
		if (time[0] == 0x00 && time[1] == 0x00)
		{
			rel_flag = 1;//整点,继电器吸附标志
		}
		if (rel_flag)
		{
			P2 = (P2 & 0x1f) | 0xa0;
			P0 = 0x10;
			led10_flag = 1;
		}
		else 
		{
			P2 = (P2 & 0x1f) | 0xa0;
			P0 = 0xaf;
			led10_flag = 0;
		}
	}
	//P0 |= 0x00;
	//P2 &= 0x1f;
}


void rd_time()
{
	uchar t;
	
	t = Read_Ds1302_Byte(0x81);//秒
	time[0] = t / 16 * 10 + t % 16 ;
	
	t = Read_Ds1302_Byte(0x83);//分
	time[1] = t / 16 * 10 + t % 16 ;
	
	t = Read_Ds1302_Byte(0x85);//时
	time[2] = t / 16 * 10 + t % 16 ;
}

void display()
{
	if (0 == jm)
		dsp_temp();
	else if (1 == jm)
		dsp_time();
	else if (2 == jm)
		dsp_para();
}
void dsp_min_sec()
{
	dsp_smg_bit(1, 11);//U
	dsp_smg_bit(2, 2);//
	
	dsp_smg_bit(4, time[1] / 10);
	dsp_smg_bit(5, time[1] % 10);
	dsp_smg_bit(6, 12);//-
	dsp_smg_bit(7, time[0] / 10);
	dsp_smg_bit(8, time[0] % 10);

}
void dsp_para()
{
	dsp_smg_bit(1, 11);//U
	dsp_smg_bit(2, 3);//
	
	dsp_smg_bit(7, para_temp / 10 % 10);
	dsp_smg_bit(8, para_temp % 10);
}

void dsp_time()
{
	dsp_smg_bit(1, 11);//U
	dsp_smg_bit(2, 2);//
	
	dsp_smg_bit(4, time[2] / 10);
	dsp_smg_bit(5, time[2] % 10);
	dsp_smg_bit(6, 12);//-
	dsp_smg_bit(7, time[1] / 10);
	dsp_smg_bit(8, time[1] % 10);
}

void dsp_temp()
{
	uint x = (uint)(curr_temp * 10);//当前温度扩大10倍
	dsp_smg_bit(1, 11);//U
	dsp_smg_bit(2, 1);//
	dsp_smg_bit(6, x / 100 % 10);
	
	//第7位数码管显示小数点
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 1 << (7 - 1);
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = tab[x / 10 % 10] & 0x7f;
	Delay1ms();
	
	P0 = 0xff;
	P2 &= 0x1f;
	
	dsp_smg_bit(8, x % 10);
}

void dsp_smg_bit(uchar pos, val)
{
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 1 << (pos - 1);
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = tab[val];
	Delay1ms();
	
	P0 = 0xff;
	P2 &= 0x1f;
}

void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

void delay_k(uchar t)
{
	while(t--)
		display();
}

 void key_handle()
{
	P35 = P34 = P32 = 1;
	P33 = 0;//第四行拉低
	if(!P35)//s12
	{
		delay_k(10);
		if(!P35)
		{
			
			if (++jm >= 3)
			jm = 0;
			while(!P35)
			{
				display();
			}
		}
	}
	
	if(!P34)//s16
	{
		delay_k(10);
		if(!P34)
		{
			if (2 == jm)
			{	
				if (++para_temp > 99)
					para_temp = 99;
			}
				while(!P34)
			{
				display();
			}
		}
	}
	
	P35 = P34 = P33 = 1;
	P32 = 0;//第三行拉低
	if(!P35)//s13
	{
		delay_k(10);
		if(!P35)
		{	
			mod_flag = !mod_flag;
			while(!P35)
			{
				display();
			}
		}
	}
	
	if(!P34)//s17
	{
		delay_k(10);
		if(!P34)
		{
			if (2 == jm)
			{
				if (--para_temp < 10)//参数操作 + 参数检查
					para_temp = 10;
			}
			if (1 == jm)
			{
				while(!P34)//s17的长按键操作
				{
					rd_time();
					dsp_min_sec();
				}
			}
			while(!P34)
			{
				display();
			}		
		}
	}
}

float rd_temperature()
{
	uchar l, h;
	uint t;
	float temp;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	l = Read_DS18B20();
	h = Read_DS18B20();
	
	t = (h & 0x0f);
	t <<= 8;
	t |= l;
	temp = t * 0.0625;
	
	return temp;
}

void timer0() interrupt 1
{
	static uint i1, i2, i3;
	if (rel_flag)//继电器闭合5秒断开标志
	{
		if (++i1 == 5000)
		{
			i1 = 0;
			rel_flag = 0;
		}
	}
	if (L1_flag)
	{
		if (++i2 == 5000)
		{
			i2 = 0;
			L1_flag = 0;
		}
	}
	if (++i3 == 100)//0.1s切换一次L3的状态,使其闪烁
	{
		L3_flag = !L3_flag;
		i3 = 0;
	}
}


void sys_init()
{
	//关蜂鸣器,继电器
	P2 = (P2 & 0x1f) | 0xa0;
	P0 = 0xaf;
	
	P2 = (P2 & 0x1f) | 0x80;
	P0 = 0xff;
	P2 &= 0x1f;

	Write_Ds1302_Byte(0x8e,0x00);//关闭写保护
	Write_Ds1302_Byte(0x80, init_time[0]);//秒
	Write_Ds1302_Byte(0x82, init_time[1]);//分
	Write_Ds1302_Byte(0x84, init_time[2]);//时
	Write_Ds1302_Byte(0x8e,0x80);//开启写保护
	
	//1ms
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0 = 1;
	ET1 = 0;//禁止定时器中断1中断
	EA = 1;
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#include 

bit init_ds18b20(void);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
void Delay_OneWire(unsigned int t);  

#endif


onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "onewire.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	char i;
	while(t--)
		for (i = 0; i < 12; i++);
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
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;
}

//DS18B20设备初始化
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;
}


ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

#include "STC15F2K60S2.h"
#include 

sbit SCK = P1^7;		
sbit SDA = P2^3;		
sbit RST = P1^3; 

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

ds1302.c

#include "ds1302.h"  									

//写字节
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//向DS1302寄存器写入数据
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);		
 	RST=0; 
}

//从DS1302寄存器读出数据
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);			
}

你可能感兴趣的:(第十三届蓝桥杯_单片机,CT107D,蓝桥杯,单片机)