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

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

3天内不再提示

DS18B20驱动编写–杂项设备框架注册

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-09-21 08:48 次阅读

DS18B20驱动编写–杂项设备框架注册

设备驱动最通俗的解释就是“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮询、中断处理、DMA通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。

驱动程序是应用层和硬件层的连接桥梁,应用层只管完成应用逻辑开发和界面设计,驱动层则处理硬件配置,实现应用层相关接口函数。

杂项设备:字符设备类的一种,杂项设备主设备号为10。

1.DS18B20简介

DS18B20是Dallas半导体公司生产的数字温度传感器,是世界上第一片支持"一线总线"接口的温度传感器。测量温度范围为-55℃ ~ +125℃,精度为±0.5℃。分辨率为9 ~ 12位。支持3V ~ 5.5V输入电压。抗干扰能力强。
每一个DSl820包括一个唯一的64位长的序号,该序号值存放在 DSl820 内部的 ROM(只读存贮器)中。开始8位是产品类型编码(DSl820 编码均为 10H) ,接着的 48位是每个器件唯一的序号,最后 8 位是前面 56 位的CRC(循环冗余校验)码。

pYYBAGMpvreAD0hgAAChVXaW_0A011.png#pic_center
引脚 说明
GND
DQ 数字信号
VDD 电源脚3V~5.5V

  DS18B20以9位数字量形式反应器件的温度值。
  DS18B20采用单总线通讯,与CPU之间只需要DQ脚相连,再和CPU之间共地即可。每一个DS18B20都有唯一的64位光刻ROM,因此可以在一根数据线上接多个DS18B20模块。

  • 单总线协议特性
  • 总线协议:一个数据线可挂载多个设备(DS18B20通过64位光刻ROM区分设备);
  • 半双工通讯:数据线上同一时间只能发送或者接收数据;

2.DS18B20驱动时序

2.1 发送复位脉冲和检测存在信号

pYYBAGMpvreAbF-eAAEld8BnKb4938.png#pic_centerpoYBAGMpvreAOwBiAACSg2l3pxo773.png#pic_center

  DS18B20初始化过程首先需要发送复位脉冲:至少480us的低电平信号。接下来释放总线,DS18B20开始返回存在信号:60~240us的低电平。最后释放总线,模块初始化完成。

/*发送复位信号,检测存在脉冲*/
static u8 ds18b20_CheckRst(void)
{
	u8 time=0;
	DS18B20_OUT_MODE();/*输出模式*/
	DS18B20_OUT(0);/*总线拉低*/
	udelay(600);/*至少480us低电平*/
	DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/
	udelay(15);
	DS18B20_INPUT_MODE();/*输入模式*/
	while(DS18B20_IN)
	{
		time++;
		udelay(1);
		if(time>=100)return 1;/*等待存在脉冲失败*/
	}
	time=0;
	while(!DS18B20_IN)
	{
		time++;
		udelay(1);
		if(time>=250)return 2;//模块出错
	}
	return 0;	
}

2.2 写一位数据时序

pYYBAGMpvriATfxzAADQRiGzSM8534.png#pic_center

  要实现写一字节数据,则首先要实现的是写一位数据时序。分为写1和写0。首先是总线拉低,产生写间隙(至少1us)。接着往数据线DQ上写入0或者1,周期时间为60us,最后释放总线(总线拉高,至少1us),至此,写数据完成。

DS18B20_OUT_MODE();/*输出模式*/
DS18B20_OUT(0);//总线拉低,产生写间隙时间
udelay(2);
if(dat&0x01)DS18B20_OUT(1);
else DS18B20_OUT(0);
udelay(60);//写周期时间
DS18B20_OUT(1);//释放总线
udelay(2);
dat>>=1;//继续发送下一位数据

2.3 读一位数据时序

poYBAGMpvriAecO2AAEQ7d3wJM8281.png#pic_center

  读数据首先需要主机产生读间隙:总线拉低,至少1us的低电平信号。接着释放总线,在15us内进行数据读取,读数据周期时间为60us,最后释放总线:总线拉高,至少1us时间。 至此,读一位数据完成。

