Detailed explanation of the fifth provincial competition question of Lanqiao Cup Microcontroller (simple temperature acquisition and control device)

I highly recommend you do it yourself before watching it! ! !

Demonstration effect

Question explanation

First of all, let’s start with the block diagram of the entire competition question, as shown in the figure.
Insert image description here
Before moving on to the next question, we must first debug the DS18B20, 3×4 matrix buttons, and digital tube display in the block diagram.
Then continue to look down:
Insert image description here
First define the variables to control the digital tube display and the temperature range:

uchar SMG_mode=0,temp=0; //定义数码管模式和温度
uchar Tmax=99,Tmin=0; //定义最高和最低温度阈值

Then display the digital tube according to the picture:

void main(void)
{
    
    
	init(); //初始开发板
	while(1)
	{
    
    
		temp=rd_temperature(); //获取温度
		if(SMG_mode==0)
		{
    
    
			if(temp<Tmin) SMG[1]=0; //小于最小温度为区间0
			else if(temp<=Tmax) SMG[1]=1; //大于最小温度小于最大温度为区间1
			else SMG[1]=2; //大于最大温度为区间2
			SMG[0]=21;SMG[2]=21;
			SMG[3]=20;SMG[4]=20;SMG[5]=20;
			SMG[6]=temp/10;SMG[7]=temp%10;
		}
		SMG_output();
		Jkey_scan();
	}
}

After completing this step, remember to debug it and then proceed to the next step! ! !
As shown in the figure:

Insert image description here
This is a matrix button input program. Press S8 to enter the input mode, so you need to reset a digital tube mode before inputting. and clear the corresponding functions.
When writing an input program, you must understand that input means assigning a value to the extinguished place, clearing means extinguishing the displayed place, and then convert this sentence into logic to write the program.
Write function:

void Input_num(uchar num)
{
    
      //把熄灭的地方给显示,从第一个数码管开始
	if(SMG[1]==20)
	{
    
    
		SMG[1]=num;
	}
	else if(SMG[2]==20)
	{
    
    
		SMG[2]=num;
	}
	else if(SMG[6]==20)
	{
    
    
		SMG[6]=num;
	}
	else if(SMG[7]==20)
	{
    
    
		SMG[7]=num;
	}	
}

Delete function:

void Delect_num(void)
{
    
      //把不熄灭的地方给熄灭,从最后一个数码管开始
	if(SMG[7]!=20)
	{
    
    
		SMG[7]=20;
	}
	else if(SMG[6]!=20)
	{
    
    
		SMG[6]=20;
	}
	else if(SMG[2]!=20)
	{
    
    
		SMG[2]=20;
	}
	else if(SMG[1]!=20)
	{
    
    
		SMG[1]=20;
	}	
}

Key program:

void Jkey_scan(void)
{
    
    
	unsigned char i,key;
	for(i=0x80;i>8;i >>=1)
	{
    
    
		if(i==0x80){
    
    P44=0;P42=1;P3=(~i);}
		else if(i==0x40){
    
    P44=1;P42=0;P3=(~i);}
		else {
    
    P44=1;P42=1;P3=(~i);}
		if(i==0x80){
    
    key=P3;key&=0x7f;}
		else if(i==0x40){
    
    key=P3;key&=0xbf;}
		else {
    
    key=P3;}
		if((key&0x0f)!=0x0f)
		{
    
    
			delay5ms();
			if((key&0x0f)!=0x0f)
			{
    
    
				switch(key)
				{
    
    
					case 0x7e:Input_num(0);break; //输入0
					case 0x7d:Input_num(3);break; //输入3
					case 0x7b:Input_num(6);break; //输入6
					case 0x77:Input_num(9);break; //输入9
				
					case 0xbe:Input_num(1);break; //输入1
					case 0xbd:Input_num(4);break; //输入4
					case 0xbb:Input_num(7);break; //输入7
					case 0xb7:
						if(SMG_mode==0)
						{
    
    
						SMG_mode=1;  
						SMG[1]=SMG[2]=SMG[6]=SMG[7]=20;
						}//先转换数码管显示,再把要输入的熄灭
						else 
						{
    
    
						Tmax=SMG[1]*10+SMG[2]; //再次按下,把输入的值给Tmax,Tmin
						Tmin=SMG[6]*10+SMG[7];
							if((SMG[1]==20)||(SMG[2]==20)||(SMG[6]==20)||(SMG[7]==20)||(Tmax<Tmin))
							{
    
     //当数码管由一个熄灭(每设置)或者tmax<tmin时就LED点亮和清除
								SMG[1]=SMG[2]=SMG[6]=SMG[7]=20;
								LED &=0xfd;SMG_mode=1;
							}
							else {
    
    SMG_mode=0;LED |=0x02;} //没有错误就保存关闭LED
						}break;	

					case 0xde:Input_num(2);break; //输入2
					case 0xdd:Input_num(5);break; //输入5
					case 0xdb:Input_num(8);break; //输入8
					case 0xd7:Delect_num();break; //删除
				}
			}
			while((key&0x0f)!=0x0f)
			{
    
    
				key=P3;SMG_output();//按下按键数码管仍然显示
			}
		}
	}
}

