搜索
bottom↓
回复: 8

数字温度传感器DS18B20在嵌入式中的应用

[复制链接]

出0入0汤圆

发表于 2009-5-16 18:12:33 | 显示全部楼层 |阅读模式
毕业设计中使用ARM做智能家居,打算使用DS18B20检测温度,并利用CGI程序在网页中动态显示。遇到很多问题,总算完成了,以下是调试步骤。
DS18B20是DALLAS公司生产的数字温度传感器。使用1-Wire技术,即单总线。具有线路简单,精度高,体积小,低功耗的特点。
1、DS18B20产品的特点

  (1)、只要求一个端口即可实现通信。

  (2)、不需要外加器件。

  (3)、测量温度范围在-55℃到+125℃之间。

  (4)、数字温度计的分辨率用户可以从9位到12位选择。

  (5)、具有温度报警功能。

2、DS18B20在嵌入式应用中的难度
DS18B20的1-Wire技术,在减小体积方面有很好的作用,但是也增加了软件设计的复杂度。DS18B20的读写需要严格的读写时序。这种要求在单片机系统应用中比较容易实现。但是在嵌入式应用中就比较难办,因为嵌入式操作系统都是多任务的。用户程序随时都有可能被打断。
以下是我所做的驱动程序,测试程序,以及CGI程序。已在我所用的系统中调试通过。
所用开发环境: Red Hat Linux 9
编译器: arm-linux-gcc 3.4.1
Linux内核版本: kernel2.6.13
开发板: mini2440
网络服务器: Boa

//ds18b20.c DS18B20的驱动程序

//////////////////////////////////////////////////////////
//             //
//   ds18b20.c DS18B20的驱动程序   //
//        //
// 作者:xshbx 日期:2009.4.19    //
//////////////////////////////////////////////////////////
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "DS18B20"
#define DS18B20_MAJOR 229

#define DS_PIN S3C2410_GPF0
#define OUT S3C2410_GPF0_OUTP
#define IN S3C2410_GPF0_INP
#define DIS_UP 1
#define EN_UP 0


#define Search 0x00F0
#define Read_ROM 0x0033   //just for one
#define Skip_ROM 0x00CC  


#define Convert 0x0044
#define Write 0x004E   //TH---TL---Config
#define Read 0x00BE


#define bit_9 0x001F
#define bit_10 0x003F
#define bit_11 0x005F
#define bit_12 0x007F


#define uint16 unsigned int

//unsigned int ROM_DATA[8];

void usdelay(unsigned int i) //延时 i us 对于不同系统可能会有所差别,请适当修改
{
unsigned int j;
for(i=i;i>0;i--)
   for(j=90;j>0;j--);
}

void msdelay(unsigned int i) //延时 i us
{
for(i=i;i>0;i--)
   usdelay(1000);
}

void SetL(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,0);
}

void SetH(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,1);

}

unsigned int Read_DS(void)
{
unsigned int i;
s3c2410_gpio_cfgpin(DS_PIN,IN);
s3c2410_gpio_pullup(DS_PIN,EN_UP);
__asm("nop");
__asm("nop");
__asm("nop");
i=s3c2410_gpio_getpin(DS_PIN);
if(i!=0)
   i=1;
return i;
}


unsigned int ds_start(void)
{
unsigned int flag=1;int err=0;
SetL();
usdelay(500); //560
SetH();
usdelay(1);
while(Read_DS()!=0)
{
//   printk(DEVICE_NAME "Wait....\n");
   usdelay(5);
   err++;
   if(err==20)
   {
    printk(DEVICE_NAME "start fail\n");
    return -1;
   }
}
// printk(DEVICE_NAME "start sucess\n");

flag=0;
SetH();
usdelay(400);
return flag;
}
void ds_send(unsigned int uidata)
{
unsigned int i;
for(i=0;i<8;i++)
{
   SetL();
   if((uidata&1)!=0)
   {
    usdelay(3); //3
    SetH();
    usdelay(80);
   }
   else
   {
    usdelay(80);
    SetH();
    usdelay(5); //
   }
   uidata>>=1;
}
}
unsigned int ds_read(void)
{
unsigned int uidata=0;unsigned int i;
for(i=0;i<8;i++)
{
   SetL();
   usdelay(4); //2 3
   SetH();
   usdelay(7); //1 2 3 4 5(e)
   if(Read_DS()==1)
    uidata+=0x0100;
   uidata>>=1;
   SetH();
   usdelay(65);
}
return uidata;
}
void ds_init(unsigned int TH,unsigned int TL,unsigned int bit_nmb)
{
SetH();
usdelay(80);
if(ds_start()==0)
{
  
   ds_send(Skip_ROM);   //复位
   ds_send(Write);   //跳过ROM匹配
   ds_send(TH);   //TH
   ds_send(TL);   //TL
   ds_send(bit_nmb);   //转换位数
}
}
unsigned int read_tem(void)
{
unsigned int th,tl;int err=0;
ds_init(100,0,bit_12);
th=tl=0;
ds_start();
ds_start();
ds_start();
ds_send(Skip_ROM);
ds_send(Convert);
msdelay(50);
while(Read_DS()==0)
{
//   printk(DEVICE_NAME "Convert....\n");
   msdelay(50);
   err++;
   if(err==10)
   {
    printk(DEVICE_NAME "convert fail\n");
    return -1;
   }
}
ds_start();
ds_start();
ds_send(Skip_ROM);
ds_send(Read);
tl=ds_read();
th=ds_read();
ds_start();
ds_start();
th<<=8;
tl|=th;
return tl;
}
/*
void read_ROM(void)
{
unsigned int i;
ds_start();
ds_send(Read_ROM);
for(i=0;i<8;i++)
   ROM_DATA=ds_read();
}
*/


