從網站上下載了lixin的mini2410的ds18b20代碼,並做了修改,成功實現了Tiny6410的ds18b20驅動。感謝署名為lixin的網友!
【程序清單】
ds18b20.c
[html]
- /******************************************Copyright(c)************************************************
- ** 文件名稱: ds18b20_drv.c
- ** 作 者: lixin
- ** 版 本: v1.0
- ** 說 明: ds18b20驅動程序.工作過程及時序見ds18b20 datasheet
- ** 修改記錄: 2009-8-27創建
- ** 最後修改時間: 2009-09-01
- ******************************************************************************************************/
- #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 <linux/device.h>
- #include <mach/hardware.h>
- #include <linux/cdev.h>
- #include <asm/uaccess.h>
- #include <linux/errno.h>
-
- #include "s3c6410_gpio.h"
-
- //#define DEBUG
- /* 相關引腳定義,方便以後移植 */
- #define DEVICE_NAME "ds18b20"
- #define DQ 8
- #define CFG_IN 0
- #define CFG_OUT 1
-
- // ds18b20主次設備號(動態分配)
- int ds18b20_major = 0;
- int ds18b20_minor = 0;
- int ds18b20_nr_devs = 1;
-
- // 定義設備類型
- static struct ds18b20_device {
- struct cdev cdev;
- };
- struct ds18b20_device ds18b20_dev;
-
- static struct class *ds18b20_class;
-
- /* 函數聲明 */
- 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);
-
- /******************************************************************************************************
- ** 函數名稱: ds18b20_open()
- ** 函數功能: 打開設備,初始化ds18b20
- ** 入口參數: inode:設備文件信息; filp: 被打開的文件的信息
- ** 出口參數: 成功時返回0,失敗返回-1
- ** 備 注:
- ******************************************************************************************************/
- static int ds18b20_open(struct inode *inode, struct file *filp)
- {
- int flag = 0;
- /*struct ds18b20_device *dev;
- dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);
- filp->private_data = dev;*/
-
- flag = ds18b20_init();
- if(flag & 0x01)
- {
- #ifdef DEBUG
- printk(KERN_WARNING "open ds18b20 failed\n");
- #endif
- return -1;
- }
- #ifdef DEBUG
- printk(KERN_NOTICE "open ds18b20 successful\n");
- #endif
- return 0;
- }
-
- /******************************************************************************************************
- ** 函數名稱: ds18b20_init()
- ** 函數功能: 復位ds18b20
- ** 入口參數: 無
- ** 出口參數: retval:成功返回0,失敗返回1
- ** 備 注: 操作時序見ds18b20 datasheet
- ******************************************************************************************************/
- static int ds18b20_init(void)
- {
- int retval = 0;
-
- s3c6410_gpio_cfgpin(DQ, CFG_OUT);
- s3c6410_gpio_pullup(DQ, 0);
-
- s3c6410_gpio_setpin(DQ, 1);
- udelay(2);
- s3c6410_gpio_setpin(DQ, 0); // 拉低ds18b20總線,復位ds18b20
- udelay(500); // 保持復位電平500us
-
- s3c6410_gpio_setpin(DQ, 1); // 釋放ds18b20總線
- udelay(60);
-
- // 若復位成功,ds18b20發出存在脈沖(低電平,持續60~240us)
- s3c6410_gpio_cfgpin(DQ, CFG_IN);
- retval = s3c6410_gpio_getpin(DQ);
-
- udelay(500);
- s3c6410_gpio_cfgpin(DQ, CFG_OUT);
- s3c6410_gpio_pullup(DQ, 0);
- s3c6410_gpio_setpin(DQ, 1); // 釋放總線
-
- return retval;
- }
-
- /******************************************************************************************************
- ** 函數名稱: write_byte()
- ** 函數功能: 向18b20寫入一個字節數據
- ** 入口參數: data
- ** 出口參數: 無
- ** 備 注:
- ******************************************************************************************************/
- static void write_byte(unsigned char data)
- {
- int i = 0;
-
- s3c6410_gpio_cfgpin(DQ, CFG_OUT);
- s3c6410_gpio_pullup(DQ, 1);
-
- for (i = 0; i < 8; i ++)
- {
- // 總線從高拉至低電平時,就產生寫時隙
- s3c6410_gpio_setpin(DQ, 1);
- udelay(2);
- s3c6410_gpio_setpin(DQ, 0);
- s3c6410_gpio_setpin(DQ, data & 0x01);
- udelay(60);
- data >>= 1;
- }
- s3c6410_gpio_setpin(DQ, 1); // 重新釋放ds18b20總線
- }
-
- /******************************************************************************************************
- ** 函數名稱: read_byte()
- ** 函數功能: 從ds18b20讀出一個字節數據
- ** 入口參數: 無
- ** 出口參數: 讀出的數據
- ** 備 注:
- ******************************************************************************************************/
- static unsigned char read_byte(void)
- {
- int i;
- unsigned char data = 0;
-
- for (i = 0; i < 8; i++)
- {
- // 總線從高拉至低,只需維持低電平17ts,再把總線拉高,就產生讀時隙
- s3c6410_gpio_cfgpin(DQ, CFG_OUT);
- s3c6410_gpio_pullup(DQ, 0);
- s3c6410_gpio_setpin(DQ, 1);
- udelay(2);
- s3c6410_gpio_setpin(DQ, 0);
- udelay(2);
- s3c6410_gpio_setpin(DQ, 1);
- udelay(8);
- data >>= 1;
- s3c6410_gpio_cfgpin(DQ, CFG_IN);
- if (s3c6410_gpio_getpin(DQ))
- data |= 0x80;
- udelay(50);
- }
- s3c6410_gpio_cfgpin(DQ, CFG_OUT);
- s3c6410_gpio_pullup(DQ, 0);
- s3c6410_gpio_setpin(DQ, 1); // 釋放ds18b20總線
- return data;
- }
- /******************************************************************************************************
- ** 函數名稱: ds18b20_read()
- ** 函數功能: 讀出18b20的溫度
- ** 入口參數:
- ** 出口參數:
- ** 備 注:
- ******************************************************************************************************/
- 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};
- //struct ds18b20_device *dev = filp->private_data;
-
- flag = ds18b20_init();
- if (flag)
- {
- #ifdef DEBUG
- printk(KERN_WARNING "ds18b20 init failed\n");
- #endif
- return -1;
- }
-
- write_byte(0xcc);
- write_byte(0x44);
-
- flag = ds18b20_init();
- if (flag)
- 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);
- }
-
- /**************************************************************
- * 字符驅動程序的核心,應用程序所調用的open,read等函數最終會
- * 調用這個結構中的對應函數
- *************************************************************/
- static struct file_operations ds18b20_dev_fops = {
- .owner = THIS_MODULE,
- .open = ds18b20_open,
- .read = ds18b20_read,
- };
-
- /******************************************************************************************************
- ** 函數名稱: ds18b20_setup_cdev()
- ** 函數功能: 初始化cdev
- ** 入口參數: dev:設備結構體; index:
- ** 出口參數: 無
- ** 備 注:
- ******************************************************************************************************/
- 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)
- {
- #ifdef DEBUG
- printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);
- #endif
- }
- }
-
- /******************************************************************************************************
- ** 函數名稱: ds18b20_dev_init()
- ** 函數功能: 為溫度傳感器分配注冊設備號,初始化cdev
- ** 入口參數: 無
- ** 出口參數: 若成功執行,返回0
- ** 備 注:
- ******************************************************************************************************/
- static int __init ds18b20_dev_init(void)
- {
- ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);
- if (ds18b20_major<0)
- {
- printk(DEVICE_NAME " Can't register major number!\n");
- return -EIO;
- }
-
- ds18b20_class = class_create(THIS_MODULE, DEVICE_NAME);
- device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEVICE_NAME);
- #ifdef DEBUG
- printk(KERN_WARNING "register ds18b20 driver successful!\n");
- #endif
- return 0;
- }
-
- /******************************************************************************************************
- ** 函數名稱: ds18b20_dev_exit()
- ** 函數功能: 注銷設備
- ** 入口參數: 無
- ** 出口參數: 無
- ** 備 注:
- ******************************************************************************************************/
- static void __exit ds18b20_dev_exit(void)
- {
- device_destroy(ds18b20_class, MKDEV(ds18b20_major,ds18b20_minor));
- class_unregister(ds18b20_class);
- class_destroy(ds18b20_class);
- unregister_chrdev(ds18b20_major, DEVICE_NAME);
- #ifdef DEBUG
- printk(KERN_WARNING "Exit ds18b20 driver!\n");
- #endif
- }
-
- module_init(ds18b20_dev_init);
- module_exit(ds18b20_dev_exit);
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("[email protected]");
- /******************************************************************************************************
- ** 文件到此結束
- ******************************************************************************************************/