ds18b20温度传感器驱动程序

news2024/11/20 16:36:49

ds18b20驱动程序

有了之前延时的方法,那么实现一个单总线数据传输的传感器驱动程序就非常简单了。下面我们套用杂项驱动框架来编写ds18b20驱动程序。
实现需要明确的是:**ds18b20驱动的本质是通过2440的gpio,通过给定的时序对ds18b20的读写数据访问,最后将数据传回应用程序。**由于我们实验的linux内核是三星公司根据2440公板修改后的内核,所以有关gpio的操作,三星公司提供了几个api函数,从而大幅度降低了程序的编写难度

  1. void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);配置gpio的功能,这里的功能主要就是输出/输入。该函数需要两个参数,第一个参数是需要控制的引脚,系统提供了几个带参宏,例如#define S3C2410_GPF(_nr) 表示GPF组的第_nr引脚。 S3C2410_GPF(1)就表示GPF1引脚。第二个参数表示功能,系统提供了几个不带参宏,如S3C2410_GPIO_OUTPUT表示输出,S3C2410_GPIO_INPUT表示输入;
  2. void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);设置gpio引脚的内部上拉电阻。第一个参数表示要设置的引脚,第二个参数为1时表示使能上拉,0表示禁止上拉。本实验要全程使用内部上拉,因为我们没有外接上拉电阻。
  3. **unsigned int s3c2410_gpio_getpin(unsigned int pin);**读取某引脚的电平,1表示高电平,0表示低电平。
  4. void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);控制某引脚的电平。第一个参数是要控制的引脚,第二个参数为1表示输出高电平,为0表示输出低电平。
    我们将ds18b20的数据引脚接到
    2440的GPF3
    引脚:
    在这里插入图片描述
    先定义几个宏便于之后的操作:

复位函数

在这里插入图片描述
首先编写ds18b20的复位函数
第29行:使能上拉电阻
第33-34行:在释放总线前,要把功能设置为输入并将引脚设置为高
之后和裸机驱动部分裸机类似

向ds18b20写数据函数

在这里插入图片描述
第69行的延时是有必要的,因为引脚从低电平变为高电平需要时间。

读取一个字节的函数

在这里插入图片描述

温度采集函数

在这里插入图片描述
最后就是温度采集了,跟裸机程序一样。需要注意的是这里不能使用浮点运算把温度值算好再传递给应用程序。这是因为内核本身是不支持浮点运算的这个计算的过程应该放在应用程序中

代码

#include <linux/init.h>
#include <linux/module.h>
#include <mach/hardware.h>
#include <mach/gpio-fns.h>
#include <asm/irq.h> 
#include <mach/regs-gpio.h>  
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/timer.h>

#define DQ S3C2410_GPF(3)
#define DQ_OUT S3C2410_GPIO_OUTPUT
#define DQ_IN  S3C2410_GPIO_INPUT

static int ds18b20_reset(void)
{
	int k;
	s3c2410_gpio_pullup(DQ,1);
	s3c2410_gpio_cfgpin(DQ,DQ_OUT);
	s3c2410_gpio_setpin(DQ,0);
	udelay(500);
	s3c2410_gpio_cfgpin(DQ,DQ_IN);
	s3c2410_gpio_setpin(DQ,1);
	k = 0;
	while(k < 30 && s3c2410_gpio_getpin(DQ))
	{
		udelay(10);
		++k;
	}
	if(k >= 30)
	{
		return 0;
	}
	k = 0;
	while(k < 30 && !s3c2410_gpio_getpin(DQ))
	{
		udelay(10);
		++k;
	}
	if(k >= 30)
	{
		return 0;
	}
	return 1;
}

static void ds18b20_write(unsigned char dat)
{
	int i;
	s3c2410_gpio_cfgpin(DQ,DQ_OUT);

	for(i = 0;i < 8;++i)
	{
		s3c2410_gpio_setpin(DQ,0);
		udelay(10);
		if(dat & 0x01)
		{
			s3c2410_gpio_setpin(DQ,1);
		}
		else
		{
			s3c2410_gpio_setpin(DQ,0);
		}
		udelay(40);
		s3c2410_gpio_setpin(DQ,1);
		udelay(3);
		dat >>= 1;
	}
}

static unsigned char ds18b20_read(void)
{
	unsigned char ret = 0;
	int i;

	for(i = 0;i < 8;++i)
	{
		s3c2410_gpio_cfgpin(DQ,DQ_OUT);
		s3c2410_gpio_setpin(DQ,0);
		udelay(3);
		s3c2410_gpio_setpin(DQ,1);
		s3c2410_gpio_cfgpin(DQ,DQ_IN);
		udelay(1);
		if(s3c2410_gpio_getpin(DQ))
		{
			ret |= 0x01 << i;
		}
		udelay(45);
	}
	return ret;
}

