S5PV210之温度传感器DS18B20 linux3.0.8驱动

发布者:Harmonious222最新更新时间:2024-12-31 来源: cnblogs关键字:S5PV210  温度传感器  DS18B20  linux3 手机看文章 扫描二维码
随时随地手机看文章

一 Ds18b20功能描述

 FEATURES(特点)

1) Unique 1-WireTM interface requires only oneport pin for communication

独特的单总线接口,使用一个引脚实现双线通线
2) Multidrop capability simplifies distributed temperature sensing applications

多分功能简化分布式温度传感器的应用
3) Requires no external components

不需要外部器件
4) Can be powered from data line.  Power supply range is 3.0V to 5.5V

可以从数据线获得电压。功作电源3-5.5V
5) Zero standby power required

不需要备用电源
6) Measures temperatures from -55°C to +125°C. Fahrenheit equivalent is -67°F to
+257°F 

测温范围:-55~+125°C, 等效于华氏温度范围:-67~257°F

7) ±0.5°C accuracy from -10°C to +85°C

-10~85°C范围的分辨率为±0.5°C
8) Thermometer resolution is programmable from 9 to 12 bits

可编程温度计分辨率范围9~12位(测量结果以9~12位数字量存储);
9) Converts 12-bit temperature to digital word in 750 ms (max.)
10) User-definable, nonvolatile temperature alarm settings
11) Alarm search command identifies and addresses devices whose temperature is
outside of programmed limits (temperature alarm condition)
12) Applications include thermostatic controls, industrial systems, consumer products,
thermometers, or any thermally sensitive system

 

二. Ds18b20时序分析

  ds18b20时序分为:复位时序,读时序,写时序。 

  最好按时序来编程,这样可以增强可移植性。

  具体的时序分析,网上或苡片资料上有。

  比如:ds18b20写时序

从上图可知,在前15us内首先把数据线拉低然后写0或1,然后ds18b20在15~60us间自动读取数据线的值。写该时序代码时,最好在15内向ds18b20数据线写值,并等待ds18b20反应30us以上。案例二上有说明。

三. 总结

案例一:总结:错在81行return((gpio_get_value(S5PV210_GPE0(3)) >> 3) & 0x01);
    导致读的值为0;
    原因:因为gpio_get_value(S5PV210_GPE0(3))函数返回的
    值为指定引脚的高或低电平,即1或0。

案例二:错误总结:

  错误部分:dat >>1;

       temp = gpio_get_value(S5PV210_GPE0(3) & 0x01);

       if ((ds18b20_back_value & 0x08) >> 3) 

  ds18b20读写函数中,没有按读写时序来写延时的时间。

正确写法:dat >>=1;

     temp = gpio_get_value(S5PV210_GPE0(3)) & 0x01;

     if ((init_DS18B20()) //因为gpio_get_value(S5PV210_GPE0(3))函数返回的
    值为指定引脚的高或低电平,即1或0。 

  最后按ds18b20的时序来解决上面时序的延时时间。那么就能在开发板上有正确的结果。

时序是很重要的,如果想这时序代码能在多平台上运用,最好延时取中值以上。

              
案例一:
mini210_ds18b20.c文件中:


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

#include   //其中copy_to*在其中

#include
#include
#include

spinlock_t lock;  //加不加这都 可以

#define DEVICE_NAME 'DS18B20'


void set_conIN(void)
{
    s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_INPUT);
    //gpio_set_value(S5PV210_GPE0(3), 1);    
}

void set_conOUT(void)
{
    s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_OUTPUT);
}

void set_data(int i)
{
    if (i == 0) {
        gpio_set_value(S5PV210_GPE0(3), 0);    
    }    else if(i == 1) {
        gpio_set_value(S5PV210_GPE0(3), 1);    
    }
}

