#include
#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口读取进行位运算无效
上一篇:PIC单片机(PIC16F877A)外部中断程序
下一篇:PIC单片机(PIC16F877A)DS1302芯片程序
推荐阅读最新更新时间:2024-03-16 16:06