unsigned short getTemperature(void)
{
	unsigned short ret;
	ds18b20_reset();
	ds18b20_write(0xCC);
	ds18b20_write(0x44);
	mdelay(500);
	ds18b20_reset();
	ds18b20_write(0xCC);
	ds18b20_write(0xBE);
	ret = ds18b20_read();
	ret |= ds18b20_read();
	return ret;
}

static int ds18b20_driver_open(struct inode *node, struct file *fp)
{
	return 0;
}

static int ds18b20_driver_close(struct inode *node, struct file *fp)
{
	return 0;
}

static ssize_t ds18b20_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{
	unsigned ret = getTemperature();
	copy_to_user(user_buffer,&ret,4);
	return sizeof(ret);
}

static ssize_t ds18b20_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
	return 0;
}


static struct file_operations fops =
{
	.owner = THIS_MODULE,
	.open = ds18b20_driver_open,
	.read = ds18b20_driver_read,
	.write = ds18b20_driver_write,
	.release = ds18b20_driver_close
};

static struct miscdevice ds18b20_dev =
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "ds18b20",
	.fops = &fops
};


static int __init ds1820_init(void)
{
	int ret;
	ret = misc_register(&ds18b20_dev);
	if(ret < 0)
	{
		printk("misc_register is failed\n");
		return -1;
	}

	return 0;
}

static void __exit ds1820_exit(void)
{
}

module_init(ds1820_init);
module_exit(ds1820_exit);

MODULE_LICENSE("GPL");

应用层代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
    int fd = open("/dev/ds18b20",O_RDWR);
    if(fd < 0)
    {
        printf("file open error\n");
        return 0;
    }

	int i = 0;
	float j = 0;
    while(1)
    {
		sleep(1);
		read(fd,&i,4);
		j = i * 0.0625; 
		printf("%.2f\n",j);
    }

    return 0;
}

结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1624117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在阿里云快速配置自动定时重启ECS云服务器?

背景 无论是电子商务、在线教育、游戏&#xff0c;还是流媒体等业务&#xff0c;服务器的稳定运行都是至关重要的。然而&#xff0c;在实际运行中&#xff0c;我们可能会遇到这样一些场景&#xff1a; 系统更新&#xff1a;一些操作系统或者软件的更新可能需要重启服务器才能…

【课程发布】软考高项目十大管理ITTO宫殿记忆法新版第四版正式发布

软考高项十大管理ITTO宫殿记忆法视频课程&#xff1a; 平台&#xff1a;荔枝微课 连接&#xff1a;十方教育 各位软考高级信息系统项目管理师考生好&#xff0c;新版第四版十大管理ITTO宫殿记忆法视频课程终于发布了&#xff0c;之前苦等的考生终于迎来了救星&#xff0c;再也…

深入理解MySQL中的UPDATE JOIN语句

在MySQL数据库中&#xff0c;UPDATE语句用于修改表中现有的记录。有时&#xff0c;我们需要根据另一个相关联表中的条件来更新表中的数据。这时就需要使用UPDATE JOIN语句。最近我们遇到了这样的需求&#xff1a;我们有一张历史记录表&#xff0c;其中一个字段记录了用,连接的多…

Zephyr学习记录

一、Zephyr是什么&#xff1f; Zephyr 是 Linux 基金会推出的一个适用于物联网的小型可伸缩的实时操作系统&#xff0c;支持多种处理器架构。Zephyr 是安全的、开源的、模块化的以及支持多种连接方式。与华为的liteos很像&#xff0c;也不知道谁抄的谁。 二、官方资料 官方介…

Python+Selenium基于PO模式的Web自动化测试框架

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供…

ElasticSearch:查询操作合集

先看下我的数据&#xff1a; 1、查询所有文档&#xff1a; GET /cartest/_search或者 GET /cartest/_search {"query": {"match_all": {}} }2、匹配查询&#xff1a; match匹配类型查询&#xff0c;会把查询条件进行分词&#xff0c;然后进行查询&…

B02、JVM调优案例

1、调优的基本问题 1.1、为什么要调优&#xff1f; 目的是防止出现OOM&#xff0c;进行JVM规划和预调优&#xff1b;解决程序运行中各种OOM&#xff1b;以及减少Full GC出现的频率&#xff0c;解决运行慢、卡顿问题。 1.2、调优的大方向 合理的编写代码&#xff0c;充分并合理…