unsigned int reset_ds18b20(void)
{
    unsigned int retValue;
  set_conOUT();

  set_data(1);
    __udelay(1);
    set_data(0);
    __udelay(600);
    set_data(1);
    __udelay(20);
    set_conIN();
    __udelay(100);
    /*稍做延时后 如果x=0则初始化成功
    x=1则初始化失*/
    //retValue = (gpio_get_value(S5PV210_GPE0(3)) >> 3) & 0x01;
    retValue = gpio_get_value(S5PV210_GPE0(3));
    printk('init is %dn',retValue);
    return retValue;
}

unsigned int read_bit(void)
{
    spin_lock(&lock);
    set_conOUT();
    set_data(0);
    __udelay(2);
    set_conIN();
    __udelay(1);    
    spin_unlock(&lock);
    return(gpio_get_value(S5PV210_GPE0(3)) & 0x01);
    //return((gpio_get_value(S5PV210_GPE0(3)) >> 3) & 0x01);
}

/*写一位命令*/
void write_bit(char bitValue)
{
    spin_lock(&lock);
    set_conOUT();
    set_data(0);
    __udelay(15);
    if( bitValue == 1 ){
        set_data(1);
    }else{
        set_data(0);
    }
    spin_unlock(&lock);
    __udelay(45);
    set_conIN();
    __udelay(2);
}

/*写命令*/
void write_cmd(char cmd)
{
  unsigned char i;
  unsigned char temp;

  for(i=0; i<8;i++){
    temp = cmd>>i;
    temp &= 0x01;
    write_bit(temp);
  }
  //__udelay(10);
}

static int ds18b20_open(struct inode *inode, struct file *filp)
{
    printk (KERN_INFO 'Device openedn');
    spin_lock_init(&lock);
    return 0;
}

 /*读取数据*/
static int ds18b20_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
{
  char lowValue=0,highValue=0;
  unsigned int i;
  int wendu_value;
  //float value;

    if(reset_ds18b20()){
      printk('init errorn');
  }
  __udelay(400);
  set_conOUT();
  set_data(1);
  write_cmd(0xCC);
  write_cmd(0x44);
  __udelay(100000);

  if(reset_ds18b20()){
     printk('init errorn');
  }
  __udelay(400);
  set_conOUT();
  set_data(1);
  write_cmd(0xcc);
  write_cmd(0xBE);
  /*读取温度转化数值*/

  for(i=0; i<8; i++){
    if( read_bit() ){
        lowValue |= (0x01<    }
    __udelay(62);
  }
  printk('lowValue is %dn',lowValue);
  for(i=0; i<8; i++){
    if( read_bit() ){
        highValue |= (0x01<    }
    __udelay(62);
  }
  printk('highValue is %dn',highValue);

  if((highValue & 0xf8) != 0x00) {
        lowValue = (~lowValue) + 1;
        
        if (lowValue > 255)
            highValue = (~highValue) + 1;
    }
    wendu_value = (highValue * 16 + lowValue/16) + ((lowValue%16)*10/16);
    
    printk('read_wendu--dat_L: %d    dat_H: %d    wendu: %d.%dn', lowValue, highValue,
        wendu_value - ((lowValue%16)*10/16), ((lowValue%16)*10/16));
 
#if 0
  i = highValue;
  i <<= 8;
  i = i|lowValue;
  value = i*0.0625;
  printk('kernel is %dn',value);
#endif

  highValue <<= 4;
  highValue |= ((lowValue&0xf0)>>4) ;
 
  copy_to_user(buffer, &highValue, sizeof(highValue));

  /*拷贝内核数据到用户空间*/
  //copy_to_user(buffer, &highValue, sizeof(highValue));
  return 0;
}
/*写命令,在此置空*/
static int ds18b20_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
    return 0;
}

static int ds18b20_release(struct inode *inode,struct file *filp)
{
    printk (KERN_INFO 'device closedn');
    return 0;
}

static long ds18b20_ioctl(struct file *filp, unsigned int cmd,
        unsigned long arg)
{
    return 0;
}

static struct file_operations ds18b20_fops = {
    .owner            = THIS_MODULE,
    .open    =    ds18b20_open,
    .read = ds18b20_read,
    .write = ds18b20_write,
    .unlocked_ioctl    = ds18b20_ioctl,
    .release = ds18b20_release,
};

static struct miscdevice ds18b20_dev = {
    .minor            = MISC_DYNAMIC_MINOR,
    .name            = DEVICE_NAME,
    .fops            = &ds18b20_fops,
};

static int __init ds18b20_dev_init(void) {
    int ret;
    int i;

    ret = gpio_request(S5PV210_GPE0(3), 'DS18b20');
    if (ret) {
        printk('%s: request GPIO %d for LED failed, ret = %dn', DEVICE_NAME,
            S5PV210_GPE0(3), ret);
        return ret;

        s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_OUTPUT);
        gpio_set_value(S5PV210_GPE0(3), 1);
    }

    ret = misc_register(&ds18b20_dev);

    printk(DEVICE_NAME'tinitializedn');

    return ret;
}

