从网站上下载了lixin的mini2410的ds18b20代码,并做了修改,成功实现了Tiny6410的ds18b20驱动。感谢署名为lixin的网友!
【程序清单】
ds18b20.c
/******************************************Copyright(c)************************************************
** 文件名称: ds18b20_drv.c
** 作 者: lixin
** 版 本: v1.0
** 说 明: ds18b20驱动程序.工作过程及时序见ds18b20 datasheet
** 修改记录: 2009-8-27创建
** 最后修改时间: 2009-09-01
******************************************************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <mach/regs-gpio.h>
#include <linux/device.h>
#include <mach/hardware.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include "s3c6410_gpio.h"
//#define DEBUG
/* 相关引脚定义,方便以后移植 */
#define DEVICE_NAME "ds18b20"
#define DQ 8
#define CFG_IN 0
#define CFG_OUT 1
// ds18b20主次设备号(动态分配)
int ds18b20_major = 0;
int ds18b20_minor = 0;
int ds18b20_nr_devs = 1;
// 定义设备类型
static struct ds18b20_device {
struct cdev cdev;
};
struct ds18b20_device ds18b20_dev;
static struct class *ds18b20_class;
/* 函数声明 */
static int ds18b20_open(struct inode *inode, struct file *filp);
static int ds18b20_init(void);
static void write_byte(unsigned char data);
static unsigned char read_byte(void);
static ssize_t ds18b20_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos);
void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);
/******************************************************************************************************
** 函数名称: ds18b20_open()
** 函数功能: 打开设备,初始化ds18b20
** 入口参数: inode:设备文件信息; filp: 被打开的文件的信息
** 出口参数: 成功时返回0,失败返回-1
** 备 注:
******************************************************************************************************/
static int ds18b20_open(struct inode *inode, struct file *filp)
{
int flag = 0;
/*struct ds18b20_device *dev;
dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);
filp->private_data = dev;*/
flag = ds18b20_init();
if(flag & 0x01)
{
#ifdef DEBUG
printk(KERN_WARNING "open ds18b20 failed\n");
#endif
return -1;
}
#ifdef DEBUG
printk(KERN_NOTICE "open ds18b20 successful\n");
#endif
return 0;
}
/******************************************************************************************************
** 函数名称: ds18b20_init()
** 函数功能: 复位ds18b20
** 入口参数: 无
** 出口参数: retval:成功返回0,失败返回1
** 备 注: 操作时序见ds18b20 datasheet
******************************************************************************************************/
static int ds18b20_init(void)
{
int retval = 0;
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1);
udelay(2);
s3c6410_gpio_setpin(DQ, 0); // 拉低ds18b20总线,复位ds18b20
udelay(500); // 保持复位电平500us
s3c6410_gpio_setpin(DQ, 1); // 释放ds18b20总线
udelay(60);
// 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)
s3c6410_gpio_cfgpin(DQ, CFG_IN);
retval = s3c6410_gpio_getpin(DQ);
udelay(500);
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1); // 释放总线
return retval;
}
/******************************************************************************************************
** 函数名称: write_byte()
** 函数功能: 向18b20写入一个字节数据
** 入口参数: data
** 出口参数: 无
** 备 注:
******************************************************************************************************/
static void write_byte(unsigned char data)
{
int i = 0;
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 1);
for (i = 0; i < 8; i ++)
{
// 总线从高拉至低电平时,就产生写时隙
s3c6410_gpio_setpin(DQ, 1);
udelay(2);
s3c6410_gpio_setpin(DQ, 0);
s3c6410_gpio_setpin(DQ, data & 0x01);
udelay(60);
data >>= 1;
}
s3c6410_gpio_setpin(DQ, 1); // 重新释放ds18b20总线
}
/******************************************************************************************************
** 函数名称: read_byte()
** 函数功能: 从ds18b20读出一个字节数据
** 入口参数: 无
** 出口参数: 读出的数据
** 备 注:
******************************************************************************************************/
static unsigned char read_byte(void)
{
int i;
unsigned char data = 0;
for (i = 0; i < 8; i++)
{
// 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1);
udelay(2);
s3c6410_gpio_setpin(DQ, 0);
udelay(2);
s3c6410_gpio_setpin(DQ, 1);
udelay(8);
data >>= 1;
s3c6410_gpio_cfgpin(DQ, CFG_IN);
if (s3c6410_gpio_getpin(DQ))
data |= 0x80;
udelay(50);
}
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1); // 释放ds18b20总线
return data;
}
/******************************************************************************************************
** 函数名称: ds18b20_read()
** 函数功能: 读出18b20的温度
** 入口参数:
** 出口参数:
** 备 注:
******************************************************************************************************/
static ssize_t ds18b20_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
int flag;
unsigned long err;
unsigned char result[2] = {0x00, 0x00};
//struct ds18b20_device *dev = filp->private_data;
flag = ds18b20_init();
if (flag)
{
#ifdef DEBUG
printk(KERN_WARNING "ds18b20 init failed\n");
#endif
return -1;
}
write_byte(0xcc);
write_byte(0x44);
flag = ds18b20_init();
if (flag)
return -1;
write_byte(0xcc);
write_byte(0xbe);
result[0] = read_byte(); // 温度低八位
result[1] = read_byte(); // 温度高八位
err = copy_to_user(buf, &result, sizeof(result));
return err ? -EFAULT : min(sizeof(result),count);
}
/**************************************************************
* 字符驱动程序的核心,应用程序所调用的open,read等函数最终会
* 调用这个结构中的对应函数
*************************************************************/
static struct file_operations ds18b20_dev_fops = {
.owner = THIS_MODULE,
.open = ds18b20_open,
.read = ds18b20_read,
};
/******************************************************************************************************
** 函数名称: ds18b20_setup_cdev()
** 函数功能: 初始化cdev
** 入口参数: dev:设备结构体; index:
** 出口参数: 无
** 备 注:
******************************************************************************************************/
void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)
{
int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);
cdev_init(&dev->cdev, &ds18b20_dev_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&(dev->cdev), devno, 1);
if (err)
{
#ifdef DEBUG
printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);
#endif
}
}
/******************************************************************************************************
** 函数名称: ds18b20_dev_init()
** 函数功能: 为温度传感器分配注册设备号,初始化cdev
** 入口参数: 无
** 出口参数: 若成功执行,返回0
** 备 注:
******************************************************************************************************/
static int __init ds18b20_dev_init(void)
{
ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);
if (ds18b20_major<0)
{
printk(DEVICE_NAME " Can't register major number!\n");
return -EIO;
}
ds18b20_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEVICE_NAME);
#ifdef DEBUG
printk(KERN_WARNING "register ds18b20 driver successful!\n");
#endif
return 0;
}
/******************************************************************************************************
** 函数名称: ds18b20_dev_exit()
** 函数功能: 注销设备
** 入口参数: 无
** 出口参数: 无
** 备 注:
******************************************************************************************************/
static void __exit ds18b20_dev_exit(void)
{
device_destroy(ds18b20_class, MKDEV(ds18b20_major,ds18b20_minor));
class_unregister(ds18b20_class);
class_destroy(ds18b20_class);
unregister_chrdev(ds18b20_major, DEVICE_NAME);
#ifdef DEBUG
printk(KERN_WARNING "Exit ds18b20 driver!\n");
#endif
}
module_init(ds18b20_dev_init);
module_exit(ds18b20_dev_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("xinli_whut@163.com");
/******************************************************************************************************
** 文件到此结束
******************************************************************************************************/
s3c6410_gpio.h
/******************************************Copyright(c)************************************************
** 文件名称: s3c6410_gpio.h
** 作 者: tandesir
** 版 本: v1.0
** 说 明: s3c6410 gpio操作
** 修改记录: 2011-9-27创建
** 最后修改时间: 2011-10-5
******************************************************************************************************/
#ifndef __S3C6410_GPIO_H__
#define __S3C6410_GPIO_H__
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <mach/regs-clock.h>
#include <asm/irq.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
//s3c_gpio_cfgpin(pin,function);
unsigned int tmp;
tmp = readl(S3C64XX_GPNCON);
tmp = (tmp & ~(3<<pin*2))|(function<<pin*2);
writel(tmp, S3C64XX_GPNCON);
}
void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)
{
//s3c_gpio_setpull(pin,to);
unsigned int tmp;
tmp = readl(S3C64XX_GPNPUD);
tmp = (tmp & ~(3<<pin*2))|(to<<pin*2);
writel(tmp, S3C64XX_GPNPUD);
}
unsigned int s3c6410_gpio_getpin(unsigned int pin)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPNDAT);
tmp = tmp & (1 << (pin));
return tmp;
}
void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPNDAT);
tmp &= ~(1 << (pin));
tmp |= ( (dat) << (pin) );
writel(tmp, S3C64XX_GPNDAT); ;
}
#endif
Makefile
# Comment/uncomment the following line to disable/enable debugging
DEBUG = n
# Add your debugging flag (or not) to CFLAGS
# "-O" is needed to expand inlines
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DDEBUG
else
DEBFLAGS = -O2
endif
EXTRA_CFLAGS += $(DEBFLAGS)
#EXTRA_CFLAGS += -I$(LDDINC)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
#scull-objs := main.o pipe.o access.o
obj-m := ds18b20.o
else
KERNELDIR :=/home/tandesir/work/linux-2.6.38
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
endif
【测试程序】
ds18b20_test.c
/******************************************Copyright(c)************************************************
** 文件名称: ds18b20_test.c
** 作 者: lixin
** 版 本: v1.0
** 说 明: ds18b20测试程序,精度:0.25度,如有需要,还可以进一步提高。
** 修改记录: 2009-8-27创建
** 最后修改时间: 2009-09-01
******************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/ioctl.h>
// 函数声明
void ds18b20_delay(int i);
int main()
{
int fd, i;
unsigned char result[2]; // 从ds18b20读出的结果,result[0]存放低八位
unsigned char integer_value = 0;
float temperature, decimal_value; // 温度数值,decimal_value为小数部分的值
fd = open("/dev/ds18b20", 0);
if (fd < 0)
{
perror("open device failed\n");
exit(1);
}
while (1)
{
i++;
read(fd, &result, sizeof(result));
integer_value = ((result[0] & 0xf0) >> 4) | ((result[1] & 0x07) << 4);
// 精确到0.25度
decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);
// decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2)+ 0.125 * ((result[0] & 0x03) >> 1)+ 0.0625 * ((result[0] & 0x01) >>0);
temperature = (float)integer_value + decimal_value;
printf("The temperature is %6.2f\n",temperature);
//printf("The temperature is %6.4f\n",temperature);
if (i % 20 == 0)
printf("\n");
ds18b20_delay(50);
}
}
/******************************************************************************************************
** 函数名称: ds18b20_delay()
** 函数功能: 延时
** 入口参数: i
** 出口参数: 无
** 备 注:
******************************************************************************************************/
void ds18b20_delay(int i)
{
int j, k;
for (j = 0; j < i; j++)
for(k = 0; k < 50000; k++);
}
/******************************************************************************************************
** 文件到此结束
******************************************************************************************************/
【学习参考】
2012-6-9
(编译步骤,这个写得不错,不过里面“巨人”的称谓有点怪,我现在只是一名学生,开博只是为了交流学习,欢迎各位共同研究感兴趣的话题。我的编译步骤后续更新会添加)
原文出书如下:
转载请标明出处,仅供学习交流,勿用于商业目的
Copyright @ http://blog.csdn.net/tandesir