DS18B20_OUT_MODE();/*输出模式*/
DS18B20_OUT(0);//总线拉低,产生读间隙时间
udelay(2);
DS18B20_INPUT_MODE();//配置为输入模式
udelay(12);//等待数据到来
data>>=1;
if(DS18B20_IN)data|=0x80;
udelay(50);//读数据时间
DS18B20_OUT(1);//恢复总线为空闲电平
udelay(2);

3.DS18B20相关命令

  • 跳转指令0xCC

这条指令允许控制器不需要提供64位光刻ROM就使用存储器操作命令,在总线上仅有一个DS18B20时使用,若有多个则会产生冲突。

  • 启动一次温度转换0x44

此命令完成一次温度转换。执行此命令后,DS18B20保持等待状态。若总线在这条命令发送后跟着读间隙,而DS18B20正处于数据转换,则会输出一个0,若温度转换完成,则会输出1。若使用寄生电源,总线必须在这条命令发完后拉高总线,保存500ms。

  • 读取一次数据0xBE

此命令用于读取暂存器中的内容,可连续读取9个字节数据。若只想读取温度数据,则只需要读取前两个字节即可。

pYYBAGMpvriAazqwAABlG4HaAp4099.png#pic_center
  • 读ROM 0x33

此命令可以读取DS18B20的64位光刻ROM数据,此命令仅能在总线上一个设备的时候使用。

  • 匹配ROM 0x55

此命令可以实现和DS18B20的ROM进行匹配,只有和DS1820的64位光刻ROM完全匹配才能响应后面存储器命令。此命令用于当总线上不止一个设备时使用。

  • 搜索ROM 0xF0

当系统第一次启动时,无法确认总线上有多少个设备或者该设备的光刻ROM,搜索光刻ROM可以让控制器通过排除法识别总线上的所有设备的64位光刻ROM。

4.DS18B20采集一次温度步骤

  采用外部电源供电,且总线上仅有一个DS18B20模块。

poYBAGMpvrmASyCNAAIrYEB6EUw129.png#pic_center

5.编写DS18B20驱动,通过杂项设备注册

  • 开发平台

开发平台:Ubuntu18.04
编译器:arm-linux-gcc
硬件平台:tiny4412基于Cortex-A9 4核1.5GHZ
开发板内核:Linux3.5

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

static unsigned int ds18b20_gpio=EXYNOS4_GPB(4);//GPB_4
#define DS18B20_OUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT)/*输出模式*/
#define DS18B20_INPUT_MODE()  s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_INPUT)/*输入模式*/
#define DS18B20_OUT(x)   gpio_set_value(ds18b20_gpio,(x))
#define DS18B20_IN   		gpio_get_value(ds18b20_gpio)
/*发送复位信号,检测存在脉冲*/
static u8 ds18b20_CheckRst(void)
{
	u8 time=0;
	DS18B20_OUT_MODE();/*输出模式*/
	DS18B20_OUT(0);/*总线拉低*/
	udelay(600);/*至少480us低电平*/
	DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/
	udelay(15);
	DS18B20_INPUT_MODE();/*输入模式*/
	while(DS18B20_IN)
	{
		time++;
		udelay(1);
		if(time>=100)return 1;/*等待存在脉冲失败*/
	}
	time=0;
	while(!DS18B20_IN)
	{
		time++;
		udelay(1);
		if(time>=250)return 2;//模块出错
	}
	return 0;	
}
/*写一个字节函数*/
static void ds18b20_writeDat(u8 dat)
{
	int i=0;
	DS18B20_OUT_MODE();/*输出模式*/
	for(i=0;i<8;i++)
	{
		DS18B20_OUT(0);//总线拉低,产生写间隙时间
		udelay(2);
		if(dat&0x01)DS18B20_OUT(1);
		else DS18B20_OUT(0);
		udelay(60);//写周期时间
		DS18B20_OUT(1);//释放总线
		udelay(2);
		dat>>=1;//继续发送下一位数据
	}
}
/*读取1字节数据*/
static u8 ds18b20_readDat(void)
{
	int i=0;
	u8 data=0;
	for(i=0;i<8;i++)
	{
		DS18B20_OUT_MODE();/*输出模式*/
		DS18B20_OUT(0);//总线拉低,产生读间隙时间
		udelay(2);
		DS18B20_INPUT_MODE();//配置为输入模式
		udelay(12);//等待数据到来
		data>>=1;
		if(DS18B20_IN)data|=0x80;
		udelay(50);//读数据时间
		DS18B20_OUT(1);//恢复总线为空闲电平
		udelay(2);
	}
	return data;
}