static void __exit ds18b20_dev_exit(void) {
    int i;

    for (i = 0; i < 1; i++) {
        gpio_free(S5PV210_GPE0(3));
    }

    misc_deregister(&ds18b20_dev);
}

module_init(ds18b20_dev_init);
module_exit(ds18b20_dev_exit);

MODULE_LICENSE('GPL');
MODULE_AUTHOR('mingLi.');

 

案例二:

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

#include   //其中copy_to*在其中

#include
#include
#include

spinlock_t lock;  //不用也行

#define DEVICE_NAME 'DS18B20'

//********************************
//功能:设置引脚为输入功能
//********************************
void set_con_in(void)
{
    s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_INPUT);
    //gpio_set_value(S5PV210_GPE0(3), 1);    
}

//********************************
//功能:设置引脚为输出功能
//********************************
void set_con_out(void)
{
    s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_OUTPUT);
}


//********************************
//功能:引脚输出高或低电平功能,i=1(高)
//********************************

void set_output_data(int i)
{
    if (i == 0) {
        gpio_set_value(S5PV210_GPE0(3), 0);    
    }    else if(i == 1) {
        gpio_set_value(S5PV210_GPE0(3), 1);    
    }
}

//********************************
//功能:ds18b20复位
//********************************
int init_DS18B20(void)
{
    int result = 10;
    set_con_out();
    __udelay(3);    //短时间延迟
    set_output_data(1);
    __udelay(3);    //短时间延迟
    set_output_data(0);
    __udelay(550); //480-960us

    set_output_data(1);
    __udelay(20); //15-60us,最好大于15us

    set_con_in();
    __udelay(100); //60-240us, ds18b20回应值保持时间
    result = gpio_get_value(S5PV210_GPE0(3));
    printk('init_DS18B20--result:%dn', result);

    set_con_out();
    __udelay(3);
    set_output_data(1);
    //__udelay(300);

    return result;
    
}

//*************************************
//功能:从ds18b20读一个字节的数据
//*************************************
unsigned char read_one_char(void)
{
    unsigned char i = 0;
    unsigned char dat = 0;
    unsigned char temp = 0;

    spin_lock(&lock);

    //苡片手册上说写周期不少于60us
    //但时从时序图可知少于60us也行
    //或者取中值左右,最好是大于60us

    //for (i=8; i > 0; i--) {
    for(i=0; i<8; i++) {
        set_con_out();
        __udelay(3);
        set_output_data(1);
        dat >>= 1;
        /*set_output_data(0);     //++    
        __udelay(3);
        set_output_data(1); //将数据线'人为'拉高,为单片机检测DS18B20的输出电平作准备
        __udelay(3);
        */
        //
        set_output_data(0); //该行与下行等效该行上面的4行
        __udelay(18);  //按时序来延时,不能太小或太大
        
        set_con_in();
        __udelay(1);
        //temp = gpio_get_value(S5PV210_GPE0(3) & 0x01);  
        //错在S5PV210_GPE0(3)后面少加')'
        temp = gpio_get_value(S5PV210_GPE0(3)) & 0x01;
        if (temp)
            dat |= 0x80;
        else
            dat |= 0x00;
        
        printk('read_one_char--temp: %dn', temp);
        __udelay(65);    
        
    }
    spin_unlock(&lock);
    printk('read_one_char--dat: %dn', dat);

    return dat;
    
}

