|
#include < reg51.h >
#include < intrins.h >
#define uchar unsigned char
#define uint unsigned int
//#define lcddata P0
#define lcddata P2
sbit LCDRS=P1^7; //液晶數(shù)據(jù)選擇命令端
sbit LCDRW=P1^6; //液晶讀寫命令端
sbit LCDEN=P1^5; //液晶使能端
//sbit LCDRS = P2^6 ; // 命令/數(shù)據(jù)選擇端 0為寫命令 1為寫數(shù)據(jù)
//sbit LCDRW = P2^5 ; // lcd讀寫端
//sbit LCDEN = P2^7 ; //lcd使能端
void write_com(uchar com);
void zdyzfxs();
unsigned char code mytab[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00} ;//lcd自定義字符
//sbit DQ = P3^7 ; //定義DS18B20端口DQ
sbit DQ = P1^0; //定義DS18B20端口DQ
bit presence; //ds18b20 DQ被拉低 信號(hào)0允許,1禁止
uint cc,cc2; //變量cc中保存讀出的溫度值
float cc1;
uchar flag; //flag為溫度值正負(fù)標(biāo)志位,“1”表示溫度為復(fù)制,“0”表示為正值//flag為溫度值正負(fù)標(biāo)志位,“1”表示溫度為復(fù)制,“0”表示為正值
void write_com(uchar com);
uchar code cdis0[ ] = "CHECKING...";
uchar code cdis1[ ] = " DS18B20 OK " ;
uchar code cdis5[ ] = "Temp: ";
uchar cdis2[ ] = "+00.00";
uchar code cdis3[ ] = " DS18B20 ERR0R " ;
uchar code cdis4[ ] = " PLEASE CHECK " ;
unsigned char data temp_data[2] = {0x00,0x00} ; //存儲(chǔ)16位溫度
/**********************************lcd1602********************************************/
//----------------------------------
void delaylcd(uint z)
{uchar x,y;
for(x=z;x>0;x--)
{for(y=110;y>0;y--);
}
}
/*lcd1602初始化 */
/**********************************/
void lcd_init(void)
{
LCDRW=0; //低電平為寫
LCDEN=0;
write_com(0x38); //使用8位數(shù)據(jù)開關(guān),顯示兩行,使用5*7字形
write_com(0x0c); //顯示器開,光標(biāo)關(guān),字符不閃爍 0x0e 光標(biāo)開
write_com(0x06); //字符不動(dòng),光標(biāo)自動(dòng)右移動(dòng)一位
write_com(0x01); //清屏
}
/*寫命令to lcd */
/**********************************/
void write_com(uchar com)//寫命令
{
LCDRW=0; //低電平為寫
LCDRS=0; //低電平為命令選擇
//LCDEN=1;
lcddata=com;
delaylcd(5);
LCDEN=1;
delaylcd(5);
LCDEN=0;
}
/*寫數(shù)據(jù)to lcd */
/**********************************/
void write_data(uchar date)
{
LCDRW=0; //低電平為寫
LCDRS=1; //高電平為數(shù)據(jù)選擇
//LCDEN=1;
lcddata=date;
delaylcd(5);
LCDEN=1;
delaylcd(5);
LCDEN=0;
}
/*設(shè)定顯示位置 */
/********************************/
void lcd_pos(uchar pos)
{ //第一行第幾列直接寫pos為幾,第二行pos從0x40開始
write_com(pos | 0x80) ; //數(shù)據(jù)指針=80+地址變量
}
/*自定義字符寫入CGRAM */
/*********************************/
void mywritetab()
{
unsigned char i ;
write_com(0x40) ; //寫CGRAM
for(i=0;i<8;i++)
{write_data(mytab[i]);}
}
/*******************************ds18b20*******************************************/
/*ms級(jí)別 */
void ddelay(uint ms)
{
uint i;
uchar j;
for(i=0;i<ms;i++)
for(j=0;j<250;j++)
{
_nop_(); //一個(gè)機(jī)器周期,1us
_nop_(); //適用于精度高的
_nop_();
_nop_();
}
}
/*us級(jí)延時(shí),延時(shí)時(shí)間約4+2*i*/
void Delayus(uchar i)
{
while(--i);
}
/*復(fù)位,每次讀寫之前都要進(jìn)行復(fù)位*/
/**********************************/
bit ow_reset(void)
{
DQ = 1 ; //DQ復(fù)位
Delayus(8) ; //稍做延時(shí)
DQ = 0; //拉低約600us
Delayus(150);
Delayus(150);
DQ = 1;//產(chǎn)生上升沿,延時(shí)約15~60us
Delayus(30);
if(DQ==0) {presence=0;}
else presence=1;
return(presence); //等待應(yīng)答信號(hào) 0允許,1禁止
}
/*讀取數(shù)據(jù)一位 */
//---------------------------------
bit Read_bit()
{
uint i = 0;
bit b = 0;
DQ = 0; //產(chǎn)生讀時(shí)隙
i++; //維持低電平至少1us
DQ = 1; //1us以上后拉高
Delayus(2); //延時(shí)8us,DO下降沿15內(nèi)ds18b20輸出的數(shù)據(jù)才有效
b = DQ; //讀取數(shù)據(jù)
Delayus(40); //每個(gè)讀時(shí)隙至少持續(xù)60us
return(b);
}
/*讀取一個(gè)字節(jié) */
//------------------------------------
uchar Read_byte()
{
uchar byte_read = 0;
uchar i, j;
for(i=0; i<8; i++)
{
j = Read_bit();
byte_read = (j<<i) | byte_read; //低位讀起
}
return(byte_read);
}
//-----------------------------------------
/*寫一個(gè)字節(jié) */
void Write_byte(uchar byte_to_write)
{
uchar i = 0;
uchar j = 0;
bit write_bit = 0;
for(j=0; j<8; j++)
{
write_bit = (byte_to_write & 0x01);
if(write_bit == 1) //寫1
{
DQ = 0; //產(chǎn)生寫時(shí)隙
Delayus(3); //延時(shí)15us
DQ = 1; //寫1
Delayus(40); //延時(shí),寫時(shí)隙不得低于60us
}
else
{
DQ = 0; //產(chǎn)生寫時(shí)隙
Delayus(50); //延時(shí),保持低約60us~120us
DQ = 1;
i++;
}
byte_to_write = byte_to_write >> 1;
}
}
//-----------------------------------
/*讀取溫度,啟動(dòng)溫度轉(zhuǎn)換*/
/*啟動(dòng)溫度轉(zhuǎn)換*/
void start_convert()
{
ow_reset(); // 發(fā)出復(fù)位脈沖,每次操作都從復(fù)位開始
ddelay(1);
Write_byte(0xcc); //skip room命令,跳過(guò)序列號(hào)命令字
Write_byte(0x44); //啟動(dòng)溫度轉(zhuǎn)換命令
}
/*讀取溫度值*/
void read_tempreture()
{
ow_reset(); // 發(fā)出復(fù)位脈沖,每次操作都從復(fù)位開始
ddelay(1);
Write_byte(0xcc); //skip room命令
Write_byte(0xbe); //讀取暫存器命令
temp_data[0] = Read_byte(); //存儲(chǔ)溫度低字節(jié)值 (整數(shù)部分低四位和小數(shù)部分) 先從低字節(jié)讀取
temp_data[1] = Read_byte(); //存儲(chǔ)溫度高字節(jié)值 (其中高五位為符號(hào)位)
}
//--------------------------------------
/* CHECKING...顯示 */
void lcd_display()
{
uchar m ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //設(shè)置顯示位置為第一行的第1個(gè)字符
m = 0 ;
while(cdis0[m] != '\0')
{ //顯示字符
write_data(cdis0[m]) ;
m++ ;
}
}
//--------------------------------------
/* DS18B20 OK 顯示菜單 */
void Ok_Menu ()
{
uchar m ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //設(shè)置顯示位置為第一行的第1個(gè)字符
m = 0 ;
while(cdis1[m] != '\0')
{ //顯示字符
write_data(cdis1[m]) ;
m++ ;
}
}
//-----------------------------------
/*DS18B20 ERR0R */
/*PLEASE CHECK 顯示 */
void Error_Menu ()
{
uchar m ;
lcd_init() ; //初始化LCD
lcd_pos(0) ; //設(shè)置顯示位置為第一行的第1個(gè)字符
m = 0 ;
while(cdis3[m] != '\0')
{
write_data(cdis3[m]) ; //顯示字符
m++ ;
}
lcd_pos(0x40) ; //設(shè)置顯示位置為第二行第1個(gè)字符
m = 0 ;
while(cdis4[m] != '\0')
{
write_data(cdis4[m]) ; //顯示字符
m++ ;
}
}
//------------------------------------
/*Temp: ℃顯示 */
void temp_c()
{
uchar m;
lcd_init() ;
lcd_pos(0);
m=0;
while(cdis5[m]!='\0')
{
write_data(cdis5[m]);
m++;
}
// write_data(0xDF); //°
zdyzfxs();lcd_pos(13);
write_data('C');
}
//-----------------------------------
/*自定義字符顯示 */
void zdyzfxs()
{
mywritetab();
lcd_pos(12);
write_data(0x00);
}
//------------------------------------
/*溫度顯示 */
void temperature_display()
{
uchar m;
flag=0;
while(1)
{
ddelay(2);
EA=0; //DS18B20讀寫數(shù)據(jù)按照嚴(yán)格的時(shí)序,最好不要被打斷,故把所有中斷關(guān)閉
start_convert(); //啟動(dòng)溫度轉(zhuǎn)換
ddelay(250);
read_tempreture(); //讀取溫度
EA=1;
cc=temp_data[1]*256.0+temp_data[0];
if(temp_data[1]>0xF8) {flag=1;cc=~cc+1;} else flag=0;
cc1=cc*0.0625;
cc2=cc1*100;
cdis2[1]=cc2/1000+0x30;
if(cdis2[1]==0x30)
{cdis2[1]=0x20;}
cdis2[2]=cc2/100%10+0x30;
cdis2[4]=cc2%100/10+0x30;
cdis2[5]=cc2%10+0x30;
if(flag==1)
cdis2[0]='-';
else
cdis2[0]='+';
lcd_pos(6) ; //設(shè)置顯示位置為第一行的第6個(gè)字符
m=0;
while(cdis2[m]!='\0')
{ //顯示字符
write_data(cdis2[m]) ;
m++;
}
}
}
//---------------------------------
/*主函數(shù) */
void main()
{
lcd_display();
ddelay(1000);
ow_reset();
if(presence==0)
{
Ok_Menu ();
ddelay(1000);
temp_c();zdyzfxs();
temperature_display();
}
else
{
Error_Menu ();
while(1)
{
ow_reset();
if(presence==0)
{
Ok_Menu ();
ddelay(1000);
temperature_display();
}
}
}
}
|
|