4.14Linux
Itop4412开发板

1、传感器介绍

DS18B20是 DALLAS公司生产的一线式数字温度传感器,具有3引脚TO-92小体积封装形式;温度测量范围为-55℃~+125℃,可编程为9位~12位A/D转换精度,测温分辨率可达0.0625℃,被测温度用符号扩展的16位数字量方式串行输出;其工作电源既可在远端引入,也可采用寄生电源方式产生;多个DS18B20可以并联到3根或2根线上,CPU只需一根端口线就能与诸多DS18B20通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。以上特点使DS18B20非常适用于远距离多点温度检测系统。

操作指令:

在这里插入图片描述

2、硬件连接

2.1、DS18B20 引脚定义:

在这里插入图片描述
① DQ 为数字信号输入/输出端(电压范围:3.0~5.5V);
② GND 为电源地;
③ VDD 为外接供电电源输入端(在寄生电源接线方式时接地)。
由于 iTOP-4412 开发板的引脚输出电压是 1.8V。

2.2、查找底板原理图:

在这里插入图片描述

J38 接口我们使用 :
4 号共地引脚,11 号 3.3V 电源引脚。

连接情况为:
4 号引脚接 DS18B20 模块的 GND,11 号接 DS18B20 模块的 VDD。
13号引脚接到 DS18B20 模块的 DQ 引脚。

2.3、找到引脚的名字:

找到XURTS1叫做GPA0_7

在这里插入图片描述

3、配置平台文件

在内核源码目录,使用“vi arch/arm/mach-exynos/mach-itop4412.c”命令打开平台文件。搜索关键词“struct platform_device s3c_device_buzzer_ctl”找到 buzzer 配置。然后在它的上面添加如下信息

在这里插入图片描述

#ifdef CONFIG_DS18B20_CTL
struct platform_device s3c_device_ds18b20_ctl = {
	.name = "ds18b20",
	.id = -1,
};
#endif

添加完如图:

在这里插入图片描述

保存,退出。

再次使用“vi arch/arm/mach-exynos/mach-itop4412.c”命令打开平台文件。搜索关键词“&s3c_device_buzzer_ctl”,在这一行上面添加:

#ifdef CONFIG_DS18B20_CTL
	&s3c_device_ds18b20_ctl,
#endif

如图:

在这里插入图片描述
保存,退出。
使用“vi drivers/char/Kconfig ”命令打开 Kconfig 配置文件。搜索关键词“BUZZER_CTL”,在该段的上面添加如下信息。

config DS18B20_CTL
	bool "Enable DS18B20 config"
	default y
	help
		Enable DS18B20 config

如图:

在这里插入图片描述
保存,退出。

在内核源码目录使用“cp config_for_linux_scp_elite .config”命令配置缺省信息。(用户要根据自己板子修改配置命令)

在内核目录下使用“make menuconfig”命令打开内核配置界面,如下图。

在这里插入图片描述
进入到 Device Drivers —>Character devices 目录。如下图。

在这里插入图片描述
可以看到 DS18B20 设备已经被选中。

然后保存退出内核配置界面。使用“make zImage”命令编译内核。如下图。

在这里插入图片描述
编译完成后如下图。

在这里插入图片描述
然后把编译生成的 zImage (在 arch/arm/boot 目录下)烧写到 iTOP-4412 开发板上,烧写完成后启动开发板。

开发板启动之后,使用命令“ls /sys/devices/platform/”可以查看到新注册的ds18b20 设备,如下图所示。

在这里插入图片描述
设备注册完成。

4、驱动应用程序

当主机需要对多个DS18B20中的某一个进行操作时,主机首先逐个与DS18B20挂接-搜索ROM(FOH),读出其序列号-读ROM(33H),然后发出匹配ROM(55H),紧接着提供64位序列号,之后的操作就是针对DS18B20的了。

如果只有一个DS18B20测温,就不需要搜索ROM、读ROM以及匹配ROM等操作了,只要用跳过ROM(CCH),就可进行如下温度转换(44H)和读取操作(BEH)了。

在这里插入图片描述

4.1、驱动程序

了解了上述指令之后,要想编程使用DS18B20的测温功能,还需要进一步知道如何进行初始化以及如何进行指令的发送与温度的接收,这就需要深入理解初始化和读与写的时序图。

相对于之前的编程实践,在对DS18B20进行操作时,对时间的要求比较严格,且单总线协议理解起来相对困难,如果把握不好,往往不能正确实现测温功能。为此,需要深入掌握其时序要求。

所有与DS18B20的通信过程都是以初始化开始,下面首先介绍DS18B20的初始化时序图。

4.1.1、初始化时序:

在这里插入图片描述
主机首先发出一个480 ~ 960us的低电平脉冲(复位),然后释放总线变为高电平,并在随后的480微秒时间内,对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。