//*************************************
//功能:向ds18b20写一个字节的数据
//*************************************
void write_one_char(unsigned char dat)
{
    //printk('write_one_char--dat: %dn', dat);
    unsigned char i = 0;

    spin_lock(&lock);
    set_con_out();

    for(i=0; i<8; i++) {

        set_output_data(1);
        __udelay(1);
        
        set_output_data(0);
        __udelay(5);    
        set_output_data(dat & 0x01);
        __udelay(55);//延时约55us,DS18B20在拉低后的约
                //15~60us期间从数据线上采样
                //最好取中值以上,太小可得会出错
                //芯片手册上说一个写周期不少于60us
                //但我使用时,少于60us也可以,
                //但不能太小,一般中值以上
                //总结:为能可移值性,
                //最好是一个写周期在于60us
                
        set_output_data(1);
        __udelay(2);
        dat >>= 1;    
    }
    spin_unlock(&lock);
    __udelay(30);
}

//********************************
//功能:读取ds18b20的温度
//********************************
unsigned int read_wendu(void)
{
    unsigned char dat_L = 0, dat_H = 0;
    unsigned int wendu_value;
    int ds18b20_back_value;
    
    ds18b20_back_value  = init_DS18B20();
    //if ((ds18b20_back_value & 0x08) >> 3)  //错,init_DS18B20()返回值为0或1
    if (ds18b20_back_value)
        printk('ds18b20 init error!!!n');
    else
        printk('ds18b20_back_value %dn', ds18b20_back_value);
    write_one_char(0xCC);
    write_one_char(0x44);
    
    if (init_DS18B20())
        printk('ds18b20 init error!!!n');
    else
        printk('ds18b20 init ok n');
    write_one_char(0xcc);
    write_one_char(0xBE);

    dat_L = read_one_char();
    dat_H = read_one_char();

    if((dat_H & 0xf8) != 0x00) {
        dat_L = (~dat_L) + 1;
        
        if (dat_L > 255)
            dat_H = (~dat_H) + 1;
    }
    wendu_value = (dat_H * 16 + dat_L/16) * 10 +((dat_L%16)*10/16);
    
    printk('read_wendu--dat_L: %d    dat_H: %d    wendu: %d.%dn',dat_L, dat_H,
        wendu_value/10, wendu_value%10);
    return(wendu_value);
    //return (dat_H*256 + dat_L);
}

static int ds18b20_open(struct inode *inode, struct file *filp)
{
    printk (KERN_INFO 'Device openedn');
    spin_lock_init(&lock);
    return 0;
}

 /*读取数据*/
static int ds18b20_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
{
    unsigned int wendu_value = 0;

    wendu_value = read_wendu();
    printk('wendu_valu is %ldn', wendu_value);

    copy_to_user(buffer, &wendu_value, sizeof(wendu_value));

    return 0;
    
}
/*写命令,在此置空*/
static int ds18b20_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
    return 0;
}

static int ds18b20_release(struct inode *inode,struct file *filp)
{
    printk (KERN_INFO 'device closedn');
    return 0;
}

static long ds18b20_ioctl(struct file *filp, unsigned int cmd,
        unsigned long arg)
{
    return 0;
}