/*获取一次温度数据*/
static u16 ds18b20_GetTemp(void)
{
	u8 L,H;
	u16 temp;
	if(ds18b20_CheckRst())return 0xffff;
	ds18b20_writeDat(0xcc);
	ds18b20_writeDat(0x44);
	while(ds18b20_readDat()!=0xff);/*等待温度转换完成*/
	if(ds18b20_CheckRst())return 0xffff;
	ds18b20_writeDat(0xcc);
	ds18b20_writeDat(0xbe);/*读取一次温度*/
	L=ds18b20_readDat();
	H=ds18b20_readDat();
	temp=H<<8|L;
	return temp;
}
static int ds18b20_open(struct inode *inode, struct file *file)
{
	printk("open函数调用成功\n");
	if(ds18b20_CheckRst())
	{
		printk("DS18B20初始化失败\n");
	}
	return 0;
}
static int ds18b20_release(struct inode *inode, struct file *file)
{
	printk("release函数调用成功");
	return 0;
}
long ds18b20_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int dir=_IOC_DIR(cmd);/*数据读写方向,00无参数,10用户层读,01用户层写,11可读写*/
	int type=_IOC_TYPE(cmd);/*魔术,标志符*/
	int size=_IOC_SIZE(cmd);/*arg的字节数*/
	printk("dir=%d,type=%c,size=%d\n",dir,type,size);
	int ret;
	u16 temp=ds18b20_GetTemp();/*获取一次温度*/
	ret=copy_to_user((void *)arg, &temp,size);
	return 4-ret;
}
static  struct file_operations ds18b20_fops=
{
	.open			=ds18b20_open,
	.release		=ds18b20_release,
	.unlocked_ioctl	=ds18b20_ioctl
};

/*杂项设备结构体*/
static struct miscdevice ds18b20_drv=
{
	.minor	=MISC_DYNAMIC_MINOR,/*255,有内核自动分配*/
	.name	="ds18b20",//设备节点名字
	.fops	=&ds18b20_fops,//文件操作集合
};
static int __init wbyq_ds18b20_init(void)
{
	/*1.GPIO注销*/
	gpio_free(ds18b20_gpio);
	/*2.注册GPIO*/
	gpio_request(ds18b20_gpio,"DS18B20");
	/*配置GPIO模式*/
	s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT);
	gpio_set_value(ds18b20_gpio,1);/*上拉*/
	/*注册杂项设备*/
	misc_register(&ds18b20_drv);
	return 0;
	
}
/*驱动释放*/
static void __exit wbyq_ds18b20_cleanup(void)
{
    printk("驱动出口,驱动注销成功\n");
	/*注销杂项设备*/
	misc_deregister(&ds18b20_drv);
	/*注销GPIO*/
	gpio_free(ds18b20_gpio);
}
module_init(wbyq_ds18b20_init);//驱动入口函数
module_exit(wbyq_ds18b20_cleanup);//驱动出口函数

MODULE_LICENSE("GPL");//驱动注册协议
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 ds18b20 Driver");
poYBAGMpvrqAcXWFAAWyG9mUpw4388.png#pic_center



审核编辑:汤梓红


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 温度传感器
    +关注

    关注

    48

    文章

    2650

    浏览量

    154300
  • DS18B20
    +关注

    关注

    10

    文章

    765

    浏览量

    80100
  • 设备驱动
    +关注

    关注

    0

    文章

    64

    浏览量

    10805
