專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享
從全面的產(chǎn)品導(dǎo)入到強大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!
深圳市英銳恩科技有限公司:臺灣麥肯單片機(Micon MDT單片機)亞太地區(qū)A級代理商
QLdsPIC3]DS18B20[C30+dsPIC30F6014A]
//實驗?zāi)康模菏煜S18B20的使用
//轉(zhuǎn)換結(jié)果送LCD1602顯示(其中整數(shù)部分3位,小數(shù)點部分4位,小數(shù)點1位)
//每隔0.1S轉(zhuǎn)換一次。
//硬件要求:把DS18B20插在18B20插座上
// 跳線J5接通
// 跳線J18全部接通
#include //dsPIC30F6014標(biāo)準頭文件
_FOSC(0x0ffe5); //XT振蕩,4倍頻晶振.
_FWDT(WDT_OFF); //關(guān)閉看門狗定時器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉電復(fù)位禁止,MCLR復(fù)位使能。
_FGS(CODE_PROT_OFF); //代碼保護禁止
#define uch unsigned char //給unsigned char起別名 uch
# define DQ PORTFbits.RF6 //定義18B20數(shù)據(jù)端口
# define DQ_DIR TRISFbits.TRISF6 //定義18B20D口方向寄存器
# define DQ_HIGH() DQ_DIR =1 //設(shè)置數(shù)據(jù)口為輸入
# define DQ_LOW() DQ = 0; DQ_DIR = 0 //設(shè)置數(shù)據(jù)口為輸出
#define rs LATBbits.LATB4 //定義LCD控制位(注意這里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e LATBbits.LATB6
unsigned char __attribute__((address(0x900))) TLV; //采集到的溫度高8位
unsigned char __attribute__((address(0x902))) THV; //采集到的溫度低8位
unsigned char __attribute__((address(0x904))) TZ; //轉(zhuǎn)換后的溫度值整數(shù)部分
unsigned char __attribute__((address(0x906))) TX; //轉(zhuǎn)換后的溫度值小數(shù)部分
unsigned int __attribute__((address(0x908))) wd; //轉(zhuǎn)換后的溫度值BCD碼形式
unsigned char __attribute__((address(0x9a0))) loop; //LCD顯示次數(shù)計數(shù)器
unsigned char __attribute__((address(0x930))) result[8]={0,0,0,'.',0,0,0,0};
//****************延時函數(shù)**************************************
//延時函數(shù)(延時時間為(2+x)us)
void delay( char x)
{
unsigned char i;
for(i=0;i<x;i++);
}
//*****************寫一個字節(jié)數(shù)據(jù)函數(shù)***************************
//在電平發(fā)生改變后需要插入一段延時時間,否則LCD反應(yīng)不過來。
void write(unsigned char x)
{
PORTD=x; //待顯示數(shù)據(jù)送PORTD口
delay(98);
rs=1; //該字節(jié)數(shù)據(jù)為數(shù)據(jù),而不是命令
delay(98);
rw=0; //此次操作為寫,而不是讀
delay(98);
e=0; //拉低使能信號
delay(98); //保持使能信號為低一段時間
e=1; //拉高使能信號,建立LCD操作所需要的上升沿
delay(98);
}
//******************LCD顯示設(shè)置函數(shù)*****************************
//在電平發(fā)生改變后需要插入一段延時時間,否則LCD反應(yīng)不過來。
void lcd_enable()
{
delay(98);
rs=0; //該字節(jié)數(shù)據(jù)為命令,而不是數(shù)據(jù)
delay(98);
rw=0; //此次操作為寫,而不是讀
delay(98);
e=0; //拉低使能信號
delay(98); //保持使能信號為低一段時間
e=1; //拉高使能信號,建立LCD操作所需要的上升沿
delay(98);
}
//------------------------------------------------
//系統(tǒng)初始化函數(shù)
void init()
{
TRISF=0X0000; //先設(shè)置18B20口方向為輸出
TRISB=0X0000; //設(shè)置B口方向為輸出
TRISD=0X0000; //設(shè)置D口方向為輸出
IFS0bits.T1IF=0; //先清除定時器中斷標(biāo)志位
PR1=0XFFFF; //周期定最大
T1CON=0X0020; //分頻比為1:64
}
//*******************LCD初始化函數(shù)*******************************
void lcd_init()
{
PORTD=0X1; //清除顯示
lcd_enable();
PORTD=0X38; //8位2行5*7點陣
lcd_enable();
PORTD=0X0e; //顯示開,光標(biāo)開,閃爍
lcd_enable();
PORTD=0X06; //文字不動,光標(biāo)右移
lcd_enable();
}
//*********************LCD顯示函數(shù)*******************************
void display()
{
PORTD=0X84; //顯示首地址
lcd_enable();
for(loop=0;loop<8;loop++) //共顯示8位
{
write(result[loop]); //查表并送顯示
delay(100); //插入一定延時
}
}
//******************復(fù)位DS18B20函數(shù)*****************************
//主控制器(dsPIC30F6014A)先拉低總線480us,然后釋放總線回到高電平
//18B20檢測到上升沿后先等待15-60us,然后拉低總線做為復(fù)位的應(yīng)答信號
//主控制器釋放總線后到復(fù)位結(jié)束時間應(yīng)為480US
reset(void)
{
char presence=1;
while(presence)
{
DQ_LOW() ; //主機拉至低電平
delay(100);
delay(100);
delay(100);
delay(100);
delay(78); //以上5條共延時480us
DQ_HIGH(); //釋放總線等電阻拉高總線,并保持15~60us
delay(38); //延時40us
if(DQ==1) presence=1; //沒有接收到應(yīng)答信號,繼續(xù)復(fù)位
else presence=0; //接收到應(yīng)答信號
delay(100);
delay(100);
delay(100);
delay(100);
delay(38); //以上5條共延時440us
}
}
//****************寫18b20寫字節(jié)函數(shù)*****************************
//主控制器寫數(shù)據(jù)1:先把總線拉低,然后在15us內(nèi)釋放總線
//主控制器寫數(shù)據(jù)0:把總線拉低至少60us
//寫一位數(shù)據(jù)至少需要60us
//兩位數(shù)據(jù)之間至少延時1us
void write_byte(uch val)
{
uch i;
uch temp;
for(i=8;i>0;i--)
{
temp=val&0x01; //最低位移出
DQ_LOW();
delay(3); //保持拉低5us
if(temp==1) DQ_HIGH(); //如果寫1,拉高電平
delay(58); //延時60us
DQ_HIGH();
delay(1); //在兩位之間插入3us延時
val=val>>1; //右移一位
}
}
//****************18b20讀字節(jié)函數(shù)********************************
//主控制器把總線拉低至少1US,然后釋放
//主控制器讀數(shù)據(jù)1:18B20保持總線狀態(tài)不變
//主控制器讀數(shù)據(jù)0:18B20檢測到總線拉低后繼續(xù)拉低總線至少60ms
//主控制器在拉低總線后的15us讀取總線上的狀態(tài)
//讀取1位數(shù)據(jù)至少需要60us
uch read_byte(void)
{
uch i;
uch value=0; //讀出溫度
for(i=8;i>0;i--)
{
value>>=1;
DQ_LOW();
delay(1); //保持總線拉低3us
DQ_HIGH(); //拉至高電平
delay(5); //釋放總線后保持7us再讀取數(shù)據(jù)
if(DQ) value|=0x80;
delay(48); //延時50us,保證每1位的60us延時
}
return(value);
}
//-------------------------------------------------
//啟動溫度轉(zhuǎn)換函數(shù)
void get_temp()
{
int i;
DQ_HIGH();
reset(); //復(fù)位等待從機應(yīng)答
write_byte(0XCC); //忽略ROM匹配
write_byte(0X44); //發(fā)送溫度轉(zhuǎn)化命令
for(i=0;i<8;i++)
{
delay(98); //確保溫度轉(zhuǎn)換完成所需要的時間
}
reset(); //再次復(fù)位,等待從機應(yīng)答
write_byte(0XCC); //忽略ROM匹配
write_byte(0XBE); //發(fā)送讀溫度命令
TLV=read_byte(); //讀出溫度低8
THV=read_byte(); //讀出溫度高8位
DQ_HIGH(); //釋放總線
TZ=(TLV>>4)|(THV<<4)&0X3f; //溫度整數(shù)部分
TX=TLV<<4; //溫度小數(shù)部分
result[0]=(TZ/100)+0x30; //整數(shù)百位
result[1]=((TZ%100)/10)+0X30; //整數(shù)十位
result[2]=((TZ%100)%10)+0X30; //整數(shù)部分個位
wd=0;
if (TX & 0x80) wd=wd+5000;
if (TX & 0x40) wd=wd+2500;
if (TX & 0x20) wd=wd+1250;
if (TX & 0x10) wd=wd+625; //以上4條指令把小數(shù)部分轉(zhuǎn)換為BCD碼形式
result[4]=(wd/1000)+0x30; //十分位
result[5]=((wd%1000)/100)+0x30; //百分位
result[6]=((wd%100)/10)+0x30; //千分位
result[7]=(wd%10)+0x30; //萬分位
}
//--------------------------------------------------
//主豬函數(shù)
int main(void)
{
init(); //調(diào)用系統(tǒng)初始化函數(shù)
lcd_init(); //LCD初始化函數(shù)
while(1)
{
TMR1=0XC2F6; //定時器初值
T1CONbits.TON=1; //啟動定時器
while(!IFS0bits.T1IF); //等待0.1s定時到
IFS0bits.T1IF=0;
get_temp(); //調(diào)用溫度轉(zhuǎn)換函數(shù)
display(); //調(diào)用結(jié)果顯示函數(shù)
}
}