ds18b20驱动及应用程序
------------------------------------------------------------------------------------------------------------------------------
交叉编译器:arm-linux-gcc-4.5.4
Linux内核版本:Linux-3.0
主机操作系统:Centos 6.5
开发板:FL2440
温度传感器:ds18b20
------------------------------------------------------------------------------------------------------------------------------
之前看过led的,platform_led的,platform_button的。当时以为看懂了,可是真的拿到一个模块要去写他的驱动的时候发现有些无从下手。于是借鉴了朋友的一篇混杂设备驱动,半抄半写的写出来了一个miscdevice类型的驱动。之后又在miscdevice与led的基础上写出来了cdev类型的驱动。并附上一个小小的测试程序。
一、miscdevice驱动
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/configfs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <plat/regs-timer.h>
#include <mach/regs-gpio.h>
#include <mach/map.h>
#include <mach/gpio-nrs.h>
#include <mach/regs-irq.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <mach/regs-clock.h>
#include <asm/irq.h>
#include <linux/types.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/atomic.h>
#include <asm/unistd.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h> /*********************************************************************************
* Copyright: (C) 2016 2013dianxin_3
* All rights reserved.
*
* Filename: ds18b20.c
* Description: This file
*
* Version: 1.0.0(08/07/2016)
* Author: xiaohexiansheng <1392195453@qq.com>
* ChangeLog: 1, Release initial version on "08/07/2016 02:21:17 PM"
*
********************************************************************************/
#define DRV_AUTHOR "xiaohexiansheng <wcchz@hotmail.com>"
#define DRV_DESC "s3c2440 ds18b20 driver"
#define DEVICE_NAME "ds18b20" #define LOW 0
#define HIGH 1
typedef unsigned char BYTE; static BYTE data[]; BYTE ds18b20_reset(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT); //配置GP0输出模式
s3c2410_gpio_setpin(S3C2410_GPG(), LOW); //向ds18b20发送一个下降沿,并保持480us
udelay();
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH); //向ds18b20发送一个上升沿,此时可释放ds18b20总线
udelay(); //以上动作是给ds18b20一个复位脉冲,通过配置GPIO引脚为输入模式可检测ds18b20是否复位成功
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_INPUT);
//若总线在释放后为高电平,则复位失败
if(s3c2410_gpio_getpin(S3C2410_GPG()))
{
printk("ds18b20 reset failed.\r\n");
return ;
}
udelay();
return ;
} BYTE ds18b20_read_byte(void)
{
BYTE i = ;
BYTE byte = ;
// 读“1”时隙:
// 若总线状态保持在低电平状态1微秒到15微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“1”信号
// 理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
// 读“0”时隙:
// 若总线状态保持在低电平状态15微秒到30微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“0”信号
// 理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
for(i = ; i < ; i++)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
udelay();
byte >>= ;
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_INPUT);
// 若总线在我们设它为低电平之后若1微秒之内变为高
// 则认为从DS18B20处收到一个“1”信号
// 因此把byte的D7为置“1”
if(s3c2410_gpio_getpin(S3C2410_GPG()))
byte |= 0x80;
udelay();
}
return byte;
} BYTE ds18b20_write_byte(BYTE byte)
{
BYTE i;
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT); // 配置GPG0为输出模式
// 写“1”时隙:
// 保持总线在低电平1微秒到15微秒之间
// 然后再保持总线在高电平15微秒到60微秒之间
// 理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
// 写“0”时隙:
// 保持总线在低电平15微秒到60微秒之间
// 然后再保持总线在高电平1微秒到15微秒之间
// 理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
for(i = ; i < ; i++)
{
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
udelay();
if(byte & HIGH)
{
// 若byte变量的D0位是1,则需向总线上写“1”
// 根据写“1”时隙规则,电平在此处翻转为高
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
}
else
{
// 若byte变量的D0位是0,则需向总线上写“0”
// 根据写“0”时隙规则,电平在保持为低
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
}
// 电平状态保持60微秒
udelay(); s3c2410_gpio_setpin(S3C2410_GPG(), HIGH); //释放总线
udelay();
byte >>= ;
}
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH); //释放总线
} void ds18b20_proc(void) //读取温度
{
while(ds18b20_reset()); //循环判断DS18B20直到复位,延时120ms;
udelay();
ds18b20_write_byte(0xcc); //写入CCH命令,跳过读序列号过程;
ds18b20_write_byte(0x44); //写入44H命令,开始温度转换,延时5 ms;
udelay(); while(ds18b20_reset()); //循环判断DS18B20直到复位,延时200 ms;
udelay();
ds18b20_write_byte(0xcc); //写入CCH命令,跳过读序列号过程;
ds18b20_write_byte(0xbe); //写入BEH命令,读取寄存器; data[] = ds18b20_read_byte(); //读温度整数部分;
data[] = ds18b20_read_byte(); //读温度小数部分
} static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
ds18b20_proc(); buff[] = data[];
buff[] = data[]; return ;
} static struct file_operations s3c2440_ds18b20_fops =
{
.owner = THIS_MODULE,
.read = s3c2440_ds18b20_read,
}; static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &s3c2440_ds18b20_fops,
}; static int __init s3c2440_ds18b20_init(void)
{
int result;
result = misc_register(&misc);
printk(DEVICE_NAME "initialized.\n"); while(ds18b20_reset());
return result;
} static void __exit s3c2440_ds18b20_exit(void)
{
misc_deregister(&misc);
} module_init(s3c2440_ds18b20_init);
module_exit(s3c2440_ds18b20_exit);
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");
二、cdevdevice驱动
#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> /*********************************************************************************
* Copyright: (C) 2016 2013dianxin_3
* All rights reserved.
*
* Filename: ds18b20.c
* Description: This file
*
* Version: 1.0.0(08/08/2016)
* Author: xiaohexiansheng <1392195453@qq.com>
* ChangeLog: 1, Release initial version on "08/08/2016 03:44:48 PM"
*
********************************************************************************/
#define DRV_AUTHOR "xiaohexiansheng <1392195453@qq.com>"
#define DRV_DESC "S3C2440 ds18b20 driver" #define DEV_NAME "ds18b20"
#define DISABLE 0
#define DRV_MAJOR_VER 1
#define DRV_MINOR_VER 0
#define DRV_REVER_VER 0 #define LOW 0
#define HIGH 1 #ifndef DEV_MAJOR
#define DEV_MAJOR 0
#endif int dev_major = DEV_MAJOR;
int dev_minor = ;
int debug = DISABLE; static struct cdev *ds18b20_cdev; typedef unsigned char BYTE;
static BYTE data[]; BYTE ds18b20_reset(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
udelay();
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
udelay(); s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_INPUT);
if(s3c2410_gpio_getpin(S3C2410_GPG()))
{
printk("ds18b20 reset failed.\r\n");
return ;
}
udelay();
return ;
} BYTE ds18b20_read_byte(void)
{
BYTE i = ;
BYTE byte = ; for(i = ; i < ; i++)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
udelay();
byte >>= ;
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_INPUT);
if(s3c2410_gpio_getpin(S3C2410_GPG()))
byte |= 0x80;
udelay();
}
return byte;
} BYTE ds18b20_write_byte(BYTE byte)
{
BYTE i;
s3c2410_gpio_cfgpin(S3C2410_GPG(), S3C2410_GPIO_OUTPUT);
for(i = ; i < ; i++)
{
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
udelay();
if(byte & HIGH)
{
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
}
else
{
s3c2410_gpio_setpin(S3C2410_GPG(), LOW);
}
udelay(); s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
udelay();
byte >>= ;
}
s3c2410_gpio_setpin(S3C2410_GPG(), HIGH);
return ;
} void ds18b20_proc(void)
{
while(ds18b20_reset());
udelay();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0x44);
udelay(); while(ds18b20_reset());
udelay();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0xbe); data[] = ds18b20_read_byte();
data[] = ds18b20_read_byte();
} static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
ds18b20_proc(); buff[] = data[];
buff[] = data[]; return ;
} static struct file_operations ds18b20_fops =
{ .owner = THIS_MODULE,
.read = s3c2440_ds18b20_read,
}; static int __init s3c_ds18b20_init(void)
{
int result;
dev_t devno; if( != ds18b20_reset())
{
printk(KERN_ERR "s3c2440 ds18b20 hardware initialize failure.\n");
return -ENODEV;
} if( != dev_major)
{
devno = MKDEV(dev_major, );
result = register_chrdev_region(devno, , DEV_NAME);
}
else
{
result = alloc_chrdev_region(&devno, dev_minor, , DEV_NAME);
dev_major = MAJOR(devno);
} if(result < )
{
printk(KERN_ERR "s3c %s driver cannot use major %d.\n", DEV_NAME, dev_major);
return -ENODEV;
}
printk(KERN_DEBUG "s3c %s driver use major %d.\n", DEV_NAME, dev_major); if(NULL == (ds18b20_cdev = cdev_alloc()))
{
printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.\n", DEV_NAME, result);
unregister_chrdev_region(devno, );
return -ENOMEM;
} ds18b20_cdev -> owner = THIS_MODULE;
cdev_init(ds18b20_cdev, &ds18b20_fops); result = cdev_add(ds18b20_cdev, devno, );
if( != result)
{
printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.\n", DEV_NAME, result);
goto ERROR;
} printk(KERN_ERR "s3c %s driver[major=%d] Version %d.%d.%d installed successfully.\n",DEV_NAME, dev_major, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
return ; ERROR:
printk(KERN_ERR "s3c %s driver installed failure./", DEV_NAME);
cdev_del(ds18b20_cdev);
unregister_chrdev_region(devno, );
return result;
} static void __exit s3c_ds18b20_exit(void)
{
dev_t devno = MKDEV(dev_major, dev_minor); cdev_del(ds18b20_cdev);
unregister_chrdev_region(devno, ); printk(KERN_ERR "s3c %s driver version %d.%d.%d removed!\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
return;
} module_init(s3c_ds18b20_init);
module_exit(s3c_ds18b20_exit); module_param(debug, int, S_IRUGO);
module_param(dev_major, int ,S_IRUGO); MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");
注:cdev的驱动需要手动创建设备节点,而misc不需要
三、测试程序
/*********************************************************************************
* Copyright: (C) 2016 2013dianxin_3
* All rights reserved.
*
* Filename: dsapp.c
* Description: This file
*
* Version: 1.0.0(08/08/2016)
* Author: xiaohexiansheng <1392195453@qq.com>
* ChangeLog: 1, Release initial version on "08/08/2016 10:19:25 AM"
*
********************************************************************************/
#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> /********************************************************************************
* Description:
* Input Args:
* Output Args:
* Return Value:
********************************************************************************/
int main (int argc, char **argv)
{
int fd;
double result = ;
unsigned char buff[];
unsigned short temp = ;
int flag = ; if ((fd=open("/dev/ds18b20",O_RDWR | O_NDELAY | O_NOCTTY)) < )
{
perror("open device ds18b20 failed.\r\n");
exit();
}
while()
{
printf("open device ds18b20 success.\r\n");
read(fd, buff, sizeof(buff));
temp=((unsigned short)buff[])<<;
temp|=(unsigned short)buff[];
result=0.0625*((double)temp);
printf("temperature is %4f \r\n", result);
sleep();
}
close(fd); return ;
} /* ----- End of main() ----- */
ds18b20驱动及应用程序的更多相关文章
- openwrt驱动与应用程序的联系
应用程序与驱动之间需要进行命令的传递,因而它们之间需要共同定义一套双方都可以识别的数据结构,实际使用时它们include的是名字和内容相同但位置不同的头文件. 比如spi_gpio_ad7193.h这 ...
- linux 设备驱动与应用程序异步通知
一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...
- i2c之at24c08驱动及应用程序
1-->修改板级文件arch/arm/mach-s3c2440/mach-mini2440.c 步骤: ->添加引用 #include <linux/i2c.h> ->添 ...
- 用Setup系列函数完成驱动卸载安装[驱动安装卸载程序]
// InstallWDFDriver.cpp : Defines the entry point for the console application. // #include "std ...
- Linux驱动之触摸屏程序编写
本篇博客分以下几部分讲解 1.介绍电阻式触摸屏的原理 2.介绍触摸屏驱动的框架(输入子系统) 3.介绍程序用到的结构体 4.介绍程序用到的函数 5.编写程序 6.测试程序 1.介绍电阻式触摸屏的原理 ...
- 从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序
笔者学习嵌入式Linux也有一段时间了,很奇怪的是很多书讲驱动编程方面的知识,也有很多书将ARM9方面的知识,但是从以前51形式的(对寄存器直接操作,初始化芯片的功能模块)编程方法,和思维模式,变换为 ...
- Linux设备驱动Hello World程序介绍
自古以来,学习一门新编程语言的第一步就是写一个打印“hello world”的程序(可以看<hello world 集中营>这个帖子供罗列了300个“hello world”程序例子)在本 ...
- Linux嵌入式学习-ds18b20驱动
ds18b20的时序图如下: 复位时序: 读写时序: 以下是程序代码: #include <linux/module.h> #include <linux/init.h> #i ...
- STM32液晶显示HT1621驱动原理及程序代码
1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机 ...
随机推荐
- JAVAEE——宜立方商城13:Mycat数据库分片、主从复制、读写分离、100%Linux中成功安装Mysql的方法
1 海量数据的存储问题 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候NoSQL ...
- Java集合&Spring源码浅读
记录自己现在知道的,以后了解了更多的话,再继续补上来 Java集合类 Collection 接口 说明:是List,set 的父类.定义了集合初始模样.集合只存储对象. Jdk8文档,内部方法定义有: ...
- 系统的Drawable(二)-Selector
系统的Drawable(二)-Selector Selector漫谈 Selector是定义 StateListDrawable 的标签,该Drawable代表着一个Drawable的集合,每一个Dr ...
- android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...
- XXX on tree
%了发树上莫队 nlognsqrt(n) // luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; in ...
- 【网站管理5】_讲解网站后台SEO优化和如何修改关键字以及关键词布局
讲解网站后台SEO优化和如何修改关键字以及关键词布局 制作:赖忠标 QQ:392277956 1.打开后台点击左侧边上的栏目,点击最后的系统-系统基本参数-站点设置 如下图 2.上图所改处 ...
- Supported Values for @SuppressWarnings(转)
Update July 2011: This list has been reviewed and made current with the most recent Eclipse 3.7 rele ...
- 使用 Spring 2.5 注释驱动的 IoC 功能(转)
基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换 ...
- 酷播迷你flv,mp4网页视频播放器(CuPlayerMini)V2.2版[经典黑]演示实例
酷播迷你flv,mp4网页视频播放器(CuPlayerMini)V2.2版[经典黑]演示实例 http://www.cuplayer.com/cu/FreeDown/
- Revit MEP API连接器类别
连接器的类别,风管不仅有两端,可能在曲线上也有. ; ; ; ; Connector conn = csi.Current ; ...