作为从机的DS18B20上电后就一直检测总线上是否有480 ~ 960微秒的低电平出现,如果检测到该复位脉冲则在总线变为高电平后,等待15~60微秒,之后将总线电平拉低60 ~ 240微秒(响应存在脉冲),告诉主机本器件已做好准备。若检测不到复位脉冲则一直处于检测等待。

主机将DQ拉成低电平保持最少480us后释放总线,延时15 ~ 60us后的60 ~ 240us时间内检测DQ是否为低电平,再延时240us保持起始时序的完整。(从主机角度看进行初始化的过程)

unsigned char init_ds(void)//ds18b20复位,返回0成功,返回1失败
{
        unsigned char ret = 1;
		int i =0;
        s3c_gpio_cfgpin(DS18B20_DQ,OUTPUT);
        s3c_gpio_setpull(DS18B20_DQ, S3C_GPIO_PULL_DOWN);
        gpio_direction_output(DS18B20_DQ,0);
	    udelay(250);
        gpio_direction_output(DS18B20_DQ,0);//发送复位脉冲
        udelay(500);//延时( >480us )
        gpio_direction_output(DS18B20_DQ,1);//拉高数据线  
	    s3c_gpio_cfgpin(DS18B20_DQ, INPUT); //用返回的值来判断初始化有没有成功,18B20存在的话=0,否则=1 
		
	while((ret==1)&&(i<10)){
		ret = gpio_get_value(DS18B20_DQ);
		udelay(10);
		i++;
	}
	if(ret==0){
		return 0;
	}
	else{
               return -1;
	}			
}



4.1.2、主机写0和1的时序

在这里插入图片描述
写周期 最少为60微秒,最长不超过120微秒。 写周期的开始,主机先把总线拉低大于1微秒表示写周期开始。随后若主机想写0,则继续拉低电平最少60微秒直至写周期结束,然后释放总线为高电平若主机想写1,在拉低总线电平1微秒后就释放总线为高电平,一直到写周期结束。 作为从机的DS18B20在检测到总线被拉低后等待15微秒后从15us~45us对总线采样(典型时间15us),在采样时间内,若检测到总线为高电平则认为主机发送了1,若检测到总线为低电平则认为主机发生了0。

void write_byte(char data)//向18b20写一个字节
{                          //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,
    int i = 0;
    s3c_gpio_cfgpin(DS18B20_DQ,OUTPUT);
	s3c_gpio_setpull(DS18B20_DQ, S3C_GPIO_PULL_UP);
	for(i=0;i<8;i++) 
        {
                gpio_direction_output(DS18B20_DQ,0);
	        udelay(10);
                gpio_direction_output(DS18B20_DQ,1);
                gpio_direction_output(DS18B20_DQ, data&0x01);  
                udelay(40);
                gpio_direction_output(DS18B20_DQ,1); 
                udelay(2);
                data >>= 1;
	}		
}
4.1.3、主机读0和1的时序

在这里插入图片描述
读周期最少为60微秒,最长不超过120微秒。读周期的开始主机先把总线拉低大于1微秒,然后释放总线。主机释放总线后,若DS18B20发送0,则把总线拉低并保持至少从读周期开始的15us,然后释放总线为高电平若DS18B20发送1,则在主机释放总线后不拉低总线(为高电平)主机须在读周期开始的15us内检测总线电平的高低,若检测到总线为低则表示DS18B20发送来0,若检测到总线为高则表示DS18B20发送来1。

unsigned char read_byte(void)//从18b20读一个字节
{                                     //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
        unsigned char i;
        unsigned char data=0;
        s3c_gpio_cfgpin(DS18B20_DQ,OUTPUT); 
        for(i=0;i<8;i++)  
	{
                data >>= 1;
	        gpio_direction_output(DS18B20_DQ,0);
	        udelay(1);
	        gpio_direction_output(DS18B20_DQ,1);
	        s3c_gpio_cfgpin(DS18B20_DQ,INPUT);
                udelay(10);		   
	        if(gpio_get_value(DS18B20_DQ))
	        data |= 0x80;
	        udelay(50);           
                s3c_gpio_cfgpin(DS18B20_DQ,OUTPUT);
	        gpio_direction_output(DS18B20_DQ,0);
	        gpio_direction_output(DS18B20_DQ,1);		   
	}               		  
        return data; 
}
4.1.4、读写时序的规则

在这里插入图片描述
1、无论是读还是写,都是以主机把总线拉低至少1us开始。
2、无论是写0还是读0,都是以把总线释放至少1us结束。对于写0尤其需要注意(程序设计),对于读零过程由DS18B20负责拉高(其实结束前早以拉高)。

4.1.5、归纳DS18B20测温的步骤

一、进行ROM操作

1、主机进行复位操作,即: DS18B20的初始化。
2、主机对DS18B20写跳过ROM指令(CCH),在单个DS18B20情况下可不进行其它ROM操作。
3、主机对DS18B20写启动温度转换命令(44H),启动温度检测和转换。
4、延时等待以便让DS18B20完成温度转换,延时时间根据分辨率定。
注意:每个指令字节在写的时候都是低位在前、高位在后