static struct file_operations ds18b20_fops = {
    .owner            = THIS_MODULE,
    .open    =    ds18b20_open,
    .read = ds18b20_read,
    .write = ds18b20_write,
    .unlocked_ioctl    = ds18b20_ioctl,
    .release = ds18b20_release,
};

static struct miscdevice ds18b20_dev = {
    .minor            = MISC_DYNAMIC_MINOR,
    .name            = DEVICE_NAME,
    .fops            = &ds18b20_fops,
};

static int __init ds18b20_dev_init(void) {
    int ret;
    int i;

    ret = gpio_request(S5PV210_GPE0(3), 'DS18b20');
    if (ret) {
        printk('%s: request GPIO %d for GPE0 failed, ret = %dn', DEVICE_NAME,
            S5PV210_GPE0(3), ret);
        return ret;

        s3c_gpio_cfgpin(S5PV210_GPE0(3), S3C_GPIO_OUTPUT);
        gpio_set_value(S5PV210_GPE0(3), 1);
    }

    ret = misc_register(&ds18b20_dev);

    printk(DEVICE_NAME'tinitializedn');

    return ret;
}

static void __exit ds18b20_dev_exit(void) {
    int i;

    for (i = 0; i < 1; i++) {
        gpio_free(S5PV210_GPE0(3));
    }

    misc_deregister(&ds18b20_dev);
}

module_init(ds18b20_dev_init);
module_exit(ds18b20_dev_exit);

MODULE_LICENSE('GPL');
MODULE_AUTHOR('mingli.');

[1] [2]
关键字:S5PV210  温度传感器  DS18B20  linux3 引用地址:S5PV210之温度传感器DS18B20 linux3.0.8驱动

上一篇:S5PV210的开发与学习:2.2 UBOOT学习笔记(零距离初体验uboot)
下一篇:tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——移植u-boot.bin(打印串口控制台)

推荐阅读最新更新时间:2026-03-20 11:04

