DS18B20驅(qū)動(dòng)編寫–雜項(xiàng)設(shè)備框架注冊(cè)
設(shè)備驅(qū)動(dòng)最通俗的解釋就是“驅(qū)使硬件設(shè)備行動(dòng)”。驅(qū)動(dòng)與底層硬件直接打交道,按照硬件設(shè)備的具體工作方式,讀寫設(shè)備的寄存器,完成設(shè)備的輪詢、中斷處理、DMA通信,進(jìn)行物理內(nèi)存向虛擬內(nèi)存的映射等,最終讓通信設(shè)備能收發(fā)數(shù)據(jù),讓顯示設(shè)備能顯示文字和畫面,讓存儲(chǔ)設(shè)備能記錄文件和數(shù)據(jù)。
驅(qū)動(dòng)程序是應(yīng)用層和硬件層的連接橋梁,應(yīng)用層只管完成應(yīng)用邏輯開發(fā)和界面設(shè)計(jì),驅(qū)動(dòng)層則處理硬件配置,實(shí)現(xiàn)應(yīng)用層相關(guān)接口函數(shù)。
雜項(xiàng)設(shè)備:字符設(shè)備類的一種,雜項(xiàng)設(shè)備主設(shè)備號(hào)為10。
1.DS18B20簡(jiǎn)介
DS18B20是Dallas半導(dǎo)體公司生產(chǎn)的數(shù)字溫度傳感器,是世界上第一片支持"一線總線"接口的溫度傳感器。測(cè)量溫度范圍為-55℃ ~ +125℃,精度為±0.5℃。分辨率為9 ~ 12位。支持3V ~ 5.5V輸入電壓??垢蓴_能力強(qiáng)。
每一個(gè)DSl820包括一個(gè)唯一的64位長(zhǎng)的序號(hào),該序號(hào)值存放在 DSl820 內(nèi)部的 ROM(只讀存貯器)中。開始8位是產(chǎn)品類型編碼(DSl820 編碼均為 10H) ,接著的 48位是每個(gè)器件唯一的序號(hào),最后 8 位是前面 56 位的CRC(循環(huán)冗余校驗(yàn))碼。
引腳 | 說明 |
GND | 地 |
DQ | 數(shù)字信號(hào)腳 |
VDD | 電源腳3V~5.5V |
??DS18B20以9位數(shù)字量形式反應(yīng)器件的溫度值。
??DS18B20采用單總線通訊,與CPU之間只需要DQ腳相連,再和CPU之間共地即可。每一個(gè)DS18B20都有唯一的64位光刻ROM,因此可以在一根數(shù)據(jù)線上接多個(gè)DS18B20模塊。
- 單總線協(xié)議特性
- 總線協(xié)議:一個(gè)數(shù)據(jù)線可掛載多個(gè)設(shè)備(DS18B20通過64位光刻ROM區(qū)分設(shè)備);
- 半雙工通訊:數(shù)據(jù)線上同一時(shí)間只能發(fā)送或者接收數(shù)據(jù);
2.DS18B20驅(qū)動(dòng)時(shí)序
2.1 發(fā)送復(fù)位脈沖和檢測(cè)存在信號(hào)
??DS18B20初始化過程首先需要發(fā)送復(fù)位脈沖:至少480us的低電平信號(hào)。接下來釋放總線,DS18B20開始返回存在信號(hào):60~240us的低電平。最后釋放總線,模塊初始化完成。
/*發(fā)送復(fù)位信號(hào),檢測(cè)存在脈沖*/
static u8 ds18b20_CheckRst(void)
{
u8 time=0;
DS18B20_OUT_MODE();/*輸出模式*/
DS18B20_OUT(0);/*總線拉低*/
udelay(600);/*至少480us低電平*/
DS18B20_OUT(1);/*釋放總線,恢復(fù)為空閑電平*/
udelay(15);
DS18B20_INPUT_MODE();/*輸入模式*/
while(DS18B20_IN)
{
time++;
udelay(1);
if(time>=100)return 1;/*等待存在脈沖失敗*/
}
time=0;
while(!DS18B20_IN)
{
time++;
udelay(1);
if(time>=250)return 2;//模塊出錯(cuò)
}
return 0;
}
2.2 寫一位數(shù)據(jù)時(shí)序
??要實(shí)現(xiàn)寫一字節(jié)數(shù)據(jù),則首先要實(shí)現(xiàn)的是寫一位數(shù)據(jù)時(shí)序。分為寫1和寫0。首先是總線拉低,產(chǎn)生寫間隙(至少1us)。接著往數(shù)據(jù)線DQ上寫入0或者1,周期時(shí)間為60us,最后釋放總線(總線拉高,至少1us),至此,寫數(shù)據(jù)完成。
DS18B20_OUT_MODE();/*輸出模式*/
DS18B20_OUT(0);//總線拉低,產(chǎn)生寫間隙時(shí)間
udelay(2);
if(dat&0x01)DS18B20_OUT(1);
else DS18B20_OUT(0);
udelay(60);//寫周期時(shí)間
DS18B20_OUT(1);//釋放總線
udelay(2);
dat>>=1;//繼續(xù)發(fā)送下一位數(shù)據(jù)
2.3 讀一位數(shù)據(jù)時(shí)序
??讀數(shù)據(jù)首先需要主機(jī)產(chǎn)生讀間隙:總線拉低,至少1us的低電平信號(hào)。接著釋放總線,在15us內(nèi)進(jìn)行數(shù)據(jù)讀取,讀數(shù)據(jù)周期時(shí)間為60us,最后釋放總線:總線拉高,至少1us時(shí)間。 至此,讀一位數(shù)據(jù)完成。
DS18B20_OUT_MODE();/*輸出模式*/
DS18B20_OUT(0);//總線拉低,產(chǎn)生讀間隙時(shí)間
udelay(2);
DS18B20_INPUT_MODE();//配置為輸入模式
udelay(12);//等待數(shù)據(jù)到來
data>>=1;
if(DS18B20_IN)data|=0x80;
udelay(50);//讀數(shù)據(jù)時(shí)間
DS18B20_OUT(1);//恢復(fù)總線為空閑電平
udelay(2);
3.DS18B20相關(guān)命令
- 跳轉(zhuǎn)指令0xCC
這條指令允許控制器不需要提供64位光刻ROM就使用存儲(chǔ)器操作命令,在總線上僅有一個(gè)DS18B20時(shí)使用,若有多個(gè)則會(huì)產(chǎn)生沖突。
- 啟動(dòng)一次溫度轉(zhuǎn)換0x44
此命令完成一次溫度轉(zhuǎn)換。執(zhí)行此命令后,DS18B20保持等待狀態(tài)。若總線在這條命令發(fā)送后跟著讀間隙,而DS18B20正處于數(shù)據(jù)轉(zhuǎn)換,則會(huì)輸出一個(gè)0,若溫度轉(zhuǎn)換完成,則會(huì)輸出1。若使用寄生電源,總線必須在這條命令發(fā)完后拉高總線,保存500ms。
- 讀取一次數(shù)據(jù)0xBE
此命令用于讀取暫存器中的內(nèi)容,可連續(xù)讀取9個(gè)字節(jié)數(shù)據(jù)。若只想讀取溫度數(shù)據(jù),則只需要讀取前兩個(gè)字節(jié)即可。
- 讀ROM 0x33
此命令可以讀取DS18B20的64位光刻ROM數(shù)據(jù),此命令僅能在總線上一個(gè)設(shè)備的時(shí)候使用。
- 匹配ROM 0x55
此命令可以實(shí)現(xiàn)和DS18B20的ROM進(jìn)行匹配,只有和DS1820的64位光刻ROM完全匹配才能響應(yīng)后面存儲(chǔ)器命令。此命令用于當(dāng)總線上不止一個(gè)設(shè)備時(shí)使用。
- 搜索ROM 0xF0
當(dāng)系統(tǒng)第一次啟動(dòng)時(shí),無法確認(rèn)總線上有多少個(gè)設(shè)備或者該設(shè)備的光刻ROM,搜索光刻ROM可以讓控制器通過排除法識(shí)別總線上的所有設(shè)備的64位光刻ROM。
4.DS18B20采集一次溫度步驟
??采用外部電源供電,且總線上僅有一個(gè)DS18B20模塊。
5.編寫DS18B20驅(qū)動(dòng),通過雜項(xiàng)設(shè)備注冊(cè)
- 開發(fā)平臺(tái)
開發(fā)平臺(tái):Ubuntu18.04
編譯器:arm-linux-gcc
硬件平臺(tái):tiny4412基于Cortex-A9 4核1.5GHZ
開發(fā)板內(nèi)核:Linux3.5
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static unsigned int ds18b20_gpio=EXYNOS4_GPB(4);//GPB_4
#define DS18B20_OUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT)/*輸出模式*/
#define DS18B20_INPUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_INPUT)/*輸入模式*/
#define DS18B20_OUT(x) gpio_set_value(ds18b20_gpio,(x))
#define DS18B20_IN gpio_get_value(ds18b20_gpio)
/*發(fā)送復(fù)位信號(hào),檢測(cè)存在脈沖*/
static u8 ds18b20_CheckRst(void)
{
u8 time=0;
DS18B20_OUT_MODE();/*輸出模式*/
DS18B20_OUT(0);/*總線拉低*/
udelay(600);/*至少480us低電平*/
DS18B20_OUT(1);/*釋放總線,恢復(fù)為空閑電平*/
udelay(15);
DS18B20_INPUT_MODE();/*輸入模式*/
while(DS18B20_IN)
{
time++;
udelay(1);
if(time>=100)return 1;/*等待存在脈沖失敗*/
}
time=0;
while(!DS18B20_IN)
{
time++;
udelay(1);
if(time>=250)return 2;//模塊出錯(cuò)
}
return 0;
}
/*寫一個(gè)字節(jié)函數(shù)*/
static void ds18b20_writeDat(u8 dat)
{
int i=0;
DS18B20_OUT_MODE();/*輸出模式*/
for(i=0;i<8;i++)
{
DS18B20_OUT(0);//總線拉低,產(chǎn)生寫間隙時(shí)間
udelay(2);
if(dat&0x01)DS18B20_OUT(1);
else DS18B20_OUT(0);
udelay(60);//寫周期時(shí)間
DS18B20_OUT(1);//釋放總線
udelay(2);
dat>>=1;//繼續(xù)發(fā)送下一位數(shù)據(jù)
}
}
/*讀取1字節(jié)數(shù)據(jù)*/
static u8 ds18b20_readDat(void)
{
int i=0;
u8 data=0;
for(i=0;i<8;i++)
{
DS18B20_OUT_MODE();/*輸出模式*/
DS18B20_OUT(0);//總線拉低,產(chǎn)生讀間隙時(shí)間
udelay(2);
DS18B20_INPUT_MODE();//配置為輸入模式
udelay(12);//等待數(shù)據(jù)到來
data>>=1;
if(DS18B20_IN)data|=0x80;
udelay(50);//讀數(shù)據(jù)時(shí)間
DS18B20_OUT(1);//恢復(fù)總線為空閑電平
udelay(2);
}
return data;
}
/*獲取一次溫度數(shù)據(jù)*/
static u16 ds18b20_GetTemp(void)
{
u8 L,H;
u16 temp;
if(ds18b20_CheckRst())return 0xffff;
ds18b20_writeDat(0xcc);
ds18b20_writeDat(0x44);
while(ds18b20_readDat()!=0xff);/*等待溫度轉(zhuǎn)換完成*/
if(ds18b20_CheckRst())return 0xffff;
ds18b20_writeDat(0xcc);
ds18b20_writeDat(0xbe);/*讀取一次溫度*/
L=ds18b20_readDat();
H=ds18b20_readDat();
temp=H<<8|L;
return temp;
}
static int ds18b20_open(struct inode *inode, struct file *file)
{
printk("open函數(shù)調(diào)用成功\n");
if(ds18b20_CheckRst())
{
printk("DS18B20初始化失敗\n");
}
return 0;
}
static int ds18b20_release(struct inode *inode, struct file *file)
{
printk("release函數(shù)調(diào)用成功");
return 0;
}
long ds18b20_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int dir=_IOC_DIR(cmd);/*數(shù)據(jù)讀寫方向,00無參數(shù),10用戶層讀,01用戶層寫,11可讀寫*/
int type=_IOC_TYPE(cmd);/*魔術(shù),標(biāo)志符*/
int size=_IOC_SIZE(cmd);/*arg的字節(jié)數(shù)*/
printk("dir=%d,type=%c,size=%d\n",dir,type,size);
int ret;
u16 temp=ds18b20_GetTemp();/*獲取一次溫度*/
ret=copy_to_user((void *)arg, &temp,size);
return 4-ret;
}
static struct file_operations ds18b20_fops=
{
.open =ds18b20_open,
.release =ds18b20_release,
.unlocked_ioctl =ds18b20_ioctl
};
/*雜項(xiàng)設(shè)備結(jié)構(gòu)體*/
static struct miscdevice ds18b20_drv=
{
.minor =MISC_DYNAMIC_MINOR,/*255,有內(nèi)核自動(dòng)分配*/
.name ="ds18b20",//設(shè)備節(jié)點(diǎn)名字
.fops =&ds18b20_fops,//文件操作集合
};
static int __init wbyq_ds18b20_init(void)
{
/*1.GPIO注銷*/
gpio_free(ds18b20_gpio);
/*2.注冊(cè)GPIO*/
gpio_request(ds18b20_gpio,"DS18B20");
/*配置GPIO模式*/
s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT);
gpio_set_value(ds18b20_gpio,1);/*上拉*/
/*注冊(cè)雜項(xiàng)設(shè)備*/
misc_register(&ds18b20_drv);
return 0;
}
/*驅(qū)動(dòng)釋放*/
static void __exit wbyq_ds18b20_cleanup(void)
{
printk("驅(qū)動(dòng)出口,驅(qū)動(dòng)注銷成功\n");
/*注銷雜項(xiàng)設(shè)備*/
misc_deregister(&ds18b20_drv);
/*注銷GPIO*/
gpio_free(ds18b20_gpio);
}
module_init(wbyq_ds18b20_init);//驅(qū)動(dòng)入口函數(shù)
module_exit(wbyq_ds18b20_cleanup);//驅(qū)動(dòng)出口函數(shù)
MODULE_LICENSE("GPL");//驅(qū)動(dòng)注冊(cè)協(xié)議
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 ds18b20 Driver");
審核編輯:湯梓紅
-
溫度傳感器
+關(guān)注
關(guān)注
48文章
2940瀏覽量
156014 -
DS18B20
+關(guān)注
關(guān)注
10文章
779瀏覽量
80820 -
設(shè)備驅(qū)動(dòng)
+關(guān)注
關(guān)注
0文章
68瀏覽量
10883
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論