Linux下ds18b20驱动

版权声明:转载请说明出处 https://blog.csdn.net/qq_33166886/article/details/85602472

ds18b20的单总线协议就不叙述了,就是一种规定,哪种信号表示一,哪种信号表示零,整个过程需要按怎样的步骤来,数据手册上一般都会说明,怎样去读写,这些都是规定死的东西 ,下面是我按照正点原子的例子修改过来的

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>

#define DQ_PIN 0

static struct class *cls;

int major;

volatile unsigned long *gpjcon;
volatile unsigned long *gpjdat;
volatile unsigned long *gpjup;

void DS18B20_IO_OUT(void)
{
    *gpjcon &= ~(3<<DQ_PIN);
    *gpjcon |=    (1<<DQ_PIN);
}
void DS18B20_DQ_OUT(int val)
{
    if(val)
        *gpjdat |=    (1<<(DQ_PIN/2));
    else
        *gpjdat &=    ~(1<<(DQ_PIN/2));
}
void DS18B20_IO_IN(void)
{
    *gpjcon &= ~(3<<DQ_PIN);
}
int DS18B20_DQ_IN(void)
{
    int ret;
    if((*gpjdat)&(1<<(DQ_PIN/2)))
        ret = 1;
    else
        ret = 0;
    return ret;
}
void DS18B20_Rst(void)       
{                 
    DS18B20_IO_OUT();     
    DS18B20_DQ_OUT(0);     
    udelay(750);        
    DS18B20_DQ_OUT(1);     
    udelay(15);         
}

unsigned char DS18B20_Check(void)        
{   
    unsigned char retry=0;
    DS18B20_IO_IN();     
    while (DS18B20_DQ_IN()&&retry<200)
    {
        retry++;
        udelay(1);
    };     
    if(retry>=200)return 1;
    else retry=0;
    while (!DS18B20_DQ_IN()&&retry<240)
    {
        retry++;
        udelay(1);
    };
    if(retry>=240)return 1;        
    return 0;
}

unsigned char DS18B20_Read_Bit(void)      
{
    unsigned char data;
    DS18B20_IO_OUT();     
    DS18B20_DQ_OUT(0); 
    udelay(2);
    DS18B20_DQ_OUT(1); 
    DS18B20_IO_IN();     
    udelay(12);
    if(DS18B20_DQ_IN())data=1;
    else data=0;     
    udelay(50);           
    return data;
}

unsigned char DS18B20_Read_Byte(void)     
{        
    unsigned char i,j,dat;
    dat=0;
    for (i=1;i<=8;i++) 
    {
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }                            
    return dat;
}

void DS18B20_Write_Byte(unsigned char dat)     
 {             
    unsigned char j;
    unsigned char testb;
    DS18B20_IO_OUT();     
    for (j=1;j<=8;j++) 
    {
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT(0);    // Write 1
            udelay(2);                            
            DS18B20_DQ_OUT(1);
            udelay(60);             
        }
        else 
        {
            DS18B20_DQ_OUT(0);    // Write 0
            udelay(60);             
            DS18B20_DQ_OUT(1);
            udelay(2);                          
        }
    }
}

void DS18B20_Start(void) 
{                                          
    DS18B20_Rst();       
    DS18B20_Check();     
    DS18B20_Write_Byte(0xcc);    // skip rom
    DS18B20_Write_Byte(0x44);    // convert
} 

 
unsigned char DS18B20_Init(void)
{
     DS18B20_IO_OUT();     
    DS18B20_DQ_OUT(1); 

    DS18B20_Rst();

    return DS18B20_Check();
}  

static int ds18b20_open(struct inode *inode, struct file *filp)  
{  
    if(DS18B20_Init()){
        printk("ds18b20 init failed\n\r");
        return -1;
    }
    printk("open ds18b20 successful\n");  
    return 0;  
}    

static ssize_t ds18b20_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos)  
{  
    unsigned long err;  
    unsigned char result[2] = { 0x00, 0x00 };  

    DS18B20_Start ();              // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();     
    DS18B20_Write_Byte(0xcc);    // skip rom
    DS18B20_Write_Byte(0xbe);    // convert        
    result[0]=DS18B20_Read_Byte();     // LSB   
    result[1]=DS18B20_Read_Byte();     // MSB  
 
    err = copy_to_user(buf, &result, sizeof(result));  
    return err ? -EFAULT : min(sizeof(result), count);  
}  
  
static struct file_operations ds18b20_dev_fops = {  
    .owner = THIS_MODULE,  
    .open = ds18b20_open,  
    .read = ds18b20_read,  
};  
  

  
static int __init ds18b20_dev_init(void)  
{  
    major = register_chrdev(0, "ds18b20", &ds18b20_dev_fops);

    cls = class_create(THIS_MODULE, "ds18b20");

    class_device_create(cls, NULL, MKDEV(major, 0), NULL, "ds18b20"); 

    gpjcon = (volatile unsigned long *)ioremap(0x560000d0, 12);
    gpjdat = gpjcon + 1;
    gpjup = gpjdat + 1;
    return 0;
}  
  
static void __exit ds18b20_dev_exit(void)  
{  
    class_device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);
    unregister_chrdev(major, "ds18b20");
    iounmap(gpjcon);
}  
  
module_init(ds18b20_dev_init);  
module_exit(ds18b20_dev_exit);  
MODULE_LICENSE("Dual BSD/GPL");  


猜你喜欢

转载自blog.csdn.net/qq_33166886/article/details/85602472