生活随笔 
收集整理的這篇文章主要介紹了
                                
DS18B20 驱动编写 
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
 
                                
                             
                             
                             嵌入式開發(fā)平臺:mini2440
 
 DS18B20 所用GPIO:S3C2410_GPF(3)
 
   
 
 一、DS18B20 時(shí)序分析 
 
 ? ? ? ? DS18B20的一線工作協(xié)議流程是:初始化→ROM操作指令→存儲器操作指令→數(shù)據(jù)傳輸,其工作時(shí)序包括:初始化時(shí)序、寫時(shí)序、讀時(shí)序。  
 
 1、初始化時(shí)序 
 
 ? ? ? ?主機(jī)首先發(fā)出一個(gè)480-960微秒的低電平脈沖,然后釋放總線變?yōu)楦唠娖?#xff0c;并在隨后的480微秒時(shí)間內(nèi)對總線進(jìn)行檢測,如果有低電平出現(xiàn)說明總線上有器件已做出應(yīng)答 ,若無低電平出現(xiàn)一直都是高電平說明總線上無器件應(yīng)答。
 
   ?作為從器件的DS18B20在一上電后就一直在檢測總線上是否有480-960微秒的低電平出現(xiàn),如果有,在總線轉(zhuǎn)為高電平后等待15-60微秒后將總線電平拉低60-240微秒做出響應(yīng)存在脈沖,告訴主機(jī)本器件已做好準(zhǔn)備 ,若沒有檢測到就一直在檢測等待。
 
   
 
   
 
 
 
   [cpp] ?view plaincopy   
    static ? int ?ds18b20_init( void )????   {????   ????int ?retval?=?0;????    ????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????   ????s3c2410_gpio_setpin(DQ,?1);????   ????udelay(2);????   ????s3c2410_gpio_setpin(DQ,?0);???    ????udelay(500);??????????????????    ????   ????s3c2410_gpio_setpin(DQ,?1);???    ????udelay(60);????   ????   ??????    ????s3c2410_gpio_cfgpin(DQ,?CFG_IN);????   ????retval?=?s3c2410_gpio_getpin(DQ);????   ????   ????udelay(500);????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????s3c2410_gpio_setpin(DQ,?1);???    ????   ????return ?retval;????    }????   
 
 
2、寫時(shí)序 
  
 
 
 ? ? ?寫周期最少為60微秒 ,最長不超過120微秒,寫周期一開始作為主機(jī)先把總線拉低1微秒表示寫周期開始 ,隨后若主機(jī)想寫0,則繼續(xù)拉低電平最少60微秒 直至寫周期結(jié)束,然后釋放總線為高電平;若主機(jī)想寫1,在一開始拉低總線電平1微秒后就釋放總線為高電平,一直到寫周期結(jié)束 。
 
 ? ? ?而作為從機(jī)的DS18B20則在檢測到總線被拉低后等待15微秒然后從15μs到45μs開始對總線采樣,在采樣期內(nèi)總線為高電平則為1,若采樣期內(nèi)總線為低電平則為0。  
 
   
 
   
 
 
 
   [cpp] ?view plaincopy   
    static ? void ?write_byte(unsigned? char ?data)????   {????   ????int ?i?=?0;????    ????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?1);????   ????   ????for ?(i?=?0;?i?<?8;?i++)????    ????{????   ??????????    ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?0);????   ????????s3c2410_gpio_setpin(DQ,?data?&?0x01);????   ????????udelay(60);????   ????????data?>>=?1;????   ????}????   ????s3c2410_gpio_setpin(DQ,?1);???    }????   
 
 
3、讀時(shí)序 
  
 
 
 ? ? ? 對于讀數(shù)據(jù)操作時(shí)序也分為讀0時(shí)序和讀1時(shí)序兩個(gè)過程,讀時(shí)序是從主機(jī)把單總線拉低之后,在1微秒之后就得釋放單總線為高電平 ,以讓DS18B20把數(shù)據(jù)傳輸?shù)絾慰偩€上。DS18B20在檢測到總線被拉低1微秒后,便開始送出數(shù)據(jù),若是要送出0就把總線拉為低電平直到讀周期結(jié)束;若要送出1則釋放總線為高電平。
 
 ? ? ?主機(jī)在一開始拉低總線1微秒后釋放總線,然后在包括前面的拉低總線電平1微秒在內(nèi)的15微秒時(shí)間內(nèi)完成對總線進(jìn)行采樣檢測,采樣期內(nèi)總線為低電平則確認(rèn)為0,采樣期內(nèi)總線為高電平則確認(rèn)為1,完成一個(gè)讀時(shí)序過程,至少需要60μs才能完成。  
 
   
 
   
 
 
 
   [cpp] ?view plaincopy   
    static ?unsigned? char ?read_byte( void )????   {????   ????int ?i;????    ????unsigned?char ?data?=?0;????    ????    ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);???   ???   ????for ?(i?=?0;?i?<?8;?i++)????    ????{????   ??????????   ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?0);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(8);????   ????????data?>>=?1;????   ????????s3c2410_gpio_cfgpin(DQ,?CFG_IN);????   ????????if ?(s3c2410_gpio_getpin(DQ))????    ????????????data?|=?0x80;????   ????????udelay(50);????   ????}????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????s3c2410_gpio_setpin(DQ,?1);???    ????return ?data;????    }????   
 
   
 
 二、操作方法 
 
 ? ? ? ?DS18B20單線通信功能是分時(shí)完成的,有嚴(yán)格的時(shí)序概念,如果出現(xiàn)序列混亂,1-WIRE器件將不影響主機(jī),因此讀寫時(shí)序很重要。系統(tǒng)對DS18B20的各種操作必須按協(xié)議進(jìn)行,根據(jù)DS18B20的協(xié)議規(guī)定,微控制器控制DS18B20完成溫度的轉(zhuǎn)換必須經(jīng)過以下4個(gè)步驟:
 
 1)每次讀寫前對DS18B20進(jìn)行復(fù)位初始化 。復(fù)位要求主CPU將數(shù)據(jù)線下拉500μs,然后釋放,DS18B20收到信號后等待16μs-60μs左右,然后發(fā)出60μs-240μs的存在低脈沖,主CPU收到此信號后表示復(fù)位成功。
 
   
 
 2)發(fā)送一條ROM指令 
 
   
 
   
 
 3)發(fā)送存儲器指令 
 
   
 
   
 
 1、讓DS18B20進(jìn)行一次溫度轉(zhuǎn)換的具體操作如下: 
 
 a -- 主機(jī)先做個(gè)復(fù)位操作;  b -- 主機(jī)再寫跳過ROM的操作(CCH)命令;  c -- 然后主機(jī)接著寫轉(zhuǎn)換溫度的操作指令,后面釋放總線至少1秒,讓DS18B20完成轉(zhuǎn)換操作。需要注意的是每個(gè)命令字節(jié)在寫的時(shí)候都是低字節(jié)先寫,例如CCH的二進(jìn)制為11001100,在寫到總線上時(shí)要從低位開始寫,寫的順序是“0、0、1、1、0、0、1、1”,整個(gè)操作的總線狀態(tài)如圖所。
 
     
 
 2、讀取RAM的溫度數(shù)據(jù),同樣,這個(gè)操作也要按照三個(gè)步驟: 
 
 a -- 主機(jī)發(fā)出復(fù)位操作并接受DS18B20的應(yīng)答(存在)脈沖;  b -- 主機(jī)發(fā)出跳過對ROM操作的命令(CCH);  c -- 主機(jī)發(fā)出讀取RAM的命令(BEH),隨后主機(jī)依次讀取DS18B20發(fā)出的從第0-第8,共九個(gè)字節(jié)的數(shù)據(jù)。如果只想讀取溫度數(shù)據(jù),那在讀完第0和第1個(gè)數(shù)據(jù)后就不再理會后面DS18B20發(fā)出的數(shù)據(jù)即可,同樣讀取數(shù)據(jù)也是低位在前,整個(gè)操作的總線狀態(tài)如圖所示。  
 
   
 
   
 
 三、具體驅(qū)動編寫 
 
 1、ds18b20_drv.c  
 
 
 
   [cpp] ?view plaincopy   
    #include?<linux/init.h>??? ??   #include?<linux/module.h>??? ??   #include?<linux/delay.h>??? ??   #include?<linux/kernel.h>??? ??   #include?<linux/moduleparam.h>??? ??   #include?<linux/init.h>??? ??   #include?<linux/types.h>??? ??   #include?<linux/fs.h>??? ??   #include?<mach/regs-gpio.h>??? ??   #include?<mach/hardware.h>??? ??   #include?<linux/cdev.h>??? ??   #include?<asm/uaccess.h>??? ??   #include?<linux/errno.h>??? ??   #include?<linux/gpio.h>??? ??   #include?<linux/device.h>??? ??   ????   ????   #define?DQ?????????S3C2410_GPF(3)??? ??   #define?CFG_IN?????S3C2410_GPIO_INPUT??? ??   #define?CFG_OUT????S3C2410_GPIO_OUTPUT??? ??   ????   ??   static ? int ?ds18b20_major?=?0;????   static ? int ?ds18b20_minor?=?0;????   static ? int ?ds18b20_nr_devs?=?1;????   ????   ??   static ? struct ?ds18b20_device????   {????   ????struct ?cdev?cdev;????    };????   ????   struct ?ds18b20_device?*ds18b20_devp;???? ????   ????   static ? struct ? class ?*ds18b20_class;????   static ? struct ?class_device?*ds18b20_class_dev;????   ????   ????   static ? int ?ds18b20_open( struct ?inode?*inode,? struct ?file?*filp);????   static ? int ?ds18b20_init( void );????   static ? void ?write_byte(unsigned? char ?data);????   static ?unsigned? char ?read_byte( void );????   static ?ssize_t?ds18b20_read( struct ?file?*filp,? char ?__user?*?buf,? size_t ?count,?loff_t?*?f_pos);????   void ?ds18b20_setup_cdev( struct ?ds18b20_device?*dev,? int ?index);????   ????   static ? int ?ds18b20_open( struct ?inode?*inode,? struct ?file?*filp)????   {????   ????int ?flag?=?0;????    ????   ????flag?=?ds18b20_init();????   ????if ?(flag?&?0x01)????    ????{????   ????????printk(KERN_WARNING?"open?ds18b20?failed\n" );????    ????????return ?-1;????    ????}????   ????printk(KERN_NOTICE?"open?ds18b20?successful\n" );????    ????return ?0;????    }????   ????   static ? int ?ds18b20_init( void )????   {????   ????int ?retval?=?0;????    ????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????   ????s3c2410_gpio_setpin(DQ,?1);????   ????udelay(2);????   ????s3c2410_gpio_setpin(DQ,?0);???    ????udelay(500);??????????????????    ????   ????s3c2410_gpio_setpin(DQ,?1);???    ????udelay(60);????   ????   ??????    ????s3c2410_gpio_cfgpin(DQ,?CFG_IN);????   ????retval?=?s3c2410_gpio_getpin(DQ);????   ????   ????udelay(500);????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????s3c2410_gpio_setpin(DQ,?1);???    ????   ????return ?retval;????    }????   ????   static ? void ?write_byte(unsigned? char ?data)????   {????   ????int ?i?=?0;????    ????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?1);????   ????   ????for ?(i?=?0;?i?<?8;?i++)????    ????{????   ??????????    ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?0);????   ????????s3c2410_gpio_setpin(DQ,?data?&?0x01);????   ????????udelay(60);????   ????????data?>>=?1;????   ????}????   ????s3c2410_gpio_setpin(DQ,?1);???    }????   ????   static ?unsigned? char ?read_byte( void )????   {????   ????int ?i;????    ????unsigned?char ?data?=?0;????    ????   ????for ?(i?=?0;?i?<?8;?i++)????    ????{????   ??????????    ????????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????????s3c2410_gpio_pullup(DQ,?0);????   ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?0);????   ????????udelay(2);????   ????????s3c2410_gpio_setpin(DQ,?1);????   ????????udelay(8);????   ????????data?>>=?1;????   ????????s3c2410_gpio_cfgpin(DQ,?CFG_IN);????   ????????if ?(s3c2410_gpio_getpin(DQ))????    ????????????data?|=?0x80;????   ????????udelay(50);????   ????}????   ????s3c2410_gpio_cfgpin(DQ,?CFG_OUT);????   ????s3c2410_gpio_pullup(DQ,?0);????   ????s3c2410_gpio_setpin(DQ,?1);???    ????return ?data;????    }????   ????   static ?ssize_t?ds18b20_read( struct ?file?*filp,? char ?__user?*?buf,? size_t ?count,?loff_t?*?f_pos)????   {????   ????int ?flag;????    ????unsigned?long ?err;????    ????unsigned?char ?result[2]?=?{?0x00,?0x00?};????    ??????    ????   ????flag?=?ds18b20_init();????   ????if ?(flag?&?0x01)????    ????{????   ????????printk(KERN_WARNING?"ds18b20?init?failed\n" );????    ????????return ?-1;????    ????}????   ????   ????write_byte(0xcc);????   ????write_byte(0x44);????   ????   ????flag?=?ds18b20_init();????   ????if ?(flag?&?0x01)????    ????????return ?-1;????    ????   ????write_byte(0xcc);????   ????write_byte(0xbe);????   ????   ????result[0]?=?read_byte();??????    ????result[1]?=?read_byte();??????    ????   ????err?=?copy_to_user(buf,?&result,?sizeof (result));????    ????return ?err???-EFAULT?:?min( sizeof (result),?count);????    }????   ????   static ? struct ?file_operations?ds18b20_dev_fops?=?{????   ????.owner?=?THIS_MODULE,????   ????.open?=?ds18b20_open,????   ????.read?=?ds18b20_read,????   };????   ????   void ?ds18b20_setup_cdev( struct ?ds18b20_device?*dev,? int ?index)????   {????   ????int ?err,?devno?=?MKDEV(ds18b20_major,?ds18b20_minor?+?index);????    ????   ????cdev_init(&dev->cdev,?&ds18b20_dev_fops);????   ????dev->cdev.owner?=?THIS_MODULE;????   ????err?=?cdev_add(&(dev->cdev),?devno,?1);????   ????if ?(err)????    ????{????   ????????printk(KERN_NOTICE?"ERROR?%d?add?ds18b20\n" ,?err);????    ????}????   }????   ????   static ? int ?__init?ds18b20_dev_init( void )????   {????   ????int ?result;????    ????dev_t?dev?=?0;????   ????   ????dev?=?MKDEV(ds18b20_major,?ds18b20_minor);????   ????   ????if ?(ds18b20_major)????    ????{????   ????????result?=?register_chrdev_region(dev,?ds18b20_nr_devs,?"ds18b20" );????    ????}????   ????else ????    ????{????   ????????result?=?alloc_chrdev_region(&dev,?ds18b20_minor,?ds18b20_nr_devs,?"ds18b20" );????    ????????ds18b20_major?=?MAJOR(dev);????   ????}????   ????if ?(result?<?0)????    ????{????   ????????printk(KERN_WARNING?"ds18b20:?failed?to?get?major\n" );????    ????????return ?result;????    ????}????   ????   ????????    ????ds18b20_devp?=?kmalloc(sizeof ( struct ?ds18b20_device),?GFP_KERNEL);????    ????if ?(!ds18b20_devp)????    ????{???????????????????????????????    ????????result?=?-ENOMEM;????   ????????goto ?fail_malloc;????    ????}????   ????memset(ds18b20_devp,?0,?sizeof ( struct ?ds18b20_device));????    ????   ????ds18b20_setup_cdev(ds18b20_devp,?0);????   ????   ????????    ????ds18b20_class?=?class_create(THIS_MODULE,?"ds18b20_sys_class" );????    ????if ?(IS_ERR(ds18b20_class))????    ????????return ?PTR_ERR(ds18b20_class);????    ????   ????ds18b20_class_dev?=????   ????????device_create(ds18b20_class,?NULL,?MKDEV(ds18b20_major,?0),?NULL,?"ds18b20" );????    ????if ?(unlikely(IS_ERR(ds18b20_class_dev)))????    ????????return ?PTR_ERR(ds18b20_class_dev);????    ????   ????return ?0;????    ????   ??fail_malloc:????   ????unregister_chrdev_region(dev,?1);????   ????return ?result;????    }????   ????   static ? void ?__exit?ds18b20_dev_exit( void )????   {????   ????cdev_del(&ds18b20_devp->cdev);??????    ????kfree(ds18b20_devp);????????????    ????unregister_chrdev_region(MKDEV(ds18b20_major,?0),?ds18b20_nr_devs);?????    ????device_unregister(ds18b20_class_dev);????   ????class_destroy(ds18b20_class);????   }????   ????   module_init(ds18b20_dev_init);????   module_exit(ds18b20_dev_exit);????   MODULE_LICENSE("Dual?BSD/GPL" );????    
 
 
