0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux驱动开发-编写DS18B20驱动

DS小龙哥-嵌入式技术 2022-09-17 15:28 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

【摘要】 当前文章介绍如何在Linux系统下编写一个DS18B20温度传感器驱动,测量环境温度,并将DS18B20注册成字符设备,通过文件接口将温度数据传递给应用层。

1. 前言

当前文章介绍如何在Linux系统下编写一个DS18B20温度传感器驱动,测量环境温度,并将DS18B20注册成字符设备,通过文件接口将温度数据传递给应用层。

当前使用的开发板是友善之臂的Tiny4412开发板,CPU三星的Exynos-4412,主频是4核1.5GHZ,当前运行的Linux内核版本是3.5。使用的温度传感器是DS18B20,是一个数字温度传感器,非常经典的一款温度传感器,常年应用在各大高校毕设、实验室、毕设、课设场景。DS1820接线比较简单,只需要一根线就行,加上两根电源线,一共3根线,并且DS18B20支持硬件序列号寻址,支持一个IO口上挂载多个DS18B20。

2. DS18B20介绍

DS18B20特性:

(1)全数字温度转换及输出。
(2)先进的单总线数据通信
(3)最高 12 位分辨率,精度可达土 0.5 摄氏度。
(4)12 位分辨率时的最大工作周期为 750 毫秒。
(5)可选择寄生工作方式。
(6)检测温度范围为–55° C ~+125° C (–67° F ~+257° F)
(7)内置 EEPROM,限温报警功能。
(8)64 位光刻 ROM,内置产品序列号,方便多机挂接。
(9)多样封装形式,适应不同硬件系统。

image-20220102202650673

DS18B20引脚功能

GND 电压地
DQ 单数据总线
VDD 电源电压
NC 空引脚

DS18B20读取温度的步骤:

发送复位信号-->
检测回应信号--->
发送0xCC-->发送0x44->
发送复位信号—>
检测回应信号—>
写0xcc--->
写0xbe--->
循环8次读取温度低字节--->
循环8次读取温度高字节---->
打印温度信息

DS18B20温度转换示例:

u16 temp;
u8 TL,TH;
u16 intT,decT; 	              //温度值的整数和小数部分
TL=DS18B20_Read_Byte();       //读取温度低8位LSB   
TH=DS18B20_Read_Byte();       //读取温度高8位MSB  
temp=((u16)TH<<8)|TL;          //将读出的温度高低位组合成16位的值
intT = temp >> 4;                //分离出温度值整数部分
decT = temp & 0xF;              //分离出温度值小数部分
printf("A: %d.%d\r\n",(int)intT,(int)decT); //打印实际温度值

3. 硬件接线图

Tiny4412开发板扩展GPIO口:

image-20220102203315453image-20220102203906312image-20220102203919777

4. 示例代码

#include 
#include 
#include    /*杂项字符设备头文件*/
#include            /*文件操作集合*/
#include         /*延时函数*/

#include 
#include 
/*DS18B20 GPIO接口: GPB_4*/

/*定义指针,用于接收虚拟地址*/
volatile unsigned int *DS18B20_GPBCON;
volatile unsigned int *DS18B20_GPBDAT;

#define DS18B20_INPUT()  {*DS18B20_GPBCON &= ~(0xf  << 4 * 4);}
#define DS18B20_OUTPUT() {*DS18B20_GPBCON &= ~(0xf  << 4 * 4);*DS18B20_GPBCON |=  (0x1   << 4 * 4);}

