tiny6410温度传感器2(测试中)

 

/*tiny6410_temp.c,温度传感器驱动*/
#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;      
    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};  
      
    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("xinli_whut@163.com");  
/*****************************************文件到此结束  *****************************************************/    

/*驱动包含的头文件*/
#ifndef __S3C6410_GPIO_H__  
#define __S3C6410_GPIO_H__  
  
#include <linux/kernel.h>  
#include <linux/init.h>  
#include <linux/module.h> 
#include <linux/interrupt.h>  
#include <linux/ioport.h>  
#include <linux/gpio.h>  
#include <linux/io.h>  
#include <mach/hardware.h>  
#include <mach/map.h>   
#include <mach/regs-gpio.h>  
#include <mach/gpio-bank-n.h>  
#include <mach/regs-clock.h>   
#include <asm/irq.h>    
#include <plat/gpio-core.h>  
#include <plat/gpio-cfg.h>    
void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)  
{  
    //s3c_gpio_cfgpin(pin,function);  
        unsigned int tmp;   
        tmp = readl(S3C64XX_GPNCON);   
        tmp = (tmp & ~(3<<pin*2))|(function<<pin*2);  
        writel(tmp, S3C64XX_GPNCON);   
}  
  
void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)  
{  
        //s3c_gpio_setpull(pin,to);  
        unsigned int tmp;   
        tmp = readl(S3C64XX_GPNPUD);  
        tmp = (tmp & ~(3<<pin*2))|(to<<pin*2);   
        writel(tmp, S3C64XX_GPNPUD);   
}  
  
unsigned int s3c6410_gpio_getpin(unsigned int pin)   
{   
        unsigned int tmp;  
        tmp = readl(S3C64XX_GPNDAT);  
        tmp = tmp & (1 << (pin));     
        return tmp;   
}  
  
void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)  
{  
        unsigned int tmp;   
        tmp = readl(S3C64XX_GPNDAT);
        tmp &= ~(1 << (pin));  
        tmp |= ( (dat) << (pin) );  
        writel(tmp, S3C64XX_GPNDAT);
}  
  
#endif  

 

/******************************************Copyright(c)***************************** 
** 文件名称: ds18b20_test.c  
** 作    者: lixin  
** 版    本: v1.0  
** 说    明: ds18b20测试程序,精度:0.25度,如有需要,还可以进一步提高。  
** 修改记录: 2009-8-27创建  
** 最后修改时间: 2009-09-01  
*************************************************************************************/  
#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];           // 从ds18b20读出的结果,result[0]存放低八位  
    unsigned char integer_value = 0; 
    float temperature, decimal_value;  // 温度数值,decimal_value为小数部分的值  
    
    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); 
        // 精确到0.25度  
         decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);  
        temperature = (float)integer_value + decimal_value;  
        printf("The temperature is %6.2f\n",temperature);  
         
        if (i % 20 == 0) 
        printf("\n");  
        ds18b20_delay(50);  
    }  
}  
  
/************************************************************************************  
** 函数名称: ds18b20_delay()  
** 函数功能: 延时  
** 入口参数: i  
** 出口参数: 无  
** 备    注:  
************************************************************************************/  
void ds18b20_delay(int i)  
{  
    int j, k;  
    for (j = 0; j < i; j++)  
      for(k = 0; k < 50000; k++); 
 }  
/*********************************************************************************** 
**                                         文件到此结束  
*************************************************************************************/



 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值