Explicación detallada de las preguntas del VI Concurso Provincial de Microcontrolador (Registrador de temperatura) de la Copa Lanqiao

Efecto de demostración

Explicación de la pregunta

Primero comenzamos con el diagrama de bloques del sistema:
Insertar descripción de la imagen aquí
¡Lo que debe hacer antes de responder las preguntas es depurar cada módulo en el diagrama de bloques del sistema por adelantado! ! !
Una vez completada la depuración, analice la pregunta con más detalle:
Insertar descripción de la imagen aquí
Luego muestre la interfaz de visualización del tubo digital como se muestra en la figura.

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

Requisitos de nota: en la interfaz del reloj, los mensajes 1 y 2 parpadean a intervalos de 1 segundo.
Por lo tanto, el mensaje debe colocarse en el cronómetro para mostrar la tarea.

//定时器初始化
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; //亮
			}
		}
	}
}

Dado que se presiona S5 para ingresar a la interfaz de visualización de la hora desde la interfaz de configuración, también es necesario modificar el programa correspondiente al escaneo de teclas. Dado que el tiempo comienza a contar cuando se presiona el botón, ¡el tiempo de inicialización debe inicializarse en el botón! ! ! Presione S4. La interfaz de configuración cambia entre 1, 5, 30 y 60 segundos.

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: //S5
					if(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;
		}
	}
}

Luego continúe leyendo las preguntas a continuación.
Insertar descripción de la imagen aquí
Dado que se requiere la recopilación de tiempo, el temporizador se utiliza para recopilar dentro del temporizador.

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; //点亮L1
			count=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; //亮
			}
		}
	}
}

La temperatura se muestra después de completar la recolección.

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

Luego se modifica la clave.
S6, L1 se apaga y cambia para mostrar los datos de temperatura almacenados en el dispositivo en orden cronológico;
Presione S7 para ingresar a la interfaz de configuración de parámetros (Figura 1 ), esperando que el usuario ingrese el intervalo de recolección de temperatura, se puede realizar la siguiente recolección de temperatura
.

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; //熄灭L1
				count++;if(count==10)count=0;} //按顺序切换
					break;
				case 0x0b: //S5
					if(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;
		}
	}
}

Insertar descripción de la imagen aquí
Finalmente, ajústelo como se requiere en la imagen y listo.

código

C Principal

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

#define uchar unsigned char
#define uint unsigned int

void 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; //熄灭L1
				count++;if(count==10)count=0;} //按顺序切换
					break;
				case 0x0b: //S5
					if(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; //点亮L1
			count=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<<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);
}

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 <stc15f2k60s2.h>
#include <intrins.h>
#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 <stc15f2k60s2.h>

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

Archivos de proyecto

Archivos de proyecto anotados

Supongo que te gusta

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