我用的是FL2440开发板查看好datasheet后找到相应的管脚写的platform 总线编写
/*********************************************************************************
* Copyright: (C) 2016 guanlei
* All rights reserved.
*
* Filename: myds18b20.c
* Description: This file
*
* Version: 1.0.0(2016年04月11日)
* Author: guanlei <995318056@qq.com>
* ChangeLog: 1, Release initial version on "2016年04月11日 14时56分25秒"
*
********************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#define DEV_NAME "ds18b20"
#ifndef DEV_MAJOR
#define DEV_MAJOR 0 /* dynamic major by default */
#endif
#define DS18B20_PIN S3C2410_GPG(0)
#define DS18B20_PIN_OUT S3C2410_GPIO_OUTPUT
#define DS18B20_PIN_IN S3C2410_GPIO_INPUT
typedef unsigned char BYTE;
dev_t devno;
MODULE_LICENSE("GPL");
static int dev_major = DEV_MAJOR;
static int dev_minor = 0;
struct cdev my_cdev;
static struct class *ds18b20_class;
BYTE data[2];
static struct platform_device s3c2440_ds18b20_device ={
.name = "s3c2440_ds18b20",
.id = 1,
.dev ={
},
};
unsigned char ds18b20_reset(void)
{
s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);/* config output mode */
s3c2410_gpio_setpin(DS18B20_PIN,1);/* send high and keep 100us */
udelay(100);
s3c2410_gpio_setpin(DS18B20_PIN,0) ;/* send low and keep 600us */
udelay(600);
s3c2410_gpio_setpin(DS18B20_PIN, 1); // 向18B20发送一个上升沿,此时可释放DS18B20总线
udelay(100);
// 通过再次配置GPIG0引脚成输入状态,可以检测到DS18B20是否复位成功
s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_IN);
if(s3c2410_gpio_getpin(DS18B20_PIN))
{
printk("DS18b20 reset failed.\r\n");
return 1;
}
printk("reset successed!\n");
return 0;
}
void ds18b20_write_byte(unsigned char byte)
{
unsigned char i;
s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);
/* write 1
* keep low 1us-15us
* then keep bus high 15us - 60us
*
* write 0
* keep low 15us - 60us
* then keeep bus high 1us - 15us
*/
for (i=0;i<8;i++)
{
s3c2410_gpio_setpin(DS18B20_PIN,0);
/* 每次写之后延时 1us */
udelay(1);
/* write 1 or 0 */
s3c2410_gpio_setpin(DS18B20_PIN,(byte&0x01)?1:0);
udelay(60);
/* release bus */
s3c2410_gpio_setpin(DS18B20_PIN,1);
byte >>= 1;
udelay(15);
}
s3c2410_gpio_setpin(DS18B20_PIN, 1); //释放总线
}
unsigned char ds18b20_read_byte(void )
{
unsigned char i ;
unsigned char dat = 0 ;
for(i=0;i<8;i++)
{
s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);
s3c2410_gpio_setpin(DS18B20_PIN,0); /* give a maicohong */
dat >>= 1;
udelay(1);
s3c2410_gpio_setpin(DS18B20_PIN,1); /* */
s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_IN);
if(s3c2410_gpio_getpin(DS18B20_PIN))
{
dat |= 0x80;
}
udelay(60);
}
return dat;
}
static int ds18b20_open(struct inode *inode, struct file *file)
{
printk("open ds18b20");
return 0;
}
static int ds18b20_read(struct file *filep,char *buff ,size_t len ,loff_t *offp)
{
//unsigned char temp_flag; /* above zero or below zero */
// unsigned short temp;
int err;
ds18b20_reset(); /* reset */
udelay(120);
ds18b20_write_byte(0xcc);//写入CCH命令,跳过读序列号过程;
ds18b20_write_byte(0x44);//写入44H命令,开始温度转换,延时5 ms;
udelay(5);
ds18b20_reset();
udelay(200);
ds18b20_write_byte(0xcc);//写入CCH命令,跳过读序列号过程;
ds18b20_write_byte(0xbe); //写入BEH命令,读取寄存器;
data[0] = ds18b20_read_byte(); //温度的整数部分
data[1] = ds18b20_read_byte(); //温度的小数部分
/*
temp = ((unsigned char)data[0]) << 8;
temp |=(unsigned char)data[1];
temp = 0.0625*((double)temp);
*/
err = copy_to_user(buff,(void *)data,len);
return err? -EFAULT:len ;
}
static struct file_operations ds18b20_ops = {
.owner = THIS_MODULE,
.read = ds18b20_read,
//.release = ds18b20_release,
};
static int s3c2440_ds18b20_probe(struct platform_device *pdev)
{
int ret ,err,result;
/*alloc the device for device */
if( 0 != dev_major)
{
devno = MKDEV(dev_major,dev_minor);
result = register_chrdev_region(devno,1,DEV_NAME);
}
else
{
result = alloc_chrdev_region(&devno,dev_minor,1,DEV_NAME);
dev_major = MAJOR(devno);
}
/* alloc for device major failure */
if(result<0)
{
printk("alloc_chdrev_region error");
printk("%s driver can't get major %d\n", DEV_NAME, dev_major);
return result;
}
printk("%s driver get major %d\n", DEV_NAME, dev_major);
/* init ds18b20_device and register cdev */
cdev_init (&my_cdev,&ds18b20_ops);
my_cdev.owner = THIS_MODULE;
err = cdev_add(&my_cdev,devno,1);
if(err<0)
{
printk("cdev error");
goto ERROR;
}
/* creat device node */
ds18b20_class = class_create(THIS_MODULE,DEV_NAME);
if(IS_ERR(ds18b20_class))
{
printk("Err:failed in ds18b20_class\n");
goto ERROR;
}
device_create(ds18b20_class,NULL,devno,NULL,DEV_NAME);
printk(DEV_NAME"initialized\n");
return 0;
ERROR:
printk("s3c %s driver version %d=dev_major,%d=dev_minor install failure",DEV_NAME,DEV_MAJOR,dev_minor);
cdev_del(&my_cdev);
unregister_chrdev_region(devno,1);
return -1;
}
static void __exit s3c2440_ds18b20_remove(void)
{
cdev_del(&my_cdev);
unregister_chrdev_region(devno,1);
class_destroy(ds18b20_class);
device_destroy(ds18b20_class,devno);
}
static struct platform_driver s3c2440_ds18b20_driver ={
.probe = s3c2440_ds18b20_probe,
.remove = s3c2440_ds18b20_remove,
.driver = {
.name = "s3c2440_ds18b20",
.owner = THIS_MODULE,
},
};
static int __init s3c2440_ds18b20_init ( void )
{
int ret = 0;
ret = platform_device_register(&s3c2440_ds18b20_device);
if(ret)
{
printk("cant not register platform__device_register");
goto fail_reg_plat_dev;
}
ret = platform_driver_register(&s3c2440_ds18b20_driver);
if(ret)
{
printk("cant not register platform_driver_register");
goto fail_reg_plat_drv;
}
printk("initial") ;
return ret;
fail_reg_plat_drv:
platform_driver_unregister(&s3c2440_ds18b20_driver);
return -1;
fail_reg_plat_dev:
return ret ;
}
static void s3c2440_ds18b20_exit(void)
{
platform_driver_unregister(&s3c2440_ds18b20_driver);
}
module_init(s3c2440_ds18b20_init);
module_exit(s3c2440_ds18b20_exit);
相应的MAKEFILE
CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
KDIR?=/home/guanlei/fl2440/kernel/linux-3.0
obj-m:=myds18b20.o
default:
$(MAKE) -C $(KDIR) M=`pwd` modules
make clean
clean:
rm -f *.ko.* *.o *mod.c *.order *.symvers
相应的简单的测试程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <termios.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
main()
{
int fd;
unsigned char buf[2];
unsigned short temp=0;
double result=0;
int flag=0;
if ((fd=open("/dev/ds18b20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
{
printf("Open Device DS18B20 failed.\r\n");
exit(1);
}
else
{
printf("Open Device DS18B20 successed.\r\n");
while(1)
{
read(fd, buf, sizeof(buf));
printf("read data is 0x%02X-0x%02X\n",buf[1],buf[0]);
temp=((unsigned short)buf[1])<<8;
temp|=(unsigned short)buf[0];
// printf("no error here\n");
result=0.0625*((double)temp);
printf("temperature is %4f \r\n", result);
sleep(2);
}
close(fd);
}
}