蓝桥杯单片机第11届国赛-电压频率测量

题目

在这里插入图片描述
读取ds18b20温度数据需要较长时间,逻辑分析仪观察读取一次温度(两字节)大概需要13毫秒,因此温度读取不能放在定时器中断,这会严重影响定时精度,导致数码管剧烈闪烁、计时错误等。另外,将温度读取放在主函数会发现温度指示灯L2在显示温度时,数码管和L2每隔一段时间会同时闪一下。这是因为主函数读取温度数据(16位)可能会被定时器中断,就比如读到第5位温度数据时产生中断,这时将执行中断函数,而执行完中断函数需要一定时间,后面几位温度数据据继续输出,MCU会错过读取这段数据,导致数据读取丢失,因此即使温度不变,读取的温度数据也会变化。
解决的办法有两个,一是判断读取的温度数据是否在正常范围内,一般在0-40度之间(乘了10,方便显示小数,因此40度为400),再改变主函数中温度值代码如下:

temp = TemperGet( );
if(temp > 0 && temp < 400)  //降低 因中断导致的数据接收错误 的概率
	tempr = temp;  //tempr为要显示处理的温度值,是个全局变量。

这一方法可以明显降低L2和数码管闪烁概率,但是仍然可能出现闪烁现象;二是换一个高速温度传感器,比如LM75A这样的IIC接口温度传感器,这样就可以将温度读取的函数放在中断函数里,避免读取数据时被打断。

main.c

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

#define uchar unsigned char
#define uint unsigned int
#define s0 0
#define s1 1
#define s2 2

char * get_ds1302();
void ds1302_init(char *time);
int TemperGet( );
int read_vol( );

uchar semg[15] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
								 0x86, 0xc6, 0x8c, 0xff, 0xbf};
uchar semg_bit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar semg_temp[8] = {13, 13, 13, 13, 13, 13, 13, 13};

uchar state = s0;
uchar state_data = s0;
uchar state_para = s0;
char time[3] = {16, 59, 50};
int tempr = 201;
uchar bri;
int   vol = 100;
char hour_para =17;
char tempr_para = 25;
char led_para = 4;


void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}


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


void display()
{
	static uchar i = 0;
	
	P2 = 0x00; P0 = 0xff;
	if( (state == 0) && (state_data == s1) && (i == 6) )
	{
		P2 = 0xe0;	P0 = semg[semg_temp[i]] & 0x7f;	P2 = 0x00;	P0 = 0xff;
		P2 = 0xc0; P0 = semg_bit[i];
	}
	else if( (state == 0) && (state_data == s2) && (i == 2) )
	{
		P2 = 0xe0;	P0 = semg[semg_temp[i]] & 0x7f;	P2 = 0x00;	P0 = 0xff;
		P2 = 0xc0; P0 = semg_bit[i];
	}
	else
	{
		P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;	P0 = 0xff;
		P2 = 0xc0; P0 = semg_bit[i];
	}
	P2 = 0x00; P0 = 0xff;
	
	i++;
	if(i == 8)
		i = 0;
}


void led()
{
	static uchar state_led = s0;
	static int count_time = 0;
	
	P2 = 0x00;	P0 = 0xff;
	switch(state_led)
	{
		case s0:
		{
			P02 = 1;
			if(bri)
			{
				count_time++;
				if(count_time == 1480)
					state_led = s1;
			}
			else		
				count_time = 0;
		}	break;
			
		case s1:
		{
			P02 = 0;
			count_time = 0;
			if(!bri)
			{
				P02 = 1;
				count_time = 0;
				state_led = s0;
			}
			else
				state_led = s1;
		}	break;
		
		default: state_led = s0; break;
	}
		
	if(hour_para > 8)
	{
		if( (time[0] >= hour_para) || (time[0] < 8) )
			P00 =0;
		else 
			P00 =1;
	}
	else if(hour_para < 8)
	{
		if( (time[0] >= hour_para) && (time[0] < 8) )
			P00 =0;
		else 
			P00 =1;
	}
	else
		P00 = 1;
		
	if(tempr < tempr_para * 10)
		P01 = 0;
	else
		P01 = 1;
	P0 = P0 | 0xf8;
	
	if(bri)
		P0 = P0 & (~(0x01 << (led_para - 1)));
	else
	 P0 = P0 | 0xf8;
	P2 = 0x80;
	P2 = 0x00; P0 = 0xff;
}