收藏 人收藏

    评论

    相关推荐

    DS18B20

    各位大神帮知道为什么DS18B20和12864显示的数据不一样吗??DS18B20的子函数是看别人的,感觉没什么错误! //初始化ds1820bit Init_DS18B20(void
    发表于 05-11 14:22

    stm32驱动ds18b20问题

    问题是这样的,我的ds18b20在51单片机可以读取温度,但是stm32就读取不了电源正确,51都能读取没有上拉电阻,百度了一下,可以不带上拉电阻软件的话,我是改stm32输入输出来驱动的,输入输出
    发表于 08-24 13:15

    DS18B20编写

    我最近在用DS18B20显示温度,但是显示的一直是00.0,应该是DS18B20模块的时序有问题,求大神指导一下正确的时序应该怎么写。
    发表于 01-06 18:53

    基于Linux的温度传感器DS18B20驱动程序设计

    驱动最终能否得以正常运行,获得实时温度值,关键在于能否正确地编写复位程序、位写程序和位读程序。  3.1复位程序  对DS18B20进行读写之前要对其复位初始化,以检测DS18B20
    发表于 11-14 15:24

    DS18B20温度传感器实验

    STM32学习记录:DS18B20温度传感器实验(HAL库)实验摘要DS18B20简述STMCubeMX引脚配置芯片选型引脚和时钟配置生成ARM-MDK工程编写DS18B20
    发表于 08-18 07:44

    DS18B20简介

    1、DS18B20简介DS18B20本身就是一个温度传感器,只需要将DS18B20的数据引脚和单片机的一个I/O口接上,单片机通过1-Wire协议与DS18B20进行通信,读出温度。C
    发表于 11-22 07:21

    DS18B20驱动根据数据手册分享

    DS18B20驱动根据数据手册编写#include***it ds18b20=P1^4;void delay_ds18b20(unsigne
    发表于 11-30 07:33

    DS18B20的基本概述

    文章目录1、DS18B20的基本概述2、DS18B20内部结构3、DS18B20的内部存储结构4、DS18B20的数据处理5、DS18B20
    发表于 12-02 06:30

    DS18B20驱动代码分享

    ;***it DQ = P1^4;//单总线接口//单总线延时函数void Delay_OneWire(u8 t)//IAP15F2K61S2{t = t * 7;while(t--);}//通过单总线向DS18B20写一个字节void Write_DS18B20(u8
    发表于 12-03 08:03

    DS18b20的相关资料分享

    蓝桥杯嵌入式扩展板模块之温度传感器硬件介绍DS18B20硬件介绍蓝桥杯嵌入式拓展版提供的温度传感器是DS18B20。关于他的驱动文件比赛的的时候是提供的,但是以防万一,自己还是要会写读写文件
    发表于 01-10 08:11

    利用STM8S驱动DS18b20

    STM8S系列驱动DS18b20今天提供STM8系列有关DS18B20 温度传感器的驱动代码具体见下面代码:我这里是找到一些网上使用的Ds18b20
    发表于 01-17 06:12

    怎样去调试一个DS18B20温度模块

    库三、PlatformIO编写程序1.示例程序2.debug3.完成四、其他方法参考资料VSCode+PlatformIO+Arduino+ESP32S2的DS18B20温度模块上一篇
    发表于 01-24 06:04

    应用DS18B20编写的C程序

    用C语言编写的,基于51单片机控制DS18B20的应用程序。
    发表于 11-30 18:18 4次下载

    DS18B20驱动根据数据手册编写

    DS18B20驱动根据数据手册编写#include<reg51.h>sbit ds18b20=P1^4;void delay_ds18b
    发表于 11-21 12:06 73次下载
    <b class='flag-5'>DS18B20</b><b class='flag-5'>驱动</b>根据数据手册<b class='flag-5'>编写</b>

    Linux驱动开发-编写DS18B20驱动

    当前文章介绍如何在Linux系统下编写一个DS18B20温度传感器驱动,测量环境温度,并将DS18B20注册成字符
    的头像 发表于 09-17 15:28 1507次阅读
    Linux<b class='flag-5'>驱动</b>开发-<b class='flag-5'>编写</b><b class='flag-5'>DS18B20</b><b class='flag-5'>驱动</b>