Then look at the last two requirements:
Insert image description here
Here you need to use a timer, we set a 1ms timer;

void Timer0Init(void)		//1毫秒@11.0592MHz
{
    
    
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;ET0=1; //打开定时器中断
}

Then in the interrupt service function, light the LED and relay

uint t=0; //计时
bit state=0; //led状态值
uint ledtime=0; //定义间隔时间
void time0() interrupt 1
{
    
    
	t++;
	if(SMG_mode==0)
	{
    
    
		if(t>=ledtime) //大于等于指定时间
		{
    
    
			t=0; //计时清零
			if(state==0){
    
    state=1;LED&=0XFE;} //LED1亮
			else {
    
    state=0;LED|=0X01;} //灭
		}
	}
}

Then cooperate with the main function to make a judgment:

		if(SMG_mode==0)
		{
    
     //温度判断和继电器控制
			if(temp<Tmin) {
    
    SMG[1]=0;ledtime=800;P2=0XA0;P0=0X00;} //小于最小温度为区间0 //设置时间为800
			else if(temp<=Tmax) {
    
    SMG[1]=1;ledtime=400;P2=0XA0;P0=0X00;} //大于最小温度小于最大温度为区间1,时间400
			else {
    
    SMG[1]=2;ledtime=200;P2=0XA0;P0=0X10;} //大于最大温度为区间2 时间200
			SMG[0]=21;SMG[2]=21;
			SMG[3]=20;SMG[4]=20;SMG[5]=20;
			SMG[6]=temp/10;SMG[7]=temp%10;
		}

Finally modify the values ​​of Tmax and Tminuchar Tmax=30,Tmin=20;
This is done.

complete program

main.c

#include <stc15f2k60s2.h>
#include "intrins.h"
#include "onewire.h"

#define uchar unsigned char
#define uint unsigned int

void SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Jkey_scan(void);
void Input_num(uchar num); //写入
void Delect_num(void); //删除
void Timer0Init(void);
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=0; //定义数码管模式和温度
uchar Tmax=30,Tmin=20; //定义最高和最低温度阈值
uchar LED=0xff; //led控制变量

uint t=0; //计时
bit state=0; //led状态值
uint ledtime=0; //定义间隔时间
void main(void)
{
    
    
	init(); //初始开发板
	Timer0Init(); //初始化定时器
	while(1)
	{
    
    
		temp=rd_temperature(); //获取温度
		if(SMG_mode==0)
		{
    
     //温度判断和继电器控制
			if(temp<Tmin) {
    
    SMG[1]=0;ledtime=800;P2=0XA0;P0=0X00;} //小于最小温度为区间0 //设置时间为800
			else if(temp<=Tmax) {
    
    SMG[1]=1;ledtime=400;P2=0XA0;P0=0X00;} //大于最小温度小于最大温度为区间1,时间400
			else {
    
    SMG[1]=2;ledtime=200;P2=0XA0;P0=0X10;} //大于最大温度为区间2 时间200
			SMG[0]=21;SMG[2]=21;
			SMG[3]=20;SMG[4]=20;SMG[5]=20;
			SMG[6]=temp/10;SMG[7]=temp%10;
		}
		else if(SMG_mode==1) //设置模式
		{
    
    
			//只显示不需要要输入的
			SMG[0]=21; SMG[3]=20;SMG[4]=20;SMG[5]=21;	
		}
		P2=0X80;P0=LED; //led显示
		SMG_output();
		Jkey_scan();
	}
}

void time0() interrupt 1
{
    
    
	t++;
	if(SMG_mode==0) //模式0才生效
	{
    
    
		if(t>=ledtime) //大于等于指定时间
		{
    
    
			t=0; //计时清零
			if(state==0){
    
    state=1;LED&=0XFE;} //LED1亮
			else {
    
    state=0;LED|=0X01;} //灭
		}
	}
}