例如CCH的二进制为
11001100,主机发送该指令的顺序是“零、零、壹、壹、零、零、壹、壹”。上述操作的总线状态如下图。
在这里插入图片描述

二、进行RAM操作

1、主机进行复位操作。
2、主机对DS18B20写跳过ROM指令(CCH)。
3、主机发出读取RAM的命令 (BEH) , DS18B20接到指令后依次将9个字节的内容按照 低字节在前、低位在前 的顺序逐位送出数据。主机可依次读取9个字节的数据,如果只想读取温度数据,在读完前2个字节的数据后就不用再理会后面送来的内容。
上述操作的总线状态如下图:

在这里插入图片描述

4.2、应用程序

#include <stdint.h>
#include <termios.h>
#define K 0.0625
int main(int argc , char **argv){
	int fd,i=5;
	char count = 5;
	unsigned int tmp;
	float res=0;
	char *hello_node = "/dev/ds18b20";
	if((fd = open(hello_node,O_RDWR|O_NOCTTY))<0){
		printf("APP open %s failed",hello_node);
	}
	else{ 
                 printf("open ds18b20 success \n" );					
	} 
	while(i--){
		read(fd, &tmp , sizeof(tmp));
		printf("read");
	        sleep(1);
	}
	res=tmp*K;
	printf("the currently temperature is %f\n",res); 		
    close(fd);
        return 0;  
}	

5、编译运行测试

5.1、Makefile文件

#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件itop4412_hello.o
obj-m += itop4412-ds18b20.o 

#源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

#当前目录变量
PWD ?= $(shell pwd)

#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:
	make -C $(KDIR) M=$(PWD) modules
		
#make clean执行的操作是删除后缀为o的文件
clean:
	rm -rf *.o

把驱动程序“itop4412-ds18b20.c”和 Makefile 文件上传到同一目录,执行“make”命令。如下图。
在这里插入图片描述
通过 U 盘挂载、tftp 或者 nfs 功能把“itop4412-ds18b20.ko”文件上传到开发板。

5.2、应用程序编译

把应用程序“test-itop4412-ds18b20.c”上传到 ubuntu 系统。使用“ arm-none-linux-gnueabi-gcc-o test-itop4412-ds18b20 test-itop4412-ds18b20.c -static”命令来静态编译应用程序。如下图。

在这里插入图片描述
通过 U 盘挂载、tftp 或者 nfs 功能把“test-itop4412-ds18b20”文件上传到开发板。如下图。

在这里插入图片描述

6、运行测试

使用“insmod itop4412-ds18b20.ko”命令来加载驱动程序。如下图。

在这里插入图片描述
由上图可知。进入 probe,并且 ds18b20 初始化成功。

使用“ ./test-itop4412-ds18b20”运行应用程序,提示权限不够。使用“chmod 777 test-itop4412-ds18b20”命令修改权限后,继续运行应用程序,如下图。

在这里插入图片描述

程序运行大约 5、6 秒之后,自动停止,并返回温度值。由上图可知当前室内温度为22.68℃。

使用“rmmod itop4412-ds18b20”命令卸载驱动。如下图。

在这里插入图片描述
由上图可知卸载成功,测试完成。

→编译好的驱动、应用、运行环境(内核、文件系统)、文档等等←

7、DS18B20的使用总结

1、使用DS18B20测温硬件简单,但是以软件的相对复杂为代价的。单总线协议对时序的要求比较严格,进行程序设计时,必须严格保证初始化以及读写的时序要求,否则将无法读取测温结果。这点对于采用c语言等高级语言进行程序设计时尤为重要,对DS18B20的操作建议采用汇编语言。

2、实际使用中要注意连接DS18B20的总线电缆长度限制。根据部分资料显示:
(1)采用普通信号电缆传输长度超过50m时,读取的测温数据将发生错误。
(2) 采用带屏蔽层的双绞线电缆时,正常通讯距离可以达到150m。
(3)采用每米绞合次数更多的带屏蔽层双绞线电缆时,正常通讯距离进一步加长。这种情况主要是由总线分布电容使信号波形产生畸变造成的。
因此,在用DS18B20进行长距离测温时要充分考虑总线分布电容和阻抗匹配问题。测温电缆线建议采用屏蔽4芯双绞线,其中一对接地线与信号线,另一对接VCC和地线,屏蔽层在DS18B20端单点接地。

3、在设计DS18B20测温程序时,完整的初始化应该检测DS18B20是否产生了应答,一般确认器件没有问题时可以采用延时而不检测,若要检测则需要防范在无应答时可能出现程序死循环的现象,这一点在进行DS18B20硬件连接和软件设计时应加以重视。

Logo

更多推荐