開發(fā)環(huán)境:
主機:Ubuntu12.04
開發(fā)板:RT5350
Openwrt:Openwrt15.05
1 硬件原理
下圖是我們溫度傳感器的接入引腳,3.3V 供電,io 口接 P07的 GP0( GPIO0 的簡稱 )。
DS18B20 數(shù)字溫度傳感器接線方便,封裝成后可應(yīng)用于多種場合,如管道式,螺紋式,磁鐵吸附式,不銹鋼封裝式,型號多種多樣,有 LTM8877,LTM8874 等等。主要根據(jù)應(yīng)用場合的不同而改變其外觀。封裝后的 DS18B20 可用于電纜溝測溫,高爐水循環(huán)測溫,鍋爐測溫,機房測溫,農(nóng)業(yè)大棚測溫,潔凈室測溫,彈藥庫測溫等各種非極限溫度場合。耐磨耐碰,體積小,使用方便,封裝形式多樣,適用于各種狹小空間設(shè)備數(shù)字測溫和控制領(lǐng)域。
2 單總線的概念
目前常用的微機與外設(shè)之間進(jìn)行數(shù)據(jù)傳輸?shù)拇锌偩€主要有 I2C 總線、 SPI 總線和 SCI總線。其中 I2C 總線以同步串行 2 線方式進(jìn)行通信(一條時鐘線,一條數(shù)據(jù)線) ,SPI 總線則以同步串行 3 線方式進(jìn)行通信(一條時鐘線,一條數(shù)據(jù)輸入線,一條數(shù)據(jù)輸出線),而 SCI 總線是以異步方式進(jìn)行通信(一條數(shù)據(jù)輸入線,一條數(shù)據(jù)輸出線) 。這些總線至少需要兩條或兩條以上的信號線。
1-wire , 即 單 線 總 線 , 又 叫 單 總 線 。 近 年 來 , 美 國 的 達(dá) 拉 斯 半 導(dǎo) 體 公 司(DALLASSEMICONDUCTOR) 推出了一項特有的單總線(1-Wire Bus)技術(shù)。該技術(shù)與上述總線不同,它采用單根信號線,既可傳輸時鐘,又能傳輸數(shù)據(jù),而且數(shù)據(jù)傳輸是雙向的,因而這種單總線技術(shù)具有線路簡單,硬件開銷少,成本低廉,便于總線擴展和維護(hù)等優(yōu)點。
3 ds18b20 相關(guān)時序
- 初始化(復(fù)位)時序圖:
(1) 先將數(shù)據(jù)線置高電平“ 1” 。
(2) 延時(該時間要求的不是很嚴(yán)格,但是盡可能的短一點)
(3) 數(shù)據(jù)線拉到低電平“ 0” 。
(4) 延時 750 微秒(該時間的時間范圍可以從 480 到 960 微秒) 。
(5) 數(shù)據(jù)線拉到高電平“ 1” 。
(6) 延時等待(如果初始化成功則在 15 到 60 微秒時間之內(nèi)產(chǎn)生一個由 DS18B20 所
返回的低電平“ 0” 。據(jù)該狀態(tài)可以來確定它的存在,但是應(yīng)注意不能無限的進(jìn)行等待,不然會使程序進(jìn)入死循環(huán),所以要進(jìn)行超時控制) 。
(7) 若 CPU 讀到了數(shù)據(jù)線上的低電平“ 0”后,還要做延時,其延時的時間從發(fā)出的高電平算起(第(5)步的時間算起)最少要 480 微秒。
(8) 將數(shù)據(jù)線再次拉高到高電平“ 1”后結(jié)束。
- 寫 ds18b20 時序圖:
(1) 數(shù)據(jù)線先置低電平“ 0” 。
(2) 延時確定的時間為 15 微秒。
(3) 按從低位到高位的順序發(fā)送字節(jié)(一次只發(fā)送一位) 。
(4) 延時時間為 45 微秒。
(5) 將數(shù)據(jù)線拉到高電平。
(6) 重復(fù)上(1)到(6)的操作直到所有的字節(jié)全部發(fā)送完為止。
(7) 最后將數(shù)據(jù)線拉高。
- 讀 ds18b20 時序圖:
(1)將數(shù)據(jù)線拉高“ 1” 。
(2)延時 2 微秒。
(3)將數(shù)據(jù)線拉低“ 0” 。
(4)延時 3 微秒。
(5)將數(shù)據(jù)線拉高“ 1” 。
(6)延時 5 微秒。
(7)讀數(shù)據(jù)線的狀態(tài)得到 1 個狀態(tài)位,并進(jìn)行數(shù)據(jù)處理。
(8)延時 60 微秒。
4 驅(qū)動程序
關(guān)于字符設(shè)備驅(qū)動程序的使用,我們可以參照點亮 led 燈的那個實驗,這里只給出跟ds18b20 密切相關(guān)的驅(qū)動程序,詳細(xì)的程序請查看我們的驅(qū)動文件!
//配置連接溫度傳感器的引腳
#define DS18B20_L *GPIO21_0_DATA &= ~(1< 0) //低電平
#define DS18B20_H *GPIO21_0_DATA |= (1< 0) //高電平
#define DS18B20_OUT *GPIO21_0_DIR |= (1< 0) //輸出
#define DS18B20_IN *GPIO21_0_DIR &= ~(1< 0) //輸入
#define DS18B20_STA *GPIO21_0_DATA & 0x01
//寄存器定義
volatile unsigned long *GPIO21_0_DIR;
volatile unsigned long *GPIO21_0_DATA;
/**************** 基本定義 **********************/
//初始化函數(shù)必要資源定義
//用于初始化函數(shù)當(dāng)中
//device number;
dev_t dev_num;
//struct dev
struct cdev ds18b20_cdev;
//auto "mknode /dev/ds18b20 c dev_num minor_num"
struct class *ds18b20_class = NULL;
struct device *ds18b20_device = NULL;
/******************** ds18b20有關(guān)的函數(shù) ****************************/
//復(fù)位ds18b20傳感器
static unsigned char ds18b20_reset(void)
{
unsigned char ret = 0;
unsigned char count = 0;
DS18B20_OUT;
DS18B20_H;
udelay(100);
DS18B20_L;
udelay(600);
DS18B20_H;
udelay(45);
DS18B20_IN;
do
{
ret = DS18B20_STA;
udelay(1);
count++;
}
while(ret != 0 && count< 50);
DS18B20_OUT;
udelay(400);
DS18B20_H;
return ret;
}
//從ds18b20讀取一個字節(jié)
static unsigned char read_byte(void)
{
unsigned char i,byte=0;
DS18B20_OUT;
DS18B20_H;
udelay(100);
for(i = 0; i< 8; i++)
{
byte > >= 1;
DS18B20_L;
udelay(4);
DS18B20_H;
udelay(2);
if(DS18B20_STA == 1)
byte |= 0x80;
udelay(10);
}
return byte;
}
//向ds18b20寫入一個字節(jié)
static unsigned char write_byte(unsigned char byte)
{
unsigned char i;
DS18B20_OUT;
DS18B20_H;
udelay(100);
for(i = 0; i< 8; i++)
{
DS18B20_L;
if( byte & 0x01 )
DS18B20_H;
else
DS18B20_L;
udelay(40);
DS18B20_H;
byte > >= 1;
}
udelay(10);
}
//從ds18b20中讀出溫度數(shù)據(jù)
static unsigned int read_temp(void)
{
unsigned int t = 0 , l = 0;
if(ds18b20_reset())
{
printk("step1,reset_ds18b20 error!n");
return 0;
}
write_byte(0xcc);
write_byte(0x44);
udelay(4);
if(ds18b20_reset())
{
printk("step2,reset_ds18b20 error!n");
return 0;
}
write_byte(0xcc);
write_byte(0xbe);
l = read_byte();
t = read_byte();
t < <= 8;
t += l;
return t;
}
/**********************************************************************/
/**************** 結(jié)構(gòu)體 file_operations 成員函數(shù) *****************/
//open
static int ds18b20_open(struct inode *inode, struct file *file)
{
printk("ds18b20 drive open...n");
DS18B20_OUT; //初始化該引腳為輸出;
return 0;
}
//close
static int ds18b20_close(struct inode *inode , struct file *file)
{
return 0;
}
//read
static ssize_t ds18b20_read(struct file *file, char __user *buffer,
size_t len, loff_t *pos)
{
unsigned int temp;
printk("ds18b20 drive read...n");
temp = read_temp();
copy_to_user(buffer, &temp, 4);
return 4;
}
/***************** 結(jié)構(gòu)體: file_operations ************************/
//struct
static const struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.open = ds18b20_open,
.release = ds18b20_close,
.read = ds18b20_read,
};
/************* functions: init , exit*******************/
//條件值變量,用于指示資源是否正常使用
unsigned char init_flag = 0;
unsigned char add_code_flag = 0;
//init
static __init int ds18b20_init(void)
{
int ret_v = 0;
printk("ds18b20 drive init...n");
//函數(shù)alloc_chrdev_region主要參數(shù)說明:
//參數(shù)2: 次設(shè)備號
//參數(shù)3: 創(chuàng)建多少個設(shè)備
if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"ds18b20") ) < 0 )
{
goto dev_reg_error;
}
init_flag = 1; //標(biāo)示設(shè)備創(chuàng)建成功;
printk("The drive info of ds18b20:nmajor: %dnminor: %dn",
MAJOR(dev_num),MINOR(dev_num));
cdev_init(&ds18b20_cdev,&ds18b20_fops);
if( (ret_v = cdev_add(&ds18b20_cdev,dev_num,1)) != 0 )
{
goto cdev_add_error;
}
ds18b20_class = class_create(THIS_MODULE,"ds18b20");
if( IS_ERR(ds18b20_class) )
{
goto class_c_error;
}
ds18b20_device = device_create(ds18b20_class,NULL,dev_num,NULL,"ds18b20");
if( IS_ERR(ds18b20_device) )
{
goto device_c_error;
}
printk("auto mknod success!n");
//------------ 請在此添加您的初始化程序 --------------//
GPIO21_0_DATA = (volatile unsigned long *)ioremap(0x10000620, 4);
GPIO21_0_DIR = (volatile unsigned long *)ioremap(0x10000624, 4);
//如果需要做錯誤處理,請:goto ds18b20_error;
add_code_flag = 1;
//---------------------- END ---------------------------//
goto init_success;
dev_reg_error:
printk("alloc_chrdev_region failedn");
return ret_v;
cdev_add_error:
printk("cdev_add failedn");
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return ret_v;
class_c_error:
printk("class_create failedn");
cdev_del(&ds18b20_cdev);
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return PTR_ERR(ds18b20_class);
device_c_error:
printk("device_create failedn");
cdev_del(&ds18b20_cdev);
unregister_chrdev_region(dev_num, 1);
class_destroy(ds18b20_class);
init_flag = 0;
return PTR_ERR(ds18b20_device);
//------------------ 請在此添加您的錯誤處理內(nèi)容 ----------------//
ds18b20_error:
add_code_flag = 0;
return -1;
//-------------------- END -------------------//
init_success:
printk("ds18b20 init success!n");
return 0;
}
//exit
static __exit void ds18b20_exit(void)
{
printk("ds18b20 drive exit...n");
if(add_code_flag == 1)
{
//---------- 請在這里釋放您的程序占有的資源 ---------//
printk("free your resources...n");
iounmap(GPIO21_0_DATA);
iounmap(GPIO21_0_DIR);
printk("free finishn");
//---------------------- END -------------------//
}
if(init_flag == 1)
{
//釋放初始化使用到的資源;
cdev_del(&ds18b20_cdev);
unregister_chrdev_region(dev_num, 1);
device_unregister(ds18b20_device);
class_destroy(ds18b20_class);
}
}
/**************** module operations**********************/
//module loading
module_init(ds18b20_init);
module_exit(ds18b20_exit);
//some infomation
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("from Jafy");
MODULE_DESCRIPTION("ds18b20 drive");
5 應(yīng)用程序
int main(int argc, char **argv)
{
int fd;
float t;
unsigned int tmp = 0;
//打開溫度傳感器驅(qū)動模塊
fd = open("/dev/ds18b20", O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("can't open!n");
return -1;
}
read(fd, &tmp, sizeof(tmp));
t = tmp * 0.0625;
printf("the current temperature is %fn",t);
close(fd);
return 0;
}
編譯模塊驅(qū)動,不熟悉的朋友可看LED驅(qū)動相關(guān)。
$make package/kernel/ds18b20/compile V=99
編譯模塊驅(qū)動和應(yīng)用程序
$make package/ds18b20_app/compile V=99
$make package/ds18b20_app/install V=99
$make package/index V=99
復(fù)制文件傳給開發(fā)板測試
6 實驗結(jié)果
審核編輯:湯梓紅
-
溫度傳感器
+關(guān)注
關(guān)注
48文章
2912瀏覽量
155885 -
DS18B20
+關(guān)注
關(guān)注
10文章
778瀏覽量
80694 -
引腳
+關(guān)注
關(guān)注
16文章
1181瀏覽量
50274 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
4943瀏覽量
97188 -
OpenWrt
+關(guān)注
關(guān)注
10文章
127瀏覽量
39266
發(fā)布評論請先 登錄
相關(guān)推薦
評論