void fun() interrupt 1
{
	static uchar i = 0, k = 0;
	uchar *temp_time, j;
	
	display();
	led();
	
	k++;
	if(k >= 100)
	{
		k = 0;
		temp_time = get_ds1302( );
		for(j= 0; j < 3; j++)
			time[j] = temp_time[j];
	}
	if(state == s0)
	{
		i++;
		if(i >= 100)
		{	
			i= 0;
			vol = read_vol( );
			if(vol < 200)
				bri = 1;
			else
				bri = 0;
		}
	}
}


void disfun() interrupt 3
{	
	display();
	led();
}


char keyscan()
{
	uchar keyrow, keycolumn, keycode, i ,j;
	static uchar keystate = s0;
	char keyvalue;
	
	P44 = 0; P42 = 0; P3 = 0x0f;
	keyrow = P3 & 0x0f;
	P44 = 1; P42 = 1; P3 = 0xf0;
	if(P44 == 0)	keycolumn = 0x70;
	else if(P42 == 0)	keycolumn = 0xb0;
	else	keycolumn = P3 & 0xf0;
	
	keycode = ~(keyrow | keycolumn);
	
	switch(keystate)
	{
		case s0:
			if(keycode)
				keystate = s1;
			else
				keyvalue = -1;
			break;
			
		case s1:
			if(keycode)
			{
				for(i = 0; i < 4; i++)
					for(j = 0; j < 4; j++)
						if( keycode == ((0x80>>i) |(0x08>>j)) )
						{
							keyvalue = i*4 +j + 4;
							break;
						}
				keystate = s2;
			}
			else
				keystate = s0;
			break;
				
		case s2:
		{
			keyvalue = -1;
			if(!keycode)
				keystate = s0;
			else	;
		}	break;
			
		default: keystate = s0;	break;
	}
	return keyvalue;
}


