Explicación detallada de la quinta pregunta de la competencia provincial sobre el microcontrolador de la Copa Lanqiao (dispositivo simple de control y adquisición de temperatura)

Efecto de demostración

Explicación de la pregunta

En primer lugar, comencemos con el diagrama de bloques de toda la pregunta de la competencia, como se muestra en la figura.
Insertar descripción de la imagen aquí
Antes de pasar a la siguiente pregunta, primero debemos depurar el DS18B20, los botones de matriz 3×4 y la pantalla del tubo digital en el diagrama de bloques.
Luego continúa mirando hacia abajo:
Insertar descripción de la imagen aquí
Primero define las variables para controlar la pantalla del tubo digital y el rango de temperatura:

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

Luego muestre el tubo digital según la imagen:

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

Después de completar este paso, recuerde depurarlo y luego continuar con el siguiente paso. ! !
Como se muestra en la figura:

Insertar descripción de la imagen aquí
Este es un programa de entrada de botones de matriz. Presione S8 para ingresar al modo de entrada, por lo que necesita restablecer un modo de tubo digital antes. ingresar y borrar las funciones correspondientes.
Al escribir un programa de entrada, debe comprender que ingresar significa asignar un valor al lugar extinguido, borrar significa extinguir el lugar mostrado y luego convertir esta oración en lógica para escribir el programa.
Función de escritura:

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;
	}	
}

Función de eliminación:

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;
	}	
}

Programa clave:

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();//按下按键数码管仍然显示
			}
		}
	}
}

Entonces mira los dos últimos requisitos:
Insertar descripción de la imagen aquí
Aquí necesitas usar un temporizador, configuramos un temporizador de 1 ms;

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; //打开定时器中断
}

Luego, en la función de servicio de interrupción, encienda el LED y el relé.

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;} //灭
		}
	}
}

Luego coopere con la función principal para emitir un juicio:

		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;
		}

Finalmente modifica los valores de Tmax y Tminuchar Tmax=30,Tmin=20;
Esto está hecho.

programa completo

C Principal

#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;
}

Archivos de proyecto

Enlace de disco de red

Supongo que te gusta

Origin blog.csdn.net/darlingqx/article/details/127521942
Recomendado
Clasificación