S5PV210温度传感器DS18B20 linux3.0.8驱动
一 Ds18b20功能描述  FEATURES(特点) 1) Unique 1-WireTM interface requires only oneport pin for communication 独特的单总线接口,使用一个引脚实现双线通线 2) Multidrop capability simplifies distributed temperature sensing applications 多分功能简化分布式温度传感器的应用 3) Requires no external components 不需要外部器件 4) Can be powered from data line. Power supply range is
[单片机]
STC8H开发(十一): GPIO单线驱动多个DS18B20数字温度计
DS18B20 参数 单线总线结构, 允许一根总线上挂接多个 DS18B20 并分别通信 在普通温度下, 可以直接从数据口取电, 这时候只需要两根连线. 供电电压 温度检测范围 摄氏度, 华氏度 精确率: 在 为 ±0.5°C Pin脚 一般见到的都是3pin的To-92封装, 和普通三极管一样, 使平面朝向自己, Pin脚朝下, 从左往右依次为: GND, DQ, VDD 内部存储结构 DS18B20内部有9字节的暂存器和3个字节的EEPROM存储, EEPROM可以擦写5万次以上. 结构如下 测温 DS18B20的核心功能就是数字化的温度读数, 可以设置为9, 10, 11, 12位分辨率, 缺省分辨率是12位.
[单片机]
STC<font color='red'>8</font>H开发(十一): GPIO单线<font color='red'>驱动</font>多个<font color='red'>DS18B20</font>数字温度计
STM8L 151G6U6 驱动RW1820温度传感器
兼容DS18B20以及RW1820(VDD=2.8V)版本 #define RW1820_DQ_OUT GPIO_Init(GPIOC, GPIO_PIN_2,GPIO_Mode_Out_OD_HiZ_Slow); //输出 #define RW1820_DQ_IN GPIO_Init(GPIOC, GPIO_PIN_2, GPIO_Mode_In_PU_No_IT); //输入 #define RW1820_DQ_HIGH GPIO_SetBits(GPIOC, GPIO_PIN_2); //拉高 #define RW1820_DQ_LOW GPIO_ResetBits(GPIOC, GPIO_PI
[单片机]
基于DS18B20温度传感器的51单片机精确测量教程
一、引言 嘿,朋友!今天咱们要一起玩个超有趣的东西,就是用 51 单片机和 DS18B20 温度传感器来测量温度,并且把温度值显示出来,还保留一位小数呢。这就好比你有一个小管家(51 单片机)和一个小温度计(DS18B20),小管家负责指挥,小温度计负责测量温度,最后把温度显示在一个小屏幕(数码管)上,是不是很有意思? 二、概念解释 1. 51 单片机 51 单片机就像是一个聪明的小管家,它能接收各种指令,然后按照指令去做事情。它有很多小房间(引脚),可以和其他东西(比如传感器、数码管)连接,通过这些连接来传递信息和控制其他东西。 2. DS18B20 温度传感器 DS18B20 就像是一个小温度计,它能感知周围的温度,并
[单片机]
51单片机学习:DS18B20温度传感器实验
实验名称:DS18B20温度传感器实验 接线说明: 实验现象:下载程序后,插上DS18B20温度传感器,数码管显示检测的温度值 注意事项:注意温度传感器的方向,在接口处我们已经用丝印画了一个凸起, 所以只需要将温度传感器对应插入即可 ***************************************************************************************/ #include public.h #include smg.h #include ds18b20.h /***********************************************************
[单片机]
STM8L 控制温度传感器DS18B20
#define DS18B20_GPIO_PORT (GPIOC) #define DS18B20_GPIO_PIN (GPIO_Pin_2) #define DS18B20_PIN_SET_OUT() GPIO_Init(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN, GPIO_Mode_Out_PP_High_Fast) #define DS18B20_PIN_SET_IN() GPIO_Init(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN, GPIO_Mode_In_PU_No_IT) #
[单片机]
基于ARM和DS18B20设计网络化的智能温度传感器
1 网络化智能传感器简介 网络化智能传感器使传感器由单一功能、单一检测向多功能和多点检测发展;从被动检测向主动进行信息处理方向发展;从就地测量向远距离实时在线测控发展。网络化使得传感器可以就近接入网络,传感器与测控设备间再无需点对点连接,大大简化了连接线路,易于系统的维护和扩充。网络化智能传感器一般由信号采集单元、数据处理单元和网络接口单元组成。这3个单元可以是采用不同芯片构成合成式的,也可以是单片式结构。网络化智能传感器的核心便是嵌入式微处理器。嵌入式微处理器具有体积小、功耗低、可靠性高、可抗干扰能力强等特点。本系统就是采用嵌入式微处理器作为核心,使用数字式的温度传感器作为采集单元。系统设计中采用的是信息技术领域最新的B/S(B
[单片机]
基于ARM和<font color='red'>DS18B20</font>设计网络化的智能<font color='red'>温度传感器</font>
数字温度传感器DS18B20在变电站测温的应用
一 概述 温度是一种最基本的环境参数,与人民生活和工农业生产有着密切的关系,在电力供应中离不开温度测量。液压操作动机的断路器是电网的重要设备,保证断路器液压操作机构油路的正常运转对保证电网安全具有重要意义。当环境温度降低到一定程度后,断路器的油路流动受到影响,液压油黏度增大不利于油路的流动,影响断路器的特性。正常情况下,该装置显示当时温度值。当气温升高或降低到规定值时,此装置会立即自动安全关闭或打开加温装置,防止发生事故,是变电站不可缺少的保护装置。因此研究温度的测量方法和测量装置在实际生产中有着重要的意义。 测量温度的关键是温度传感器。随着技术飞速发展,传感器已进入第三代数字传感器。本测温系统采用的DS18B20就是属于
[单片机]
数字<font color='red'>温度传感器</font><font color='red'>DS18B20</font>在变电站测温的应用
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved