Ubuntu下编写ds18b20驱动程序

本程序是在大三实习阶段的时候写的一个驱动程序,当时对于驱动程序的理解不是很彻底,只是在别人的框架下自己去填写代码,先把ds18b20的时序图读懂,照着时序图写代码就可以了,但是要注意的就是时序图中的延时问题,在满足要求的情况下,尽量延时长一点!!!写驱动程序还有一点很重要的就是会自己测试程序,要在能尽可能的测试到驱动程序最容易出错的地方。


1.以下是驱动程序代码:

注:本程序在飞凌OK6410开发板上测试通过,其它的开发板也一样,只要做很少的改动应该就可以运行,不过,本程序只实现了一块ds18b20的情况,比较简单。多块的情况也可以通过芯片手册做一定的改动,不过,我没试过。

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>


#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>


#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-m.h>


#define DEVICE_NAME "ds18b20"


unsigned int tmp;


int output_mode(void)
{
    tmp=readl(S3C64XX_GPECON);
    tmp&=(~0x0F);
    tmp|=0x01;
    writel(tmp,S3C64XX_GPECON);
    return 0;
}


int input_mode(void)
{
    tmp=readl(S3C64XX_GPECON);
    tmp&=(~0x0F);
    tmp|=0x00;
    writel(tmp,S3C64XX_GPECON);
    return 0;
}


int output_bit(unsigned int bit)
{
tmp=readl(S3C64XX_GPEDAT);
    tmp&=(~0x01);
    tmp|=bit;
    writel(tmp,S3C64XX_GPEDAT);
return 0;
}


unsigned int input_bit(void)
{
    tmp=readl(S3C64XX_GPEDAT);
    tmp&=0x01;
//    printk("In Input_bit tmp is %d\n",tmp);
return tmp;
}


int init_DS18B20(void)
{

    unsigned int tp=0;


    int waittime=10;
    output_mode();
    output_bit(1);
    output_bit(0);
    udelay(480);
    input_mode();
    udelay(15);
    tp=input_bit();
    while(1)
    {
        if(!tp||waittime>500)
                  break; 
        udelay(5);
        waittime+=5;
        tp=input_bit();
       // printk("tp is %d\n",tp);
    }


    if(!tp)
    {
         udelay(480);
         output_mode();
         output_bit(1);
         printk("Init Success\n");
         return 0;
    }
    else 
    {
         printk("Failed\n");
         return -1;
    }
}


int write_to_DS18B20(unsigned char byte)
{
    unsigned  char  i,k;
         for(i=0;i<=7;i++)
         {
                         
            k=(byte>>i)&(0x01);
            if(k==1)
            {
                output_mode();
                output_bit(1);
                output_bit(0);
                udelay(1);
                input_mode();
                udelay(45);
            }
            else
            {
                output_mode();
                output_bit(1);
                output_bit(0);
                udelay(60);
                input_mode();
            }
        }
return 0;
}


unsigned char read_from_DS18B20(void)
{

         unsigned int i,j;
         unsigned char byte=0x00;
         for(i=0;i<=7;i++)
         {
                          output_mode();
                          output_bit(1);
                          output_bit(0);
                          udelay(1);
                          input_mode();
                          udelay(10);
                          j=input_bit();
                          if(j==1)
                             byte|=1<<i;
                          udelay(45);
         }
   return byte;
}


int config_DS18B20(void)
{
init_DS18B20();      //initialization *********************
write_to_DS18B20(0xCC);   //skip rom
write_to_DS18B20(0x4E);   //write scratchpad
write_to_DS18B20(0x55);   //set TH 85
write_to_DS18B20(0x00);   //set TL 0
write_to_DS18B20(0x1F);   //Resolution: set 9 bit, (0.5)
return 0;
}


unsigned short get_temperature(void)
{
unsigned char LSB;
unsigned char MSB;
unsigned short t;
    init_DS18B20();
//    udelay(120);
    write_to_DS18B20(0xcc);
    write_to_DS18B20(0x44);
 //   udelay(5);
    init_DS18B20();
  //  udelay(200);
    write_to_DS18B20(0xcc);
    write_to_DS18B20(0xbe);
    LSB=read_from_DS18B20();
    MSB=read_from_DS18B20();
    t=MSB*256+LSB;
  //  printk("MSB is %d LSB is %d\n",MSB,LSB);
return t;
}


static long s3c64xx_temperature_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned short temp = 0;
temp = get_temperature();
 //   printk("The Temperature is %d\n",temp);
return temp;
}


static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl= s3c64xx_temperature_ioctl,
};


static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};


static int __init dev_init(void)
{
int ret;
config_DS18B20();


ret = misc_register(&misc);//注意使用混杂设备注册可以减少很多不必要的初始化
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}


static void __exit dev_exit(void)
{
misc_deregister(&misc);
}


module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chenjun");

2.驱动程序的Makefile如下:

obj:
make -C /shell/linux-2.6.36.2-v1.05/  SUBDIRS=/shell/ds18b20/  modules

注: /shell/linux-2.6.36.2-v1.05/  是我用的linux的内核目录
驱动程序所在目录:SUBDIRS=/shell/ds18b20/ 
以模块的方式加载:modules


3.以下是测试程序代码:
#include    <unistd.h>
#include    <signal.h>
#include    <stdlib.h>
#include    <sys/types.h>
#include    <sys/stat.h>
#include    <fcntl.h>
#include    <stdio.h>
#include    <string.h>
#include     <time.h>
#include     <sys/time.h>
#include     <sys/mman.h>


#define  EPS 0.5
#define np 0.0625


void warn(int fd);
int main()
{
    int fd,old,new,led;
    double result=0;
    if ((fd=open("/dev/ds18b20",O_RDWR)) < 0)
    {
        printf("Open Device DS18B20 failed.\r\n");
        exit(1);
    }


    if ((led=open("/dev/leds",O_RDONLY)) < 0)
    {
        printf("Open Device leds failed.\r\n");
        exit(1);
    }


    old=new=0; 
    while(1)
    {
      new=ioctl(fd,0,0);
        if(fabs((abs(old-new)*np))>EPS)
        { 
            warn(led);
        }
        result=(double)new*np;
        printf("%.2lf \n", result);
        sleep(1);
        old=new;
    }


    close(fd);
    return 0;
}
void warn(int fd)
{
    int i,t;
   for(i=0;i<40;i++)
   {
        t=i&1;
        ioctl(fd, t, 0);
        ioctl(fd, t, 1); 
        ioctl(fd, t, 2); 
        ioctl(fd, t, 3); 
        usleep(5000);
  }
}


注:
以上的测试程序在一定程度上有点Bug,由于实习完后,没有开发板了,所以没有再做修改。也没有测试了。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值