PIC单片机(PIC16F877A)DS18B20温度传感器驱动程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhoukouguren/article/details/7703043
#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
#define rs_h (PORTC|=0x01)
#define rs_l (PORTC&=0xfe)
#define rs_o (TRISC&=0xfe)
#define rw_h (PORTC|=0x02)
#define rw_l (PORTC&=0xfd)
#define rw_o (TRISC&=0xfd)
#define en_h (PORTC|=0x04) 
#define en_l (PORTC&=0xfb)
#define en_o (TRISC&=0xfb)
#define temp_h (PORTC|=0x08) 
#define temp_l (PORTC&=0xf7) 
#define temp_o (TRISC&=0xf7)
#define temp_i (TRISC|=0x08)
#define led_o (TRISC&=0xef)
#define led_l (PORTC&=0xef)
#define led_h (PORTC|=0x10)
#define LCD PORTB
uchar dat1,dat2;//保存读出的温度z
unsigned long int dat;
void delayms(uint x) //4M晶振下,延时1ms
{
	uint y,z;
	for(y=x;y>0;y--)
		for(z=110;z>0;z--);
}
void Ds18b20_reset(void)//DS18B20初始化
{
	uint count;
	uchar i,flag=1;
	temp_o;
	temp_l;
	for(count=60;count>0;count--);//延时480us
	temp_i;
	while(flag)
	{
		if(RC3)
			flag=1;
		else
			flag=0;	
	}
	led_o;
	led_l;//开指示灯
	for(count=60;count>0;count--);//延时480us
}
void Ds18b20_write(uchar datt)//向DS18B20写一个字节
{
	uchar count;
	uchar i;
	temp_o;
	for(i=8;i>0;i--)
	{
		temp_o;
		temp_l;
		for(count=1;count>0;count--);
		if(datt&0x01==0x01)
			temp_i;
		else
		{	
			temp_o;
			temp_l;
		}
		for(count=23;count>0;count--);//延时60us
		temp_i;
		for(count=1;count>0;count--);
		datt>>=1;	
	}	
}
uchar Ds18b20_read(void) //从DS18B20读一个字节
{
	uchar i,datt;
	uchar count;
	for(i=8;i>0;i--)
	{
		datt>>=1;
		temp_o;
		temp_l;
		for(count=1;count>0;count--);
		temp_i;//改为输入方向时,上拉电阻把数据线拉高,释放总线,此语句必须有,参考datasheet的P15
		for(count=1;count>0;count--);
		if(RC3)
			datt|=0x80;
		for(count=23;count>0;count--);//延时60us	
	}
	return datt;
}
void lcd_com(uchar com)//向LCD1602写命令
{
 	rs_o;
	rw_o;
	en_o;
	TRISB=0x00;//配置RB为输出方向
	rs_l;	
	rw_l;
	LCD=com;
	delayms(1);
	en_h;
	delayms(1);	
	en_l;
	delayms(1);		
}
void lcd_dat(uchar dat)//向LCD1602写数据
{
 	rs_o;
	rw_o;
	TRISB=0x00;//配置RB为输出方向
	en_o;
	rs_h;	
	rw_l;
	LCD=dat;
	delayms(1);
	en_h;
	delayms(1);
	en_l;
	delayms(1);	
}
void lcd_write(uchar c,uchar r,uchar dat)//向LCD1602指定行、指定列、写数据
{
	lcd_com(0x80+0x40*c+r);
	lcd_dat(dat);
	delayms(1);
}
void lcd_init(void)//LCD1602初始化,初始化后第一行显示temperature:,第二行显示.C
{
	lcd_com(0x38);
	lcd_com(0x0c);
	lcd_com(0x06);
	lcd_write(0,2,0x54);
	lcd_write(0,3,0x65);
	lcd_write(0,4,0x6d);
	lcd_write(0,5,0x70);
	lcd_write(0,6,0x65);
	lcd_write(0,7,0x72);
	lcd_write(0,8,0x61);
	lcd_write(0,9,0x74);
	lcd_write(0,10,0x75);
	lcd_write(0,11,0x72);
	lcd_write(0,12,0x65);
	lcd_write(0,13,0x3a);
	lcd_write(1,11,0xdf);
	lcd_write(1,12,0x43);
}
void show(void)//把温度值送LCD1602显示
{
	uchar flag;
	uchar t[4];
	uint temp;
	if(dat2>=240)
	{
		dat= (~(dat2*256+dat1)+1)*(0.0625*10);//取反加一,保留一位小数
		flag=1;
	}
	else
	{
		dat=(dat2*256+dat1)*(0.0625*10);
		flag=0;
	};
	temp=dat%10;
	t[0]=(0x30+temp);
	temp=dat%100;
	temp=temp/10;
	t[1]=(0x30+temp);
	temp=dat%1000;
	temp=temp/100;
	t[2]=(0x30+temp);
	temp=dat/1000;
	t[3]=(0x30+temp);
	if(flag==1)//负温度显示
	{
		lcd_write(1,10,t[0]);
		lcd_write(1,9,0xa5);
		lcd_write(1,8,t[1]);
		lcd_write(1,7,t[2]);
		lcd_write(1,6,t[3]);
		lcd_write(1,5,0x2d);
	}
	if(flag==0)//正温度显示
	{
		lcd_write(1,10,t[0]);
		lcd_write(1,9,0xa5);
		lcd_write(1,8,t[1]);
		lcd_write(1,7,t[2]);
		lcd_write(1,6,t[3]);
		lcd_write(1,5,0x20);//显示空格,刷掉负号
	}
}
void main(void)
{
	lcd_init();
	while(1)
	{
		Ds18b20_reset();
		Ds18b20_write(0xcc);
		Ds18b20_write(0x44);//发送温度转换命令
		delayms(1000);//延时1s,等待温度转换完成
		Ds18b20_reset();
		Ds18b20_write(0xcc);
		Ds18b20_write(0xbe);//发送读温度寄存器命令
		dat1=Ds18b20_read();
		dat2=Ds18b20_read();
		show();
		led_h;//关指示灯
		delayms(2000);
	}
}
//调试总结:
//某IO口8位未全使用时,对整个IO口读取进行位运算无效


没有更多推荐了,返回首页