【聚沙成塔 | 4T网单片机练习】按键控制DS18B20温度精度显示

1、题目:

2、DS18B20温度传感器原理图:

DQ引脚P14

3、DS18B20读温度的基本代码

 修改onewire.c:

1、加头文件

2、定义引脚sbit DQ=P1^4;

3、添加读取温度函数

// add: reading the temperature function
unsigned int read_temp()
{
	unsigned int temp;
	unsigned char tempH, tempL;
	
	init_ds18b20();
	
	// Skip ROM operations and send commands directly to the DS18B20
	// Since there is only one temperature sensor
	Write_DS18B20(0xcc);
	
	// Start the temperature conversion command
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	// Send read temperature command
	Write_DS18B20(0xbe);
	
	// Firstly read the low byte of the temperature value
	tempL = Read_DS18B20();
	// Secondly the high byte
	tempH = Read_DS18B20();
	
	// combination
	temp = tempH<<8|tempL;
	
	// integer value: 0.0625
	// one decimal: 0.0625*10
	// two decimal: 0.0625*100
	temp = 0.0625*temp;
	return temp;
}

注意:

  • 精度是0.0625,如果想要显示1位小数,就扩大10倍,乘以0.625;显示2位小数,就扩大100倍,乘以6.25。
  • 函数返回值是unsigned int

主函数操作:

1、extern外部调用onewire.c中我们自己定义的这个读取温度的函数

2、定义全局变量temperature,接收读温度函数的返回值。

3、数码管段选表增添带有小数点的数字:将0~9的段选高4位减去8即可,也就是让最高一位置0。0~9(带小数点)紧挨着放到0~9(无小数点)的后面。这样0~9(带小数点)的索引就是10~19,也就是原始数字索引值0~9的基础上+10

4、温度传感器读取温度需要一定的时间,可以设置500ms(或其他时间间隔)读一次温度。这个时候需要再定义一个全局的温度的计时变量time_temp。计时变量time_temperature的自增操作则放在定时器1的中断服务程序中,即每过1ms自增1。然后放到main函数的while循环去判断有没有自增到500,如果自增到500,就调用一次读温度函数,同时将计时变量time_temp归零。

5、使用数码管显示功能正常显示温度即可,记得在对应位置加上小数点,+10即可。

4、学习心得 

① 稳定按键的while循环

第一遍写完代码,测试的时候,发现按键很不稳定,按一下切换的时候总是闪烁,或者切换不成功。后来发现是延迟10ms判断按键按下,做了状态变量的切换以后,还必须写一个while循环直到按键被释放。

void key()
{
    P44=1; P42=0 ;P35=1 ;P34=1;
    if(P32==0){
        Delay10ms();
        if(P32==0) state=!state;
        //while循环不可省!
        while(!P32);

    }
}

② 学会用全局状态变量来辅助按键判断

由于本题只有2种状态,1位小数和2位小数。所以设bit型的全局状态变量state,每当按键S9被按下,就将state逻辑取反,从而达到使用S9一个按键切换两种状态的目的。

5、完整main代码

#include <STC15F2K60S2.H>

#define Y4C P2=P2&0X1F|0X80;
#define Y5C P2=P2&0X1F|0Xa0;
#define Y6C P2=P2&0X1F|0Xc0; //位选
#define Y7C P2=P2&0X1F|0Xe0; //段选
#define Y0C P2=P2&0X1F|0X00;

typedef unsigned char u8;
typedef unsigned int u16;

code unsigned char Seg_Table[] =  
{ 
//数字
0xc0,  //0
0xf9,  //1
0xa4,  //2
0xb0,  //3
0x99,  //4
0x92,  //5
0x82,  //6
0xf8,  //7
0x80,  //8
0x90,  //9
//带小数点(高位减去8)
0x40,  //0
0x79,  //1
0x24,  //2
0x30,  //3
0x19,  //4
0x12,  //5
0x02,  //6
0x78,  //7
0x00,  //8
0x10,  //9
//字符
0xff,  //空 20
0xbf,  // -  21
//字母	
0x88,  //A	22
0x83,  //b	23
0xc6,  //C	24
0xa1,  //d	25
0x86,  //E	26
0x8e   //F	27
}; 

code unsigned char com[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 seg_index[8] = {0};

u16 temp=0;				//温度变量接收读取到的温度
u16 time_temp=0;	//温度的计时变量
bit state=0;

//外部调用读取温度函数
extern unsigned int read_temperature10();
extern unsigned int read_temperature100();

void init()
{
	Y4C;P0=0XFF;Y0C;
	Y5C;P0=0X00;Y0C;
	Y6C;P0=0XFF;Y0C;
	Y7C;P0=0XFF;Y0C;
}

void seg_display()
{
	static u8 num = 0;
	//关段选
	Y7C;P0=0XFF;Y0C;
	//选位选
	Y6C;P0=com[num];Y0C;
	//开段选
	Y7C;P0=Seg_Table[seg_index[num]];Y0C;
	
	if(++num==8) num=0;
}

void set_index(u8 d0,d1,d2,d3,d4,d5,d6,d7)
{
	seg_index[0]=d0;
	seg_index[1]=d1;
	seg_index[2]=d2;
	seg_index[3]=d3;

	seg_index[4]=d4;
	seg_index[5]=d5;
	seg_index[6]=d6;
	seg_index[7]=d7;	
}

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

	i = 117;
	j = 184;
	do
	{
		while (--j);
	} while (--i);
}

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初值
	TH1 = 0xD1;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
  ET1 = 1;    //使能定时器0中断
  EA = 1;
}

void tm1_isr() interrupt 3
{
	seg_display();
	time_temp++;
}

void key()
{
	P44=1; P42=0 ;P35=1 ;P34=1;
	if(P32==0){
		Delay10ms();
		if(P32==0) state=!state;
		while(!P32);
	}
}


main()
{
	init();
	Timer1Init();
	
	while(1)
	{
		key();
		
		//每500ms读取一次温度
		if(time_temp >= 500)
		{
			time_temp=0;
			if(!state)
			temp = read_temperature10();
			else if(state)
			temp = read_temperature100();			
		}
		//1位小数
		if(!state)
			set_index(20,20,20,20,temp/100,(temp%100/10)+10,temp%10,24);
		//2位小数
		else if(state)
			set_index(20,20,20,temp/1000,(temp%1000/100)+10,temp%100/10,temp%10,24);
	}
}

6、完整onewire.c代码

#include <STC15F2K60S2.H>

sbit DQ=P1^4;

//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

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

//增写:读取温度的函数(1位小数)
unsigned int read_temperature10()
{
	//注意:温度是int类型
	unsigned int temp;
	unsigned char teH,teL;
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0X44);
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0XBE);
	
	teL = Read_DS18B20();
	teH = Read_DS18B20();
	
	temp= teH<<8|teL;
	temp= temp*0.625;
	return temp;
}
//增写:读取温度的函数(2位小数)
unsigned int read_temperature100()
{
	//注意:温度是int类型
	unsigned int temp;
	unsigned char teH,teL;
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0X44);
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0XBE);
	
	teL = Read_DS18B20();
	teH = Read_DS18B20();
	
	temp= teH<<8|teL;
	temp= temp*6.25;
	return temp;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值