AVR溫度計(jì)DS18B20
#include
#include
#include
#include
unsigned char data_H, data_L,wendu;
unsigned int data_T;
void main(void)
{
LCD_init(); //lcd初始化
lcd_cls(); //清屏,光標(biāo)回位
while(1)
{
monobus_init(); //單總線復(fù)位
write_monobus(0xCC); //跳過(guò)ID碼匹配,適用于一個(gè)DS18B20
//可以使用8條語(yǔ)句代替上面的那條語(yǔ)句依次寫(xiě)入8個(gè)ID碼,這樣就是ID碼匹配了
//如果不知道18B20的ID碼,可以在總線上接入單個(gè)18B20
//然后參考下面的讀取語(yǔ)句,依次讀取18B20的8個(gè)ID碼
//記得使用CRC8校驗(yàn)一下是否正確
write_monobus(0x44); //啟動(dòng)溫度轉(zhuǎn)換
delay_ms(500); //等待轉(zhuǎn)換
monobus_init(); //單總線復(fù)位
write_monobus(0xCC); //跳過(guò)ID碼匹配
write_monobus(0xBE); //通知DS18B20,準(zhǔn)備讀數(shù)據(jù)
data_L=read_monobus(); //讀取第一個(gè)數(shù)據(jù)(溫度低字節(jié))
data_H=read_monobus(); //讀取第二個(gè)數(shù)據(jù)(溫度高字節(jié))
//可以繼續(xù)讀取第三個(gè)到第九個(gè)RAM數(shù)據(jù)
lcd_cls();
data_T=data_H*256+data_L; //合并后得到原始溫度數(shù)據(jù)
if(data_H>15) data_T=(~data_T+1)/16; else data_T/=16; //計(jì)算實(shí)際溫度
wendu=data_T;
lcd_gotoxy(16,3);
lcd_putsf("T = ",4); //顯示字符串,字符串是保存在Flash的
if(data_H>15) lcd_putchar('-');
lcd_put(wendu); //顯示溫度
lcd_putchar(' '); //空一個(gè)字符
lcd_write(2); //顯示C前面上標(biāo)的一個(gè)點(diǎn)
lcd_write(0); //空一小格
lcd_putchar('C');
delay_ms(250);
}
}
/*
如果溫度為正,則T的最高位的4位都為0,否則為1
負(fù)溫度的計(jì)算:原始數(shù)據(jù)取反、加1、再乘以 0.0625
正溫度的計(jì)算:原始數(shù)據(jù)乘以 0.0625
CVAVR自帶了18B20的庫(kù),如果大家不喜歡上面我寫(xiě)的函數(shù),也可以使用自帶的
*/
//**********************************************************************************
//**********************************************************************************
//monobus.h文件,用于操作DS18B20/DS2401等單總線器件
//假設(shè)軟件設(shè)計(jì)要求的時(shí)鐘頻率是4MHz
//實(shí)際上硬件工作在2-8MHz下也很正常,就是說(shuō),下面代碼的延時(shí)取值是很合適的
//CVAVR本身自帶單總線的庫(kù)1wire.h,如果大家不喜歡下面的代碼也可以使用它自帶的函數(shù)(請(qǐng)看幫助文檔)
#define monobus_1 DDRC.0=0 //設(shè)置單片機(jī)IO為輸入,由于總線存在上拉電阻,所以此時(shí)電平是1
#define monobus_0 DDRC.0=1 //設(shè)置 單片機(jī) IO為輸出,配合默認(rèn)的 PORTC.0=0 則輸出0電平
#define monobus_inPINC.0 //檢測(cè)總線(從機(jī))的電平狀態(tài)
void monobus_init(void) //復(fù)位,不檢測(cè)從機(jī)設(shè)備是否存在(只要沒(méi)有虛焊就肯定存在的)
{
monobus_0;
delay_us(480);
monobus_1;
delay_us(480);
}
void write_monobus(unsigned char data) //向單總線的從機(jī)寫(xiě)入數(shù)據(jù)(先寫(xiě)低位再寫(xiě)高位,與SPI相反)
{
unsigned char n=1;
while(n)
{
monobus_0;
delay_us(2); //拉低總線1-3us,通知從機(jī)準(zhǔn)備收發(fā)數(shù)據(jù)
if(data&n) monobus_1; else monobus_0; //向總線寫(xiě)數(shù)據(jù)的某一位(1或者0)
delay_us(75); //等待90us,保證從機(jī)有足夠的時(shí)間進(jìn)行采樣(24-210us)
monobus_1; //釋放總線
delay_us(2); //釋放總線時(shí)間要大于1us
n<<=1;
}
}
unsigned char read_monobus(void) //讀單總線的從機(jī)數(shù)據(jù)(先傳輸?shù)臀缓髠鬏敻呶?與SPI相反)
{
unsigned char data_18b20=0;
unsigned char n=1;
while(n)
{
monobus_0;
delay_us(2); //拉低總線1-3us,通知從機(jī)準(zhǔn)備收發(fā)數(shù)據(jù)
monobus_1; //釋放總線
delay_us(5); //從機(jī)在1-25us內(nèi)會(huì)向總線輸出數(shù)據(jù)的某一位(1或者0)
if(monobus_in) data_18b20+=n; //讀取總線數(shù)據(jù)
delay_us(55); //等待從機(jī)釋放總線
n<<=1;
}
return data_18b20;
}
//**********************************************************************************
//**********************************************************************************
/*************************************************************
使用者只需把這個(gè)nokia3310.h的文件復(fù)制到工程目錄即可
使用nokia3310庫(kù)函數(shù)時(shí),請(qǐng)先定義3310與MCU的連接
本例子3310LCD與 單片機(jī) 的連接如下
RESET PB1
D/C PB2
SDIN PB3
SCLK PB5
SCE GND
英文字庫(kù),5*8點(diǎn)陣,每一個(gè)字符占用5個(gè)字節(jié),共94個(gè)可顯示字符數(shù)據(jù)**/
#define RESET PORTB.1 //RESET=0時(shí),LCD復(fù)位
#define DC PORTB.2 //DC=0_指令,DC=1_數(shù)據(jù)
#define SDIN PORTB.3
#define SCLK PORTB.5