ds18b20的时序图如下:
复位时序:
读写时序:
以下是程序代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/irq.h>
#include <linux/random.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <mach/gpio.h>
#include <linux/mutex.h>
#define GPH3_0CON 0xE0200C60
#define GPH3_0DAT 0xE0200C64
#define GPH3_0PUD 0xE0200C68
unsigned int *gpio_config;
unsigned char *gpio_data;
unsigned int *gpio_pud;
static struct class *fog_class; //´´½¨Àà
static struct class_device *fog_class_devs; //´´½¨Àà¶ÔÓ¦µÄÉ豸
int major;
struct mutex res_mutex;
void Ds18b20_Pin_Init(void)
{
unsigned int pin_val;
gpio_request(S5PV210_GPH3(0),"my_ds1802");
gpio_config = ioremap(GPH3_0CON,4);
gpio_data = ioremap(GPH3_0DAT,1);
gpio_pud = ioremap(GPH3_0PUD,2);
pin_val = readl(gpio_pud);
pin_val &=~(0x0003);
pin_val |= 0x2;
writel(pin_val,gpio_pud);
pin_val = readl(gpio_data);
writel(pin_val|0x1,gpio_data);
}
void DS18B20_OUT( unsigned char value)
{
if( value == 1)
{
gpio_direction_output( S5PV210_GPH3(0), 1);
}
else
{
gpio_direction_output( S5PV210_GPH3(0), 0);
}
}
unsigned char DS18B20_IN( void )
{
unsigned int pin_val;
gpio_direction_input( S5PV210_GPH3(0));
pin_val = readl(gpio_data);
return pin_val&0x1;
}
static void Init_DS18B20(void)
{
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(200);
gpio_direction_output( S5PV210_GPH3(0), 0);
udelay(600);
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(480);
}
static void WriteCode(unsigned char dat)
{
unsigned char temp,i;
for(i=0;i<8;i++)
{
temp = dat&0x01;
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(2);
gpio_direction_output( S5PV210_GPH3(0), 0);
if(temp == 0x01)
{
udelay(2);
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(100);
}else{
udelay(100);
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(3);
}
dat = dat>>1;
}
}
static void Reset_DS18B20( void )
{
gpio_direction_output( S5PV210_GPH3(0), 0);
udelay(500);
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(480);
}
static unsigned int ReadData(void)
{
unsigned int rec,data,i;
data = 0;
for(i=0;i<16;i++)
{
gpio_direction_output( S5PV210_GPH3(0), 0);
udelay(5);
udelay(3);
rec = DS18B20_IN();
udelay(20);
if(rec){
data |= 0x8000;
}else{
data &= 0x7fff;
}
if(i<15)
data >>=1;
udelay(20);
gpio_direction_output( S5PV210_GPH3(0), 1);
udelay(5);
}
return (data);
}
int ds18b20_open(struct inode *node, struct file *filp)
{
return 0;
}
static int ds18b20_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
int tem;
int ds_value;
mutex_lock_interruptible(&res_mutex);
Ds18b20_Pin_Init();
Init_DS18B20();
WriteCode(0xcc);
WriteCode(0x44);
gpio_direction_input( S5PV210_GPH3(0));
udelay(100);
tem = DS18B20_IN();
if(tem)
{
gpio_direction_output( S5PV210_GPH3(0), 1);
Reset_DS18B20();
WriteCode(0xcc);
WriteCode(0xbe);
ds_value = ReadData();
}else{
udelay(50);
ds_value = 0xaaaa;
}
mutex_unlock(&res_mutex);
copy_to_user(buffer, &ds_value, 4);
return sizeof ds_value;
}
static struct file_operations ds18b20_fops =
{
.open = ds18b20_open,
.read = ds18b20_read,
};
static int Ds18b20_init(void)
{
major = register_chrdev( 0,"ds18b20_drv", &ds18b20_fops );
fog_class = class_create(THIS_MODULE,"ds18b20_class");
fog_class_devs = device_create(fog_class,NULL,MKDEV(major,0),NULL,"my_ds1802");
mutex_init(&res_mutex);
printk("install module successed\n");
return 0;
}
void Ds18b20_exit(void)
{
unregister_chrdev( major, "ds18b20_drv" );
device_unregister(fog_class_devs);
class_destroy(fog_class);
}
module_init(Ds18b20_init);
module_exit(Ds18b20_exit);
MODULE_LICENSE("GPL");