static int ds18b20_ioctl(

struct inode *inode,
struct file *file,
unsigned int cmd,unsigned long arg)
{
return 0;

}


static ssize_t ds18b20_read(struct file *pFile, uint16 __user *pData, size_t count, loff_t *off )

{

    uint16 tmp,ret;
   


    tmp =read_tem();
    ret=copy_to_user(pData, &tmp, sizeof(tmp));    //将读取得的DS18B20数值复制到用户区
if(ret>0)
{
   printk("copy data failed\n");
   return -1;
}

    return 0;

}


static struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.ioctl = ds18b20_ioctl,
.read = ds18b20_read,
};

static int __init ds18b20_init(void)
{
int ret;

ret = register_chrdev(DS18B20_MAJOR, DEVICE_NAME, &ds18b20_fops);
if (ret < 0) {
   printk(DEVICE_NAME " can't register major number\n");
   return ret;
}

devfs_mk_cdev(MKDEV(DS18B20_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);

s3c2410_gpio_cfgpin(DS_PIN, OUT);
s3c2410_gpio_setpin(DS_PIN, 1);

printk(DEVICE_NAME " initialized\n");
return 0;
}

static void __exit ds18b20_exit(void)
{

devfs_remove(DEVICE_NAME);
unregister_chrdev(DS18B20_MAJOR, DEVICE_NAME);
printk(DEVICE_NAME " rmmodule\n");
}

module_init(ds18b20_init);
module_exit(ds18b20_exit);

MODULE_AUTHOR("xshbx@126.com");             // 驱动程序的作者
MODULE_DESCRIPTION("DS18B20 Driver");   // 一些描述信息
MODULE_LICENSE("GPL");                              // 遵循的协议



//Test_ds.c DS18B20的测试程序

//////////////////////////////////////////////////////////
//             //
//   Test_ds.c DS18B20的测试程序   //
//        //
// 作者:xshbx 日期:2009.4.19    //
//////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>

#define K 0.0625

int main(void)

{

    int fd = -1;

    char count = 5;

    unsigned int tmp = 0;float res=0;


    fd = open("/dev/DS18B20", 0);

    if(fd < 0)

    {

        perror("Can't open /dev/DS18B20 \n");

        exit(1);

    }

    printf("open ds18b20 success \n");


        read(fd, &tmp , sizeof(tmp));
        printf("Tem %d \n",tmp);

res=tmp*K;
printf("the currently temperature is %f \n",res);

close(fd);

    return 0;
}


//Temperature.c DS18B20的CGI程序
//////////////////////////////////////////////////////////
//             //
// Temperature.c DS18B20的CGI程序    //
//        //
// 作者:xshbx 日期:2009.4.19    //
//////////////////////////////////////////////////////////


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//#include <linux/sched.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define K 0.0625

int main()
{
unsigned int tem=0;int fd;
float res=0;
printf("Content-type: text/html\n\n");
    printf("<HTML><HEAD><TITLE>温度监测</TITLE></HEAD>\n");
    printf("<BODY style=\"background-image: url(http://192.168.1.230/images/bj.jpg);\">\n");
printf("<br><br><br>\n");
printf("<H2>温度监测</H2><br>\n");


    fd = open("/dev/DS18B20", 0);

    if(fd < 0)

    {

        printf("Can't open /dev/DS18B20 <br><br><br>\n");
printf("返回主界面请点击<font size=\"6\">这里</font><br>\n");
    printf("</BODY></HTML>\n");
    fflush(stdout);

        exit(1);

    }


        read(fd, &tem , sizeof(tem));
res=tem*K;
close(fd);
  

printf("DS18B20返回值: %u <br><br>\n",tem);
printf("当前温度: %f <br><br><br><br>\n",res);
printf("返回主界面请点击<font size=\"6\">这里</font><br>\n");

    printf("</CENTER></BODY></HTML>\n");


    fflush(stdout);

    return 0;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-5-16 19:10:14 | 显示全部楼层
8错,不过不赞同在驱动程序中作此种严格的时序操作,我更愿意把这些操作和类似的其它功能放到一个单片机里去,然后用SPI之类的接口送到CPU上去

出0入0汤圆

发表于 2009-5-16 20:42:27 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2009-8-11 20:43:01 | 显示全部楼层
楼主的代码很严谨,值得学习!

出0入0汤圆

发表于 2009-8-11 22:24:51 | 显示全部楼层
有点深度,看不懂……

出0入0汤圆

发表于 2009-11-4 16:42:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-31 12:20:24 | 显示全部楼层
看不懂,要是多点注释就好了,呵呵。
头像被屏蔽

出0入0汤圆

发表于 2010-1-24 16:54:10 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽

出0入0汤圆

发表于 2010-1-24 16:55:39 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 21:48

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表