2、app-ds18b20.c  
   [cpp] ?view plaincopy   
    #include?<stdio.h>??? ??   #include?<stdlib.h>??? ??   #include?<unistd.h>??? ??   #include?<linux/ioctl.h>??? ??   ????   ??   void ?ds18b20_delay( int ?i);????   ????   int ?main()????   {????   ????int ?fd,?i;????    ????unsigned?char ?result[2];???? ??    ????unsigned?char ?integer_value?=?0;????    ????float ?decimal_value?=?0;???? ??    ????float ?temperature?=?0;????    ????   ????fd?=?open("/dev/ds18b20" ,?0);????    ????if ?(fd?<?0)????    ????{????   ????????perror("open?device?failed\n" );????    ????????exit(1);????   ????}????   ????while ?(1)????    ????{????   ????????i++;????   ????????read(fd,?&result,?sizeof (result));????    ????????integer_value?=?((result[0]?&?0xf0)?>>?4)?|?((result[1]?&?0x07)?<<?4);????   ??????????    ????????decimal_value?=?0.5?*?((result[0]?&?0x0f)?>>?3)?+?0.25?*?((result[0]?&?0x07)?>>?2);????   ????????temperature?=?(float )integer_value?+?decimal_value;????    ????????printf("Current?Temperature:%6.2f\n" ,?temperature);????    ????   ????????ds18b20_delay(500);????   ????}????   }????   ????   void ?ds18b20_delay( int ?i)????   {????   ????int ?j,?k;????    ????for ?(j?=?0;?j?<?i;?j++)????    ????????for ?(k?=?0;?k?<?50000;?k++)?;????    }????   
 
 測試結(jié)果:
 
 
 
   [cpp] ?view plaincopy   
    [root@www.linuxidc.com?home]#????   [root@www.linuxidc.com?home]#./app-ds18b20????   open?ds18b20?successful????   Current?Temperature:?23.50????   Current?Temperature:?23.50????   Current?Temperature:?23.25????   Current?Temperature:?23.50????   Current?Temperature:?23.50????   Current?Temperature:?23.50????   ^C????   [root@www.linuxidc.com?home]# ? ?  
                            總結(jié) 
                            
                                以上是生活随笔 為你收集整理的DS18B20 驱动编写 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。