easyx 按键信息

前言 看看代码吧 ExMessage msg { 0 }; bool button(int x, int y, int w, int h, const char* text) {//绘制按钮setfillcolor(RGB(230, 231, 232));fillroundrect(x, y, x w, y h, 5, 5);if ((msg.x > x && msg.x<x w && msg.y>y && …

AcWing 1264. 动态求连续区间和 ,详细讲解线段树与树状数组(Python,篇一)

本篇博客主要介绍一下什么是线段树与树状数组&#xff0c;它们的原理与结构是怎样&#xff0c;并通过实际题型来讲解&#xff0c;篇一主要讲解线段树&#xff0c;下一篇博客讲解树状数组。 线段树与树状数组的区别和特点&#xff1a; 它们的时间复杂度都是O(nlogn) 存储方式…

ets Jan 8 2013,rst cause:1, boot mode:(3,6)解决esp8266不断崩溃重启!

1.RAM使用不要超过50% 2.usb直接插在电脑上&#xff0c;不要插在usb扩展坞上&#xff0c;防止电流太小造成开发板电量不够而引起的不断重启&#xff08;千万注意这个&#xff01;&#xff09; 3.减少全局变量使用 4.减少不必要的方法定义 5. //调试代码的时候打开 struct rst_i…

Three.js——基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

C#基础|构造方法相关

哈喽&#xff0c;你好&#xff0c;我是雷工。 以下为C#方法相关的学习笔记。 01 方法的概述 概念&#xff1a;方法表示这个对象能够做什么&#xff0c;也就是封装了这个对象行为。 类型&#xff1a;实例方法—>静态方法&#xff08;抽象方法、虚方法&#xff09;—>特殊…

【JAVA进阶篇教学】第五篇:Java多线程编程

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第五篇&#xff1a;Java多线程编程。 在Java编程中&#xff0c;使用多线程可以提高程序的并发性能&#xff0c;但是直接创建和管理线程可能会导致资源浪费和性能下降。Java提供了线程池来管理线程的生命周期和执行任务…

【蓝桥杯省赛真题40】python摘苹果 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析

目录 python摘苹果 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python摘苹果 第十三届蓝桥杯青少年组python编程省赛真题 一、题目要求 &…

浅谈数据模型

1&#xff1a;事实表和维表的概述 前言&#xff1a;数据仓库是一种用于存储和管理大量数据的技术。其中&#xff0c;事实表和维表是数据仓库中的两个重要概念&#xff0c;首先了解一下事实表和维度表 1.事实表&#xff1a;是指用于存储测量“事实数据”的表&#xff0c;事实数…

IE浏览器,文件下载失败,onDownloadProgress方法里报错:无法获取未定义或null引用的属性“getResponseheader“

问题背景&#xff1a; 谷歌、火狐、edge都没有问题&#xff0c;ie11浏览器也没有问题&#xff0c;ie10及以下会报错&#xff0c;无法获取未定义或null引用的属性"getResponseheader 查看代码&#xff0c;getResponseHeader这个方法是在获取进度条的时候使用&#xff0c; …

OpenWRT设置自动获取IP,作为二级路由器

前言 上一期咱们讲了在OpenWRT设置PPPoE拨号的教程&#xff0c;在光猫桥接的模式下&#xff0c;OpenWRT如果不设置PPPoE拨号&#xff0c;就无法正常上网。 OpenWRT设置PPPoE拨号教程 但现在很多新装的宽带&#xff0c;宽带师傅为了方便都会把光猫设置为路由模式。如果你再外…

SpringCloud系列(15)--Eureka自我保护

前言&#xff1a;在上一章节中我们说明了一些关于Eureka的服务发现功能&#xff0c;也用这个功能进行接口的实现&#xff0c;在本章节则介绍一些关于Eureka的自我保护 1、Eureka保护模式概述 保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。默认情况…

带你走进不一样的策略模式

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 带你走进不一样的策略模式 前言策略模式简介概念解释 策略模式的结构策略模式优点项目实践之bean策略构思业务策略实现策略接口实现策略上下文业务实现 前言 在编程的世界里&#xff0c;每一次按键都…

Golang对接Ldap(保姆级教程:概念搭建实战)

Golang对接Ldap&#xff08;保姆级教程&#xff1a;概念&搭建&实战&#xff09; 最近项目需要对接客户的LDAP服务&#xff0c;于是趁机好好了解了一下。LDAP实际是一个协议&#xff0c;对应的实现&#xff0c;大家可以理解为一个轻量级数据库。用户查询。比如&#xff…