- //要注意一点,在裸机状态下可以使用data = data * 6.25来对温度值进行放大100倍,但是在内核中不能使用,但可以使用data = data * 625 / 100;
- //网上查了一下好像是内核不支持浮点.不知道是不是这回事,但是我不使用浮点驱动加载就没问题,使用后不能加载了.
- /****************************************************************************************************************
- * 文件名称 : DS18B20_drive.c
- * 简介 : OK6410 DS18B20驱动
- * 作者 : 异灵元(cp1300@139.com)
- * 创建时间 : 2012/09/18 20:37
- * 修改时间 : 2012/09/18
- * 说明 : OK6410 开发板(S3C6410)DS18B20(GPIO)驱动
- ****************************************************************************************************************/
- //系统头文件
- #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 <linux/delay.h>
- #include <linux/io.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 DS18B20_ERROR 0xf000 //初始化失败
- //系统US延时定义
- #define Delay_US(x) udelay(x)
- //设置DS18B20 IO为推挽输出模式
- void Set18b20IOout(void)
- {
- unsigned int reg;
- reg = readl(S3C64XX_GPECON);
- reg |= 1;
- writel(reg,S3C64XX_GPECON);
- }
- //读IO
- unsigned char Read18b20IO(void)
- {
- unsigned int reg;
- reg = readl(S3C64XX_GPEDAT);
- if(reg & 1)
- return 1;
- else
- return 0;
- }
- //写IO
- void Write18b20IO(unsigned char data)
- {
- unsigned int reg;
- reg = readl(S3C64XX_GPEDAT);
- if(data)
- reg |= 1;
- else
- reg &= ~1;
- writel(reg,S3C64XX_GPEDAT);
- }
- //设在DS18B20 IO输入模式
- void Set18b20IOin(void)
- {
- unsigned int reg;
- reg = readl(S3C64XX_GPECON);
- reg &= (~0xf);
- writel(reg,S3C64XX_GPECON);
- }
- //复位DS18B20
- u8 DS18B20_Reset(void)
- {
- u8 i = 0;
- Set18b20IOout();
- Write18b20IO(1);
- Delay_US(1);
- Write18b20IO(0);
- Delay_US(500);
- Write18b20IO(1);
- Delay_US(2);
- Set18b20IOin();
- while(Read18b20IO())
- {
- i ++;
- Delay_US(1);
- if(i > 100)
- return 1;
- }
- Delay_US(250);
- return 0x00;
- }
- //读DS18B20数据
- u8 DS18B20_ReadData(void)
- {
- u8 i,data = 0;
- for(i = 0;i < 8;i ++)
- {
- Set18b20IOout();
- Write18b20IO(0);
- data >>= 1;
- Delay_US(12);
- Write18b20IO(1);
- Set18b20IOin();
- Delay_US(1);
- if(Read18b20IO())
- data |= 0x80;
- Delay_US(42);
- }
- return data;
- }
- //写DS18B20数据
- void DS18B20_WriteData(u8 data)
- {
- u8 i;
- Set18b20IOout();
- for(i = 0;i < 8;i ++)
- {
- Write18b20IO(0);
- Delay_US(12);
- Write18b20IO(data & 0x01);
- Delay_US(30);
- Write18b20IO(1);
- data >>= 1;
- Delay_US(2);
- }
- }
- //读取温度
- int DS18B20_ReadTemper(void)
- {
- u8 th, tl;
- int data;
- if(DS18B20_Reset())
- {
- return DS18B20_ERROR;
- }
- DS18B20_WriteData(0xcc);
- DS18B20_WriteData(0x44);
- DS18B20_Reset();
- DS18B20_WriteData(0xcc);
- DS18B20_WriteData(0xbe);
- tl = DS18B20_ReadData();
- th = DS18B20_ReadData();
- data = th;
- data <<= 8;
- data |= tl;
- data = data * 625 / 100;
- return data;
- }
- ///
- //驱动模块名称
- #define DEVICE_NAME "OK6410_DS18B20"
- //函数声明
- ///
- static long OK6410_DS18B20_ioctl(
- struct file *file,
- unsigned int cmd,
- unsigned long arg);
- static ssize_t OK6410_DS18B20_write(
- struct file *file,
- const char __user *buff,
- size_t size,
- loff_t *loff);
- static ssize_t OK6410_DS18B20_read(
- struct file *file,
- char __user *buff,
- size_t size,
- loff_t *loff);
- ///
- /* 这个结构是字符设备驱动的核心
- * 当应用程序操作设备文件所提供的open,read,write等函数,
- * 最终会调用到这个结构中的对应函数
- */
- static struct file_operations dev_fops = {
- .owner = THIS_MODULE, //这是一个宏,指向编译模块时自动创建的__this_module变量
- .unlocked_ioctl = OK6410_DS18B20_ioctl,
- .read = OK6410_DS18B20_read,
- .write = OK6410_DS18B20_write
- };
- //注册驱动所使用的相关信息
- static struct miscdevice misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME, //驱动模块名称
- .fops = &dev_fops,
- };
- //DS18B20设备访问信号量
- struct semaphore DS18B20_sem;
- /****************************************************************************************************************
- *函数名 : static int __init OK6410_DS18B20_init(void)
- *功能 : DS18B20模块初始化函数
- *参数 : 无
- *返回 : 0:成功;<0:失败
- *依赖 : linux底层宏定义
- *作者 : 异灵元(cp1300@139.com)
- *创建时间 : 2012/09/18 20:38
- *最后修改时间: 2012/09/18 20:38
- *说明 : 初始化DS18B20硬件,注册DS18B20驱动
- ****************************************************************************************************************/
- static int __init OK6410_DS18B20_init(void)
- {
- int ret;
- ret = misc_register(&misc); //注册驱动
- if(ret < 0)
- {
- printk(DEVICE_NAME " can't initialized DS18B20!\n");
- return ret;
- }
- init_MUTEX(&DS18B20_sem); //注册信号量
- printk(DEVICE_NAME " initialized\n");
- return 0; //返回成功
- }
- /****************************************************************************************************************
- *函数名 : static long OK6410_DS18B20_ioctl(
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- *功能 : 发送命令给DS18B20驱动模块,无实际作用,直接返回0
- *参数 : 无作用
- *返回 : 0
- *依赖 : 无
- *作者 : 异灵元(cp1300@139.com)
- *创建时间 : 2012/09/18 20:38
- *最后修改时间: 2012/09/18 20:38
- *说明 : 无
- ****************************************************************************************************************/
- static long OK6410_DS18B20_ioctl(
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- {
- return 0;
- }
- /****************************************************************************************************************
- *函数名 : static ssize_t OK6410_DS18B20_write(
- struct file *file,
- const char __user *buff,
- size_t size,
- loff_t *loff)
- *功能 : 写数据到DS18B20驱动模块,无效函数,返回0
- *参数 : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用
- *返回 : 0:成功;<0:失败
- *依赖 : linux底层宏
- *作者 : 异灵元(cp1300@139.com)
- *创建时间 : 2012/09/18 20:38
- *最后修改时间: 2012/09/18 20:38
- *说明 : 写无效
- ****************************************************************************************************************/
- static ssize_t OK6410_DS18B20_write(
- struct file *file,
- const char __user *buff,
- size_t size,
- loff_t *loff)
- {
- return 0;
- }
- /****************************************************************************************************************
- *函数名 : static ssize_t OK6410_DS18B20_read(
- struct file *file,
- char __user *buff,
- size_t size,
- loff_t *loff)
- *功能 : 读DS18B20状态,低电平灯亮
- *参数 : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用
- *返回 : 0:成功;<0:失败
- *依赖 : linux底层宏
- *作者 : 异灵元(cp1300@139.com)
- *创建时间 : 2012/09/18 20:38
- *最后修改时间: 2012/09/18 20:38
- *说明 : 读取到的是一个16位有符号的温度
- ****************************************************************************************************************/
- static ssize_t OK6410_DS18B20_read(
- struct file *file,
- char __user *buff,
- size_t size,
- loff_t *loff)
- {
- int temp;
- int *p;
- if(down_interruptible(&DS18B20_sem)) //获取信号量
- return -ERESTARTSYS;
- temp = DS18B20_ReadTemper(); //读取温度
- if(temp == DS18B20_ERROR) //DS18B20初始化失败
- return -1; //DS18B20读取失败,返回错误
- p = (int *)buff;
- *p = temp; //将温度写入到缓冲区
- up(&DS18B20_sem); //释放信号量
- return 0;
- }
- /****************************************************************************************************************
- *函数名 : static void __exit OK6410_DS18B20_exit(void)
- *功能 : 卸载DS18B20驱动
- *参数 : 无
- *返回 : 无
- *依赖 : linux底层宏
- *作者 : 异灵元(cp1300@139.com)
- *创建时间 : 2012/09/18 20:38
- *最后修改时间: 2012/09/18 20:38
- *说明 : 卸载驱动
- ****************************************************************************************************************/
- static void __exit OK6410_DS18B20_exit(void)
- {
- misc_deregister(&misc); //卸载驱动
- }
- //动态加载驱动接口(必须)
- module_init(OK6410_DS18B20_init);
- module_exit(OK6410_DS18B20_exit);
- //其它信息(非必需)
- MODULE_AUTHOR("cp1300@139.com"); //驱动程序作者
- MODULE_DESCRIPTION("OK6410(S3C6410) DS18B20 Driver"); //一些描述信息
- MODULE_LICENSE("GPL"); //遵循的协议
makefile
- ARCH=arm
- CROSS_COMPILE=arm-linux-
- obj-m := ds18b20_drive.o
- #ds18b20_drive-objs := ds18b20_drive.o
- KDIR :=/home/cfan/linux/linux-3.0.1
- PWD :=$(shell pwd)
- all:
- $(MAKE) -C $(KDIR) M=$(PWD) modules
- clean:
- $(MAKE) -C $(KDIR) M=$(PWD) clean
测试
- /****************************************************************************************************************
- * 文件名称 : ds18b20_teset.c
- * 简介 : OK6410 DS18B20驱动测试程序
- * 作者 : 异灵元(cp1300@139.com)
- * 创建时间 : 2012/09/19 22:10
- * 修改时间 : 2012/09/19
- * 说明 : OK6410 开发板(S3C6410)DS18B20(GPIO)驱动测试程序
- ****************************************************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- int main(void)
- {
- int fd;
- int data;
- //DS18B20测试
- printf("DS18B20 test...\n");
- fd = open("/dev/OK6410_DS18B20",O_RDONLY); //open DS18B20
- if(fd == -1)
- {
- printf("open DS18B20 error!\n");
- exit(-1);
- }
- else
- {
- printf("open DS18B20 ok!\n");
- }
- while(1)
- {
- if(read(fd,&data,(size_t)2))
- printf("read error!\n");
- printf("ds18b20 = %d\n",data);
- usleep(1000 * 1000); //1000MS
- }
- }