ds18b20温度传感器驱动程序

devtools/2024/9/22 19:40:58/

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_INPUTstatic 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.ppmy.cn/devtools/16636.html

相关文章

上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 如果软件开发好了之后&#xff0c;下面就是实施和部署。对于树莓派4b来说&#xff0c;部署其实就是烧录卡和拷贝文件。之前我们烧录卡&#xff0c;…

图神经网络 | 混合神经网络模型GCTN地铁客流预测

随着城市人口的不断增加,城市交通也在迅速扩张,这对城市的可持续发展提出了新的挑战。与私家车相比,城市轨道交通可以减少与交通相关的能源消耗、出行成本、交通拥堵和环境污染。同时,研究表明,在城市轨道交通强度较高的城市,汽车保有量的增长相对较慢。因此,地铁、公交…

vue+springboot项目的登录验证码(JAVA自带)

后台springboot CaptureController package com.example.controller;import com.example.common.Result; import com.example.service.AuthCodeService; import com.example.utils.CodeUtils; import lombok.SneakyThrows; import org.apache.ibatis.annotations.Param; impo…

浅谈菊风实时音视频 (RTC)与实时操作系统 (RTOS) 在智能硬件领域应用

近年来&#xff0c;菊风通过实时音视频赋能智能手表、智能门禁、智能门锁/门铃、智能眼镜等数十种智能硬件&#xff0c;与一众合作伙伴共同探索在IoT智能硬件领域的不同场景应用&#xff0c;积累了丰富的实践经验。在智能硬件中&#xff0c;RTOS因其轻量化的系统内核&#xff0…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 一、简单介绍 二、简单进行人脸训练与识别 1、LBPH…

开源向量数据库比较:Chroma, Milvus, Faiss,Weaviate

语义搜索和检索增强生成(RAG)正在彻底改变我们的在线交互方式。实现这些突破性进展的支柱就是向量数据库。选择正确的向量数据库能是一项艰巨的任务。本文为你提供四个重要的开源向量数据库之间的全面比较&#xff0c;希望你能够选择出最符合自己特定需求的数据库。 什么是向量…

PostgreSQL的学习心得和知识总结(一百三十九)|深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

组合优于继承:什么情况下可以使用继承?

C设计模式专栏&#xff1a;http://t.csdnimg.cn/8Ulj3 目录 1.引言 2.为什么不推荐使用继承 3.相比继承&#xff0c;组合有哪些优势 4.如何决定是使用组合还是使用继承 1.引言 面向对象编程中有一条经典的设计原则:组合优于继承&#xff0c;也常被描述为多用组合&#xff0…