void Input_num(uchar num)
{
    
      //把熄灭的地方给显示,从第一个数码管开始
	if(SMG[1]==20)
	{
    
    
		SMG[1]=num;
	}
	else if(SMG[2]==20)
	{
    
    
		SMG[2]=num;
	}
	else if(SMG[6]==20)
	{
    
    
		SMG[6]=num;
	}
	else if(SMG[7]==20)
	{
    
    
		SMG[7]=num;
	}	
}

void Delect_num(void)
{
    
      //把不熄灭的地方给熄灭,从最后一个数码管开始
	if(SMG[7]!=20)
	{
    
    
		SMG[7]=20;
	}
	else if(SMG[6]!=20)
	{
    
    
		SMG[6]=20;
	}
	else if(SMG[2]!=20)
	{
    
    
		SMG[2]=20;
	}
	else if(SMG[1]!=20)
	{
    
    
		SMG[1]=20;
	}	
}

void Jkey_scan(void)
{
    
    
	unsigned char i,key;
	for(i=0x80;i>8;i >>=1)
	{
    
    
		if(i==0x80){
    
    P44=0;P42=1;P3=(~i);}
		else if(i==0x40){
    
    P44=1;P42=0;P3=(~i);}
		else {
    
    P44=1;P42=1;P3=(~i);}
		if(i==0x80){
    
    key=P3;key&=0x7f;}
		else if(i==0x40){
    
    key=P3;key&=0xbf;}
		else {
    
    key=P3;}
		if((key&0x0f)!=0x0f)
		{
    
    
			delay5ms();
			if((key&0x0f)!=0x0f)
			{
    
    
				switch(key)
				{
    
    
					case 0x7e:Input_num(0);break; //输入0
					case 0x7d:Input_num(3);break; //输入3
					case 0x7b:Input_num(6);break; //输入6
					case 0x77:Input_num(9);break; //输入9
				
					case 0xbe:Input_num(1);break; //输入1
					case 0xbd:Input_num(4);break; //输入4
					case 0xbb:Input_num(7);break; //输入7
					case 0xb7:
						if(SMG_mode==0)
						{
    
    
						SMG_mode=1;  
						SMG[1]=SMG[2]=SMG[6]=SMG[7]=20;
						}//先转换数码管显示,再把要输入的熄灭
						else 
						{
    
    
						Tmax=SMG[1]*10+SMG[2]; //再次按下,把输入的值给Tmax,Tmin
						Tmin=SMG[6]*10+SMG[7];
							if((SMG[1]==20)||(SMG[2]==20)||(SMG[6]==20)||(SMG[7]==20)||(Tmax<Tmin))
							{
    
     //当数码管由一个熄灭(每设置)或者tmax<tmin时就LED点亮和清除
								SMG[1]=SMG[2]=SMG[6]=SMG[7]=20;
								LED &=0xfd;SMG_mode=1;
							}
							else {
    
    SMG_mode=0;LED |=0x02;} //没有错误就保存关闭LED
						}break;	

					case 0xde:Input_num(2);break; //输入2
					case 0xdd:Input_num(5);break; //输入5
					case 0xdb:Input_num(8);break; //输入8
					case 0xd7:Delect_num();break; //删除
				}
			}
			while((key&0x0f)!=0x0f)
			{
    
    
				key=P3;SMG_output();//按下按键数码管仍然显示
			}
		}
	}
}

void Timer0Init(void)		//1毫秒@11.0592MHz
{
    
    
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;ET0=1; //打开定时器中断
}

void SMG_output(void)
{
    
    
	uchar i;
	for(i=0;i<8;i++)
	{
    
    
	P2=(P2&0X1F)|0Xc0;
	P0=(1<<i);
	P2=(P2&0X1F)|0Xe0;
	P0=tab[SMG[i]];
	Delay1ms();
	}
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void init(void)
{
    
    
	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);
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#include "stc15f2k60s2.h"

sbit DQ = P1^4;  

#define u8 unsigned char
#define u32 unsigned int
	
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

onewire.c

#include "onewire.h"

unsigned char rd_temperature(void)
{
    
    
	u8 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 *=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;
}

Project Files

Network disk link

Guess you like

Origin blog.csdn.net/darlingqx/article/details/127521942