<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于S3C2440嵌入式Linux系統(tǒng)下的一個(gè)DS18B20驅(qū)動(dòng)

          基于S3C2440嵌入式Linux系統(tǒng)下的一個(gè)DS18B20驅(qū)動(dòng)

          作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò) 收藏
          用Linux驅(qū)動(dòng)編程的方法寫(xiě)一個(gè)DS18B20的溫度傳感器驅(qū)動(dòng),從底層采集溫度信息。以下乃本人所寫(xiě)的驅(qū)動(dòng)和測(cè)試的源碼,嵌入式Linux內(nèi)核版本為2.6.29,硬件平臺(tái)是友善之臂的QQ2440,DS18B20引腳連接S3C2440的GPIOB1,程序難免存在一定的漏洞,希望大家指出。


          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include

          本文引用地址:http://www.ex-cimer.com/article/201611/318872.htm

          typedef unsigned char BYTE;

          #define DS18B20_PIN S3C2410_GPB1
          #define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP
          #define DS18B20_PIN_INP S3C2410_GPB1_INP
          #define HIGH 1
          #define LOW 0
          #define DEV_NAME "DS18B20"
          #define DEV_MAJOR 232
          static BYTE data[2];

          // DS18B20復(fù)位函數(shù)
          BYTE DS18b20_reset (void)
          {
          // 配置GPIOB0輸出模式
          s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);

          // 向18B20發(fā)送一個(gè)上升沿,并保持高電平狀態(tài)約100微秒
          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          udelay(100);

          // 向18B20發(fā)送一個(gè)下降沿,并保持低電平狀態(tài)約600微秒
          s3c2410_gpio_setpin(DS18B20_PIN, LOW);
          udelay(600);

          // 向18B20發(fā)送一個(gè)上升沿,此時(shí)可釋放DS18B20總線
          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          udelay(100);

          // 以上動(dòng)作是給DS18B20一個(gè)復(fù)位脈沖
          // 通過(guò)再次配置GPIOB1引腳成輸入狀態(tài),可以檢測(cè)到DS18B20是否復(fù)位成功
          s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);

          // 若總線在釋放后總線狀態(tài)為高電平,則復(fù)位失敗
          if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.rn"); return 1;}

          return 0;
          }

          void DS18b20_write_byte (BYTE byte)
          {
          BYTE i;
          // 配置GPIOB1為輸出模式
          s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);

          // 寫(xiě)“1”時(shí)隙:
          // 保持總線在低電平1微秒到15微秒之間
          // 然后再保持總線在高電平15微秒到60微秒之間
          // 理想狀態(tài): 1微秒的低電平然后跳變?cè)俦3?0微秒的高電平
          //
          // 寫(xiě)“0”時(shí)隙:
          // 保持總線在低電平15微秒到60微秒之間
          // 然后再保持總線在高電平1微秒到15微秒之間
          // 理想狀態(tài): 60微秒的低電平然后跳變?cè)俦3?微秒的高電平
          for (i = 0; i < 8; i++)
          {
          s3c2410_gpio_setpin(DS18B20_PIN, LOW); udelay(1);
          if(byte & HIGH)
          {
          // 若byte變量的D0位是1,則需向總線上寫(xiě)“1”
          // 根據(jù)寫(xiě)“1”時(shí)隙規(guī)則,電平在此處翻轉(zhuǎn)為高
          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          }
          else
          {
          // 若byte變量的D0位是0,則需向總線上寫(xiě)“0”
          // 根據(jù)寫(xiě)“0”時(shí)隙規(guī)則,電平在保持為低
          // s3c2410_gpio_setpin(DS18B20_PIN, LOW);
          }
          // 電平狀態(tài)保持60微秒
          udelay(60);

          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          udelay(15);

          byte >>= 1;
          }
          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          }

          BYTE DS18b20_read_byte (void)
          {
          BYTE i = 0;
          BYTE byte = 0;
          // 讀“1”時(shí)隙:
          // 若總線狀態(tài)保持在低電平狀態(tài)1微秒到15微秒之間
          // 然后跳變到高電平狀態(tài)且保持在15微秒到60微秒之間
          // 就認(rèn)為從DS18B20讀到一個(gè)“1”信號(hào)
          // 理想情況: 1微秒的低電平然后跳變?cè)俦3?0微秒的高電平
          //
          // 讀“0”時(shí)隙:
          // 若總線狀態(tài)保持在低電平狀態(tài)15微秒到30微秒之間
          // 然后跳變到高電平狀態(tài)且保持在15微秒到60微秒之間
          // 就認(rèn)為從DS18B20讀到一個(gè)“0”信號(hào)
          // 理想情況: 15微秒的低電平然后跳變?cè)俦3?6微秒的高電平
          for (i = 0; i < 8; i++)
          {
          s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
          s3c2410_gpio_setpin(DS18B20_PIN, LOW);

          udelay(1);
          byte >>= 1;

          s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
          s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);

          // 若總線在我們?cè)O(shè)它為低電平之后若1微秒之內(nèi)變?yōu)楦?br /> // 則認(rèn)為從DS18B20處收到一個(gè)“1”信號(hào)
          // 因此把byte的D7為置“1”
          if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80;
          udelay(60);
          }
          return byte;
          }

          void DS18b20_proc(void)
          {
          while(DS18b20_reset());

          udelay(120);

          DS18b20_write_byte(0xcc);
          DS18b20_write_byte(0x44);

          udelay(5);

          while(DS18b20_reset());
          udelay(200);

          DS18b20_write_byte(0xcc);
          DS18b20_write_byte(0xbe);

          data[0] = DS18b20_read_byte();
          data[1] = DS18b20_read_byte();
          }

          static ssize_t s3c2440_18b20_read(struct file *filp, char *buf, size_t len, loff_t *off)
          {
          DS18b20_proc();

          buf[0] = data[0];
          buf[1] = data[1];

          return 1;
          }

          static struct file_operations s3c2440_18b20_fops =
          {
          .owner = THIS_MODULE,
          .read = s3c2440_18b20_read,
          };

          static int __init s3c2440_18b20_init(void)
          {
          if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_fops) < 0)
          {
          printk(DEV_NAME ": Register major failed.rn");
          return -1;
          }

          devfs_mk_cdev(MKDEV(DEV_MAJOR, 0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEV_NAME);

          while(DS18b20_reset());
          }

          static void __exit s3c2440_18b20_exit(void)
          {
          devfs_remove(DEV_NAME);
          unregister_chrdev(DEV_MAJOR, DEV_NAME);
          }
          module_init(s3c2440_18b20_init);
          module_exit(s3c2440_18b20_exit);

          #include "stdio.h"
          #include "sys/types.h"
          #include "sys/ioctl.h"
          #include "stdlib.h"
          #include "termios.h"
          #include "sys/stat.h"
          #include "fcntl.h"
          #include "sys/time.h"

          main()
          {
          int fd;
          unsigned char buf[2];
          float result;

          if ((fd=open("/dev/DS18B20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
          {
          printf("Open Device DS18B20 failed.rn");
          exit(1);
          }
          else
          {
          printf("Open Device DS18B20 successed.rn");
          while(1)
          {
          read(fd, buf, 1);
          result = (float)buf[0];
          result /= 16;
          result += ((float)buf[1] * 16);

          printf("%.1f `Crn", result);
          sleep(1);
          }
          close(fd);
          }
          }

          obj-m := s3c2440_ds18b20.o

          KERNELDIR ?= ../../kernel/linux-2.6.29
          PWD := $(shell pwd)
          CC := arm-linux-gcc
          CLEAN := rm -rf


          all : s3c2440_ds18b20.c test_ds18b20
          $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

          test_ds18b20 : test_ds18b20.c
          $(CC) test_ds18b20.c -o test_ds18b20

          clobber :
          $(CLEAN) test_ds18b20 s3c2440_ds18b20.ko
          clean :
          $(CLEAN) *.mod.* *.o *~ modules.order Module.symvers

          這個(gè)驅(qū)動(dòng)是基于Linux的2.6.29內(nèi)核樹(shù)編譯的,內(nèi)核樹(shù)的路徑是當(dāng)前目錄的../../kernel/linux-2.6.29,若以來(lái)其他的Linux的內(nèi)核樹(shù),編譯時(shí)可能會(huì)出現(xiàn)找不到某些文件的情況,如hardware.h等,只需要在內(nèi)核樹(shù)中作一些軟鏈接就可以解決,還有聲明一點(diǎn)的就是:Makefile中的命令操作前的并非空格,而是TAB跳格。

          make編譯,編譯完畢后產(chǎn)生許多文件,我們只關(guān)心test_ds18b20和s3c2440_ds18b20.ko這兩個(gè)。

          把以上兩個(gè)文件下載到開(kāi)發(fā)板中,創(chuàng)建一個(gè)設(shè)備節(jié)點(diǎn):

          mknod /dev/DS18B20 c 232 0

          把s3c2440_ds18b20這個(gè)模塊加載到內(nèi)核:

          insmod s3c2440_ds18b20.ko

          加載成功后我們可以通過(guò)模塊列表查看:

          之后把test_ds18b20測(cè)試文件改為可執(zhí)行狀態(tài):

          chmod 0111 test_ds18b20

          執(zhí)行后可以觀察到以下的結(jié)果:



          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();