第27章 DS18B20温度传感器
来源:互联网 发布:网络传播负面消息方法 编辑:程序博客网 时间:2024/05/21 08:55
27.1硬件原理
下图是我们温度传感器的接入引脚,3.3V 供电,io 口接 P13 的 GP0( GPIO0 的简称 )。
DS18B20 数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有 LTM8877,LTM8874 等等。主要根据应用场合的不同而改变其外观。封装后的 DS18B20 可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
27.2单总线的概念
目前常用的微机与外设之间进行数据传输的串行总线主要有 I2C 总线、 SPI 总线和 SCI总线。其中 I2C 总线以同步串行 2 线方式进行通信(一条时钟线,一条数据线) ,SPI 总线则以同步串行 3 线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线),而 SCI 总线是以异步方式进行通信(一条数据输入线,一条数据输出线) 。这些总线至少需要两条或两条以上的信号线。
1-wire , 即 单 线 总 线 , 又 叫 单 总 线 。 近 年 来 , 美 国 的 达 拉 斯 半 导 体 公 司(DALLASSEMICONDUCTOR) 推出了一项特有的单总线(1-Wire Bus)技术。该技术与上述总线不同,它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优点。
27.3 ds18b20 相关时序
初始化(复位)时序图:
(1) 先将数据线置高电平“ 1” 。
(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
(3) 数据线拉到低电平“ 0” 。
(4) 延时 750 微秒(该时间的时间范围可以从 480 到 960 微秒) 。
(5) 数据线拉到高电平“ 1” 。
(6) 延时等待(如果初始化成功则在 15 到 60 微秒时间之内产生一个由 DS18B20 所
返回的低电平“ 0” 。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制) 。
(7) 若 CPU 读到了数据线上的低电平“ 0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要 480 微秒。
(8) 将数据线再次拉高到高电平“ 1”后结束。
写 ds18b20 时序图:
(1) 数据线先置低电平“ 0” 。
(2) 延时确定的时间为 15 微秒。
(3) 按从低位到高位的顺序发送字节(一次只发送一位) 。
(4) 延时时间为 45 微秒。
(5) 将数据线拉到高电平。
(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7) 最后将数据线拉高。
读 ds18b20 时序图:
(1)将数据线拉高“ 1” 。
(2)延时 2 微秒。
(3)将数据线拉低“ 0” 。
(4)延时 3 微秒。
(5)将数据线拉高“ 1” 。
(6)延时 5 微秒。
(7)读数据线的状态得到 1 个状态位,并进行数据处理。
(8)延时 60 微秒。
27.4驱动程序
关于字符设备驱动程序的使用,我们可以参照点亮 led 灯的那个实验,这里只给出跟ds18b20 密切相关的驱动程序,详细的程序请查看我们的驱动文件!
//配置连接温度传感器的引脚#define DS18B20_L *GPIO21_0_DATA &= ~(1<<0) //低电平 #define DS18B20_H *GPIO21_0_DATA |= (1<<0) //高电平#define DS18B20_OUT *GPIO21_0_DIR |= (1<<0) //输出 #define DS18B20_IN *GPIO21_0_DIR &= ~(1<<0) //输入 #define DS18B20_STA *GPIO21_0_DATA & 0x01 //寄存器定义volatile unsigned long *GPIO21_0_DIR;volatile unsigned long *GPIO21_0_DATA; /**************** 基本定义 **********************///初始化函数必要资源定义//用于初始化函数当中//device number; dev_t dev_num;//struct dev struct cdev ds18b20_cdev;//auto "mknode /dev/ds18b20 c dev_num minor_num"struct class *ds18b20_class = NULL;struct device *ds18b20_device = NULL;/******************** ds18b20有关的函数 ****************************///复位ds18b20传感器static unsigned char ds18b20_reset(void){ unsigned char ret = 0; unsigned char count = 0; DS18B20_OUT; DS18B20_H; udelay(100); DS18B20_L; udelay(600); DS18B20_H; udelay(45); DS18B20_IN; do { ret = DS18B20_STA; udelay(1); count++; } while(ret != 0 && count<50); DS18B20_OUT; udelay(400); DS18B20_H; return ret;}//从ds18b20读取一个字节static unsigned char read_byte(void){ unsigned char i,byte=0; DS18B20_OUT; DS18B20_H; udelay(100); for(i = 0; i<8; i++) { byte >>= 1; DS18B20_L; udelay(4); DS18B20_H; udelay(2); if(DS18B20_STA == 1) byte |= 0x80; udelay(10); } return byte;}//向ds18b20写入一个字节static unsigned char write_byte(unsigned char byte){ unsigned char i; DS18B20_OUT; DS18B20_H; udelay(100); for(i = 0; i<8; i++) { DS18B20_L; if( byte & 0x01 ) DS18B20_H; else DS18B20_L; udelay(40); DS18B20_H; byte >>= 1; } udelay(10);}//从ds18b20中读出温度数据static unsigned int read_temp(void){ unsigned int t = 0 , l = 0; if(ds18b20_reset()) { printk("step1,reset_ds18b20 error!\n"); return 0; } write_byte(0xcc); write_byte(0x44); udelay(4); if(ds18b20_reset()) { printk("step2,reset_ds18b20 error!\n"); return 0; } write_byte(0xcc); write_byte(0xbe); l = read_byte(); t = read_byte(); t <<= 8; t += l; return t;}/**********************************************************************//**************** 结构体 file_operations 成员函数 *****************///openstatic int ds18b20_open(struct inode *inode, struct file *file){ printk("ds18b20 drive open...\n"); DS18B20_OUT; //初始化该引脚为输出; return 0;}//closestatic int ds18b20_close(struct inode *inode , struct file *file){ return 0;}//readstatic ssize_t ds18b20_read(struct file *file, char __user *buffer, size_t len, loff_t *pos){ unsigned int temp; printk("ds18b20 drive read...\n"); temp = read_temp(); copy_to_user(buffer, &temp, 4); return 4;}/***************** 结构体: file_operations ************************///structstatic const struct file_operations ds18b20_fops = { .owner = THIS_MODULE, .open = ds18b20_open, .release = ds18b20_close, .read = ds18b20_read,};/************* functions: init , exit*******************///条件值变量,用于指示资源是否正常使用unsigned char init_flag = 0;unsigned char add_code_flag = 0;//initstatic __init int ds18b20_init(void){ int ret_v = 0; printk("ds18b20 drive init...\n"); //函数alloc_chrdev_region主要参数说明: //参数2: 次设备号 //参数3: 创建多少个设备 if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"ds18b20") ) < 0 ) { goto dev_reg_error; } init_flag = 1; //标示设备创建成功; printk("The drive info of ds18b20:\nmajor: %d\nminor: %d\n", MAJOR(dev_num),MINOR(dev_num)); cdev_init(&ds18b20_cdev,&ds18b20_fops); if( (ret_v = cdev_add(&ds18b20_cdev,dev_num,1)) != 0 ) { goto cdev_add_error; } ds18b20_class = class_create(THIS_MODULE,"ds18b20"); if( IS_ERR(ds18b20_class) ) { goto class_c_error; } ds18b20_device = device_create(ds18b20_class,NULL,dev_num,NULL,"ds18b20"); if( IS_ERR(ds18b20_device) ) { goto device_c_error; } printk("auto mknod success!\n"); //------------ 请在此添加您的初始化程序 --------------// GPIO21_0_DATA = (volatile unsigned long *)ioremap(0x10000620, 4); GPIO21_0_DIR = (volatile unsigned long *)ioremap(0x10000624, 4); //如果需要做错误处理,请:goto ds18b20_error; add_code_flag = 1; //---------------------- END ---------------------------// goto init_success;dev_reg_error: printk("alloc_chrdev_region failed\n"); return ret_v;cdev_add_error: printk("cdev_add failed\n"); unregister_chrdev_region(dev_num, 1); init_flag = 0; return ret_v;class_c_error: printk("class_create failed\n"); cdev_del(&ds18b20_cdev); unregister_chrdev_region(dev_num, 1); init_flag = 0; return PTR_ERR(ds18b20_class);device_c_error: printk("device_create failed\n"); cdev_del(&ds18b20_cdev); unregister_chrdev_region(dev_num, 1); class_destroy(ds18b20_class); init_flag = 0; return PTR_ERR(ds18b20_device);//------------------ 请在此添加您的错误处理内容 ----------------//ds18b20_error: add_code_flag = 0; return -1;//-------------------- END -------------------//init_success: printk("ds18b20 init success!\n"); return 0;}//exitstatic __exit void ds18b20_exit(void){ printk("ds18b20 drive exit...\n"); if(add_code_flag == 1) { //---------- 请在这里释放您的程序占有的资源 ---------// printk("free your resources...\n"); iounmap(GPIO21_0_DATA); iounmap(GPIO21_0_DIR); printk("free finish\n"); //---------------------- END -------------------// } if(init_flag == 1) { //释放初始化使用到的资源; cdev_del(&ds18b20_cdev); unregister_chrdev_region(dev_num, 1); device_unregister(ds18b20_device); class_destroy(ds18b20_class); }}/**************** module operations**********************///module loadingmodule_init(ds18b20_init);module_exit(ds18b20_exit);//some infomationMODULE_LICENSE("GPL v2");MODULE_AUTHOR("from Jafy");MODULE_DESCRIPTION("ds18b20 drive");27.5应用程序int main(int argc, char **argv){ int fd; float t; unsigned int tmp = 0; //打开温度传感器驱动模块 fd = open("/dev/ds18b20", O_RDWR | O_NONBLOCK); if (fd < 0) { printf("can't open!\n"); return -1; } read(fd, &tmp, sizeof(tmp)); t = tmp * 0.0625; printf("the current temperature is %f\n",t); close(fd); return 0;}
编译模块驱动,不熟悉的朋友可看LED驱动相关。
make package/kernel/ds18b20/compile V=99
编译模块驱动和应用程序
make package/ds18b20_app/compile V=99make package/ds18b20_app/install V=99make package/index V=99
复制文件传给开发板测试
ald@ald888:/work/openwrt/trunk/bin/ramips/packages/base$ cpkmod-ds18b20_3.14.25-1_ramips_24kec.ipk /mnt/hgfs/share/ald@ald888:/work/openwrt/trunk/bin/ramips/packages/base$ cpds18b20_app_1_ramips_24kec.ipk /mnt/hgfs/share/
27.6实验结果
本章附件
点击进入下载
- 第27章 DS18B20温度传感器
- ds18b20温度传感器
- DS18B20温度传感器
- ds18b20温度传感器
- 温度传感器 DS18B20
- DS18B20数字温度传感器介绍
- linux ds18b20 温度传感器驱动
- DS18B20温度传感器示例
- ds18b20温度传感器应用实例
- 温度传感器DS18B20 ISIS仿真
- 16.4 温度传感器DS18B20
- DS18B20温度传感器 - arduino
- 温度传感器--DS18B20的使用
- 温度传感器(DS18B20)程序
- ds18b20温度传感器主程序
- 温度传感器DS18B20介绍
- STC89C52MCU -- DS18B20温度传感器
- stm32 ds18b20 温度传感器
- 智力大冲浪
- 失去手臂五年后,这个仿生机械臂帮他重拾钢琴曲演奏
- springmvc--数据转换器
- QEMU-KVM 介绍1 使用与安装
- 思考: 现有图像算法的缺陷
- 第27章 DS18B20温度传感器
- python中的星号'*'和双星号'**'
- Mybatis_全局配置文件
- AutoCAD .Net 创建对齐标注
- Oracle中char和varchar2的区别
- 【双目视觉探索路4】分析整理Learning OpenCV3书中立体标定、校正以及对应代码(2)之部分验证
- 2017.12.16江苏开璇智能科技有限公司
- 51nod 1245 Binomial Coefficients Revenge kummer定理+数位dp
- 波动序列