/*
函数功能:等待DS18B20的回应
返回1:未检测到DS18B20的存在
返回0:存在
*/
unsigned char DS18B20_Check(void) 	   
{   
	unsigned char retry=0;
	DS18B20_INPUT() ///SET PG11 INPUT	 
    while((*DS18B20_GPBDAT & (1 << 4))&&retry<200)
	{
		retry++;
		udelay(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while(!(*DS18B20_GPBDAT & (1 << 4))&&retry<240)
	{
		retry++;
		udelay(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
/*
从DS18B20读取一个位
返回值:1/0
*/
unsigned char DS18B20_Read_Bit(void) 			 // read one bit
{
    unsigned char data;
	DS18B20_OUTPUT();
    *DS18B20_GPBDAT &= ~(1 << 4);//输出0 
	udelay(2);
    *DS18B20_GPBDAT |= (1 << 4);//输出1 
	DS18B20_INPUT()
	udelay(12);
	if((*DS18B20_GPBDAT & (1 << 4)))data=1;
    else data=0;	 
    udelay(50);           
    return data;
}
/*
从DS18B20读取一个字节
返回值:读到的数据
*/
unsigned char DS18B20_Read_Byte(void)    // read one byte
{        
    unsigned char i,j,dat;
    dat=0;
	for(i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
		dat=dat>>1;
		if(j)        //主机对总线采样的数 判断-------读数据-1就是1,否则就是0 
		dat|=0x80;   //先收低位数据--一步一步向低位移动>>
    }						    
    return dat;
}
/*
写一个字节到DS18B20
dat:要写入的字节
*/
void DS18B20_Write_Byte(unsigned char dat)     
 {             
    unsigned char j;
    unsigned char testb;
	DS18B20_OUTPUT();
    for(j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if(testb) 
        {
            *DS18B20_GPBDAT &= ~(1 << 4);//输出0// Write 1
            udelay(2);                            
            *DS18B20_GPBDAT |= (1 << 4);//输出1
            udelay(60);             
        }
        else 
        {
            *DS18B20_GPBDAT &= ~(1 << 4);//输出0// Write 0
            udelay(60);             
            *DS18B20_GPBDAT |= (1 << 4);//输出1
            udelay(2);                          
        }
    }
}
/*
从ds18b20得到温度值
精度:0.1C
返回值:温度值 (-550~1250) 
*/
short DS18B20_Get_Temp(void)
{
	unsigned short aaa;
    unsigned char temp;
	unsigned char TL,TH;
	DS18B20_OUTPUT(); 
    *DS18B20_GPBDAT &= ~(1 << 4);//输出0 //拉低DQ
    udelay(750);    //拉低750us
    *DS18B20_GPBDAT |= (1 << 4);//输出1 //DQ=1 
	udelay(15);     //15US	  
	
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);
    DS18B20_Write_Byte(0x44);
	
    DS18B20_OUTPUT(); 
    *DS18B20_GPBDAT &= ~(1 << 4);//输出0 //拉低DQ
    udelay(750);    //拉低750us
    *DS18B20_GPBDAT |= (1 << 4);//输出1 //DQ=1 
    udelay(15);     //15US
	
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert	    
    TL=DS18B20_Read_Byte();  // LSB   
    TH=DS18B20_Read_Byte();  // MSB  
    aaa=((unsigned short)TH<<8)|TL;
	return aaa;
}
/*
杂项字符设备注册示例----->DS18B20
*/
static int tiny4412_open(struct inode *my_inode, struct file *my_file)
{
	/*映射物理地址*/
	DS18B20_GPBCON=ioremap(0x11400040,4);
	DS18B20_GPBDAT=ioremap(0x11400044,4);
	printk("DS18B20初始化成功!\r\n");
	
	 /*设置ds18b20为输出模式*/
    *DS18B20_GPBCON &= ~(0xf  << 4 * 4);
    *DS18B20_GPBCON |=  (0x1  << 4 * 4);
	return 0;
}
static int tiny4412_release(struct inode *my_inode, struct file *my_file)
{
	/*释放虚拟地址*/
	iounmap(DS18B20_GPBCON);
	iounmap(DS18B20_GPBDAT);
	printk("DS18B20释放成功\r\n");
	return 0;
}
static ssize_t tiny4412_read(struct file *my_file, char __user *buf, size_t len, loff_t *loff)
{
	/*读取温度信息*/
	short temp=DS18B20_Get_Temp();
	copy_to_user(buf,&temp,2);    //拷贝温度至应用层 
	return 0;
}
static ssize_t tiny4412_write(struct file *my_file, const char __user *buf, size_t len, loff_t *loff)
{
	return 0;
}
/*文件操作集合*/
static struct file_operations tiny4412_fops=
{
	.open=tiny4412_open,
	.read=tiny4412_read,
	.write=tiny4412_write,
	.release=tiny4412_release
};
/*
核心结构体
*/
static struct miscdevice tiny4412_misc=
{
	.minor=MISC_DYNAMIC_MINOR,  /*自动分配次设备号*/
	.name="DS18B20",      		/*设备文件,指定/dev/生成的文件名称*/
	.fops=&tiny4412_fops
};

static int __init DS18B20_dev_init(void)
{
    /*杂项设备注册*/
    misc_register(&tiny4412_misc);
	return 0;
}

static void __exit DS18B20_dev_exit(void)
{	
	/*杂项设备注销*/
	misc_deregister(&tiny4412_misc);
}
module_init(DS18B20_dev_init); 
module_exit(DS18B20_dev_exit);
MODULE_LICENSE("GPL");
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 温度传感器
    +关注

    关注

    48

    文章

    3105

    浏览量

    162461
  • 驱动
    +关注

    关注

    12

    文章

    1928

    浏览量

    88204
  • DS18B20
    +关注

    关注

    10

    文章

    782

    浏览量

    83096
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux驱动开发的必备知识

    、内核模块编程: 掌握内核模块的编写、编译、加载和卸载方法。 了解内核模块的初始化和清理函数的编写。 5、设备驱动框架: 熟悉字符设备、块设备、网络设备等驱动框架。 能够根据
    发表于 12-04 07:58

    【免费送书】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    Linux系统的设备驱动开发,一直给人门槛较高的印象,主要因内核机制抽象、需深度理解硬件原理、开发调试难度大所致。2021年,一本讲解驱动
    的头像 发表于 11-18 08:06 437次阅读
    【免费送书】成为硬核<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>者:《<b class='flag-5'>Linux</b> 设备<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>(第 2 版)》

    要做一个DS18B20的读取程序,单总线需要配置为输入或者输出,怎么配置好?

    目前要做一个DS18B20的读取程序,单总线需要配置为输入或者输出。怎么配置好
    发表于 11-18 06:30

    【书籍评测活动NO.67】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    开发设备驱动和板级支持包。截至目前,Linux仍是嵌入式系统领域的主流内核,几乎广泛应用于工业界的所有领域,这主要得益于其功能强大的子系统。因此,约翰·马迪厄编写本书,向广大
    发表于 11-17 17:52

    使用18b20软件包报错怎么解决?

    In file included from ../packages/ds18b20-latest/src/dallas_ds18b20_sensor_v1.c:12:0: C
    发表于 10-14 06:49

    单片机实例项目:DS18B20温度传感器

    单片机实例项目:DS18B20温度传感器,推荐下载!
    发表于 06-03 20:59

    itop-3568开发驱动开发指南-实验程序的编写

    本实验对应的网盘路径为:iTOP-RK3568 开发板【底板 V1.7 版本】\\\\03_【iTOP-RK3568开发板】指南教程\\\\02_Linux 驱动配套资料\\\\04_
    发表于 05-19 10:26

    血泪教训总结:Air780EPM的LuatOS二次开发——OneWire协议调试注意事项

    的OneWire通信,大幅提升项目开发效率。 一、LuatOS 及 OneWire 说明   LuatOS 支持 OneWire 通信协议,本文以 DS18B20 温度传感器和 Air780EPM 搭配
    的头像 发表于 03-20 17:52 906次阅读
    血泪教训总结:Air780EPM的LuatOS二次<b class='flag-5'>开发</b>——OneWire协议调试注意事项

    基于FPGA的DS18B20数字温度传感器测温实例

    本文将使用三段式状态机(Moore型)的写法来对DS18B20进行测温操作,以便了解DS18B20和熟悉三段式状态机的写法。
    的头像 发表于 03-17 11:06 2089次阅读
    基于FPGA的<b class='flag-5'>DS18B20</b>数字温度传感器测温实例

    DS18B20实时温度传感器中文资料

    DS18B20 是一种单总线数字温度传感器,它被广泛应用于各种领域,例如气象监测、室内温度控制、工业自动化等。DS18B20 采用了单总线接口(One-Wire Interface),这意味着可以通过单个引脚与微控制器通信,大大简化了连接和布线
    发表于 02-28 17:02 5次下载

    迅为RK3568开发驱动指南Linux中通用SPI设备驱动

    迅为RK3568开发驱动指南Linux中通用SPI设备驱动
    的头像 发表于 01-23 11:02 3433次阅读
    迅为RK3568<b class='flag-5'>开发</b>板<b class='flag-5'>驱动</b>指南<b class='flag-5'>Linux</b>中通用SPI设备<b class='flag-5'>驱动</b>

    迅为RK3568开发板SPI驱动指南-mcp2515驱动编写:读寄存器函数

    迅为RK3568开发板SPI驱动指南-mcp2515驱动编写:读寄存器函数
    的头像 发表于 01-20 14:43 1504次阅读
    迅为RK3568<b class='flag-5'>开发</b>板SPI<b class='flag-5'>驱动</b>指南-mcp2515<b class='flag-5'>驱动</b><b class='flag-5'>编写</b>:读寄存器函数

    基于FPGA的温度传感器(ds18b20)驱动设计

    本篇主要讨论基于FPGA的温度传感器(ds18b20驱动设计---第一版 设计实现:利用FPGA驱动DS18b20,读取到温度数值显示到数码管上。 首先介绍
    的头像 发表于 01-16 14:08 2051次阅读
    基于FPGA的温度传感器(<b class='flag-5'>ds18b20</b>)<b class='flag-5'>驱动</b>设计

    【正点原子STM32H7R3开发套件试用体验】DS18B20、DHT11温湿度采集

    【正点原子STM32H7R3开发套件试用体验】DS18B20、DHT11温湿度采集 本文主要分为两部分,分别介绍了使用正点原子STM32H7R3开发套件,通过 DS18B20、DHT1
    发表于 01-01 11:16

    《DNESP32S3使用指南-IDF版_V1.6》第二十九章 DS18B20实验

    和IO0连接图如下图所示。 图29.2.3.2 WIRE_DQ和IO0连接图 图29.2.3.3 DS18B20开发板连接的位置29.3 程序设计29.3.1 程序流程图程序流程图能帮助我们更好
    发表于 12-25 09:43