------------------------------------------------------------------------------------------------------------------------------

交叉编译器: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驱动及应用程序的更多相关文章

  1. openwrt驱动与应用程序的联系

    应用程序与驱动之间需要进行命令的传递,因而它们之间需要共同定义一套双方都可以识别的数据结构,实际使用时它们include的是名字和内容相同但位置不同的头文件. 比如spi_gpio_ad7193.h这 ...

  2. linux 设备驱动与应用程序异步通知

    一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...

  3. i2c之at24c08驱动及应用程序

    1-->修改板级文件arch/arm/mach-s3c2440/mach-mini2440.c 步骤: ->添加引用 #include <linux/i2c.h> ->添 ...

  4. 用Setup系列函数完成驱动卸载安装[驱动安装卸载程序]

    // InstallWDFDriver.cpp : Defines the entry point for the console application. // #include "std ...

  5. Linux驱动之触摸屏程序编写

    本篇博客分以下几部分讲解 1.介绍电阻式触摸屏的原理 2.介绍触摸屏驱动的框架(输入子系统) 3.介绍程序用到的结构体 4.介绍程序用到的函数 5.编写程序 6.测试程序 1.介绍电阻式触摸屏的原理 ...

  6. 从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序

    笔者学习嵌入式Linux也有一段时间了,很奇怪的是很多书讲驱动编程方面的知识,也有很多书将ARM9方面的知识,但是从以前51形式的(对寄存器直接操作,初始化芯片的功能模块)编程方法,和思维模式,变换为 ...

  7. Linux设备驱动Hello World程序介绍

    自古以来,学习一门新编程语言的第一步就是写一个打印“hello world”的程序(可以看<hello world 集中营>这个帖子供罗列了300个“hello world”程序例子)在本 ...

  8. Linux嵌入式学习-ds18b20驱动

    ds18b20的时序图如下: 复位时序: 读写时序: 以下是程序代码: #include <linux/module.h> #include <linux/init.h> #i ...

  9. STM32液晶显示HT1621驱动原理及程序代码

    1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机 ...

随机推荐

  1. JAVAEE——宜立方商城13:Mycat数据库分片、主从复制、读写分离、100%Linux中成功安装Mysql的方法

    1 海量数据的存储问题 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候NoSQL ...

  2. Java集合&Spring源码浅读

    记录自己现在知道的,以后了解了更多的话,再继续补上来 Java集合类 Collection 接口 说明:是List,set 的父类.定义了集合初始模样.集合只存储对象. Jdk8文档,内部方法定义有: ...

  3. 系统的Drawable(二)-Selector

    系统的Drawable(二)-Selector Selector漫谈 Selector是定义 StateListDrawable 的标签,该Drawable代表着一个Drawable的集合,每一个Dr ...

  4. 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 进程间 通讯 ...

  5. XXX on tree

    %了发树上莫队 nlognsqrt(n) // luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; in ...

  6. 【网站管理5】_讲解网站后台SEO优化和如何修改关键字以及关键词布局

    讲解网站后台SEO优化和如何修改关键字以及关键词布局 制作:赖忠标   QQ:392277956 1.打开后台点击左侧边上的栏目,点击最后的系统-系统基本参数-站点设置     如下图 2.上图所改处 ...

  7. Supported Values for @SuppressWarnings(转)

    Update July 2011: This list has been reviewed and made current with the most recent Eclipse 3.7 rele ...

  8. 使用 Spring 2.5 注释驱动的 IoC 功能(转)

    基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean.装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换 ...

  9. 酷播迷你flv,mp4网页视频播放器(CuPlayerMini)V2.2版[经典黑]演示实例

    酷播迷你flv,mp4网页视频播放器(CuPlayerMini)V2.2版[经典黑]演示实例 http://www.cuplayer.com/cu/FreeDown/

  10. Revit MEP API连接器类别

    连接器的类别,风管不仅有两端,可能在曲线上也有. ;         ;         ;         ;             Connector conn = csi.Current ; ...