void menu(char keyvalue)
{
	static char temp_hour = 17, temp_tempr = 25, temp_led = 4;
	
	switch(state)
	{
		case s0:
		{
			if(keyvalue == 4)
			{
				state_para = s0;
				state = s1;
			}
			switch(state_data)
			{
				case s0:
				{
					semg_temp[0] = time[0] / 10;
					semg_temp[1] = time[0] % 10;
					semg_temp[2] = 14;
					semg_temp[3] = time[1] / 10;
					semg_temp[4] = time[1] % 10;
					semg_temp[5] = 14;
					semg_temp[6] = time[2] / 10;
					semg_temp[7] = time[2] % 10;
					if(keyvalue == 5)
						state_data = s1;
				}	break;
					
				case s1:
				{
					semg_temp[0] = 11;
					semg_temp[1] = 13;
					semg_temp[2] = 13;
					semg_temp[3] = 13;
					semg_temp[4] = 13;
					semg_temp[5] = tempr / 100;
					semg_temp[6] = (tempr - semg_temp[5] * 100) / 10;
					semg_temp[7] = tempr % 10;
					if(keyvalue == 5)
						state_data = s2;
				}	break;
						
				case s2:
				{
					semg_temp[0] = 10;
					semg_temp[1] = 13;
					semg_temp[2] = vol / 100;;
					semg_temp[3] = (vol - semg_temp[2] * 100) / 10;
					semg_temp[4] = vol % 10;
					semg_temp[5] = 13;
					semg_temp[6] = 13;
					semg_temp[7] = bri;
					if(keyvalue == 5)
						state_data = s0;						
				}	break;
					
				default: state_data = s0;	break;
			}
		}	break;
			
		case s1:
		{
			semg_temp[2] = 13;
			semg_temp[3] = 13;
			semg_temp[4] = 13;
			semg_temp[5] = 13;
			if(keyvalue == 4)
			{
				state = s0;
				state_data = s0;
				hour_para = temp_hour;
				tempr_para = temp_tempr;
				led_para = temp_led;
			}
			switch(state_para)
			{
				case s0:
				{
					semg_temp[0] = 12;
					semg_temp[1] = 1;
					semg_temp[6] = temp_hour / 10;
					semg_temp[7] = temp_hour % 10;
					if(keyvalue == 5)
						state_para = s1;
					else if(keyvalue == 8)
					{
						temp_hour++;
						if(temp_hour > 23)
							temp_hour = 0;
					}
					else if(keyvalue == 9)
					{
						temp_hour--;
						if(temp_hour < 0)
							temp_hour = 23;
					}
				}	break;
					
				case s1:
				{
					semg_temp[0] = 12;
					semg_temp[1] = 2;
					semg_temp[6] = temp_tempr / 10;
					semg_temp[7] = temp_tempr % 10;
					if(keyvalue == 5)
						state_para = s2;
					else if(keyvalue == 8)
					{
						temp_tempr++;
						if(temp_tempr > 99)
							temp_tempr = 0;
					}
					else if(keyvalue == 9)
					{
						temp_tempr--;
						if(temp_tempr < 0)
							temp_tempr = 99;
					}
				}	break;
						
				case s2:
				{
					semg_temp[0] = 12;
					semg_temp[1] = 3;
					semg_temp[6] = 13;
					semg_temp[7] = temp_led;
					if(keyvalue == 5)
						state_para = s0;
					else if(keyvalue == 8)
					{
						temp_led++;
						if(temp_led > 8)
							temp_led = 4;
					}
					else if(keyvalue == 9)
					{
						temp_led--;
						if(temp_led < 4)
							temp_led = 8;
					}
				}	break;
					
				default: state_para = s0;	break;
			}
		}	break;
				
		default: state = s0;	break;
	}

}


void allinit()
{
	P2 = 0x80;	P0 = 0xff;
	P2 = 0xe0;	P0 = 0xff;
	P2 = 0xc0;	P0 = 0xff;
	P2 = 0xa0;	P0 = 0x00;
}


void main()
{
	char keyvalue;
	int temp = 0;
	
	ds1302_init(&time);
	allinit();
	Timer0Init();
	
	while(1)
	{
		keyvalue = keyscan();
		menu(keyvalue);
		temp = TemperGet( );
		if(temp > 0 && temp < 400)  //降低 因中断导致的数据接收错误 的概率
			tempr = temp;
		Delay5ms();	
	}
}

ds1302.c

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

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

void ds1302_init(char *time)
{
	uchar addr, i;
	
	addr = 0x84;
	Write_Ds1302_Byte(0x8e, 0x00);
	for(i = 0; i < 3; i++)
	{
		Write_Ds1302_Byte(addr, ((time[i] / 10) << 4) + (time[i] % 10) );
		addr -= 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);
}

char * get_ds1302()
{
	char time[3];
	uchar addr, i;
	
	addr = 0x85;
	Write_Ds1302_Byte(0x8e, 0x00);
	for(i = 0; i < 3; i++)
	{
		time[i] = Read_Ds1302_Byte(addr);
		time[i] = ((time[i] / 16) * 10) + (time[i] % 16);//BCD码转换为10进制数
		addr -= 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);
	
	return time;
}

ds18b20.c

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

#define uchar unsigned char
#define uint unsigned int

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

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}

//通过单总线向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;
}

int TemperGet()
{
	uchar low,high,temp;
	int tempr;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(100);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp = (low & 0x0f) * 0.625;
	low=low>>4;
	high=high<<4;
	tempr = (high | low) *10 + temp;
	return tempr;
}

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

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


#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */


void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}


void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}


bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}


void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}


unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}

int read_vol( )
{
	int dat;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x01);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat=IIC_RecByte();	
  IIC_Stop();
	dat=dat*1.96078;
	return dat;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值