完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
一、前言
继上次发布的光照传感器讲解,这次继续讲一些简单的适合大学生学习使用的传感器。这次要讲的是一款温度传感器,想要完整代码工程的,可以在文章末尾的链接下载。 二、芯片介绍 1、简介 DS18B20是一款数字型温度传感器,这款传感器已经有长的历史了,驱动方式简单,很适合初学者使用,具体的我就不多说了,很多人应该都是知道这个传感器的。 2、引脚定义 [tr]引脚名称说明[/tr]
DS18B20用的是单总线方式,单片机给DQ引脚输出一定规则的时序信号即可配置和驱动DS18B20,同样的,单片机按照时序接收DS18B20发送的数据即可得到温度数据。 4、工作原理 DS18B20通过传感电路把温度转换成对应的电压信息,然后转换成数字信号,再把温度相关的数据存到自身的寄存器里面,单片机去读取这些数据,就可以知道当前的温度了。简单的说就是把模拟信号转换成数字信号,然后把这些数据存起来交给单片机,大概的原理是这样,如果你想继续深入了解,可以去找一下相关的文章,关于这方面的介绍有很多。 三、编程讲解 1、DS18B20驱动程序 //单片机只需要用一个普通的IO口和DS18B20的DQ引脚相连,然后控制这个IO口输出高低电平即可 //复位DS18B20 //作用:复位 void DS18B20_Rst(void) { DS18B20_IO_OUT(); //把单片机的IO口配置为输出 DS18B20_DQ_OUT=0; //拉低DQ delay_us(750); //拉低750us,这个时间是根据DS18B20本身的规则定的,可以在数据手册找到相关介绍 DS18B20_DQ_OUT=1; //拉高DQ delay_us(15); //15US } //等待DS18B20的回应 //作用:检查单片机和DS18B20的通讯是否正常 //返回1:未检测到DS18B20的存在(可能是DQ引脚没有上拉电阻,通讯的时序不对,芯片损坏等原因) //返回0:存在 u8 DS18B20_Check(void) { u8 retry=0; DS18B20_IO_IN();//把IO口配置为输入,目的是为了接收DS18B20发过来的数据 while (DS18B20_DQ_IN&&retry<200)//如果IO口是低电平,则是正常的,否则一直进while循环 { retry++; delay_us(1); }; if(retry>=200) {//通讯有误,返回1 return 1; } else {//正常 retry=0; } while (!DS18B20_DQ_IN&&retry<240)//继续读取电平,如果IO口是高电平,则是正常的 { retry++; delay_us(1); }; if(retry>=240) {//通讯有误,返回1 return 1; } return 0;//通讯正常,返回0 } //从DS18B20读取一个位 //作用:读取一个位数据,重复调用该函数可以把温湿度数据读出来 //返回值:1/0 u8 DS18B20_Read_Bit(void) // read one bit { u8 data; DS18B20_IO_OUT();//单片机输出一个由低到高的上升沿脉冲给DS18B20 DS18B20_DQ_OUT=0; delay_us(2); DS18B20_DQ_OUT=1; DS18B20_IO_IN();//把IO口配置为输入,读取电平 delay_us(12); if(DS18B20_DQ_IN)//如果是高电平,则DS18B20输出的数据是'1',否则为'0' data=1; else data=0; delay_us(50); return data; } //从DS18B20读取一个字节 //作用:连续读8个位,并合成一个字节数据 //返回值:读到的数据 u8 DS18B20_Read_Byte(void) // read one byte { u8 i,j,dat; dat=0; for (i=1;i<=8;i++) { j=DS18B20_Read_Bit();//连续调用8次 dat=(j<<7)|(dat>>1);//每次读取到1个位的数据后左移1位,读取完8个位的数据之后就可以合成1个字节了 } return dat;//返回合成的1字节数据 } //写一个字节到DS18B20 //作用:写数据到DS18B20,调用这个函数可以发送指令控制DS18B20 //dat:要写入的字节 void DS18B20_Write_Byte(u8 dat) { u8 j; u8 testb; DS18B20_IO_OUT();//SET PA0 OUTPUT; for (j=1;j<=8;j++) { testb=dat&0x01;//把传进来的这个数据的最高位提取出来 dat=dat>>1;//dat的数据左移1位,作用是把次高位移到最高位 if (testb) //如果最高位数据为'1' { DS18B20_DQ_OUT=0;// Write 1 delay_us(2); DS18B20_DQ_OUT=1;//输出60us高电平,相当于告诉DS18B20要传的数据是'1' delay_us(60); } else //如果最高位数据为'0' { DS18B20_DQ_OUT=0;//输出60us低电平,相当于告诉DS18B20要传的数据是'0' delay_us(60); DS18B20_DQ_OUT=1; delay_us(2); } } } //开始温度转换 //作用:从DS18B20中读取温度数据 void DS18B20_Start(void)// ds1820 start convert { DS18B20_Rst();//复位 DS18B20_Check();//检查单片机和DS18B20的通讯是否正常 DS18B20_Write_Byte(0xcc);//寻址总线上的所有从设备,详细说明可以参考数据手册ROM COMMANDS DS18B20_Write_Byte(0x44);//0x44命令为启动温度转换命令,详细说明可以参考数据手册ROM COMMANDS } //初始化DS18B20的IO口DQ 同时检测DS18B20的存在 //返回1:不存在 //返回0:存在 u8 DS18B20_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PORTA0 推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出1 DS18B20_Rst();//复位 return DS18B20_Check(); } //从ds18b20得到温度值 //精度:0.1C //返回值:温度值 (-550~1250) short DS18B20_Get_Temp(void) { u8 temp; u8 TL,TH; short tem; //DS18B20_Start (); //开始采集温度 DS18B20_Rst();//复位 DS18B20_Check();//检查单片机和DS18B20通讯是否正常 DS18B20_Write_Byte(0xcc);//寻址总线上的所有从设备,详细说明可以参考数据手册ROM COMMANDS DS18B20_Write_Byte(0xbe);//0x44命令为启动温度转换命令,详细说明可以参考数据手册ROM COMMANDS TL=DS18B20_Read_Byte(); //读取数据低字节 TH=DS18B20_Read_Byte(); //读取数据高字节 if(TH>7) { TH=~TH; TL=~TL; temp=0;//温度为负 } else { temp=1;//温度为正 } tem=TH;//获得高字节数据 tem<<=8;//高字节位左移8位 tem+=TL;//左移的高8位加上低8位合成一个16位数据 tem=(float)tem*0.625;//从DS18B20读取到的2个字节的数据还不是温度值,需要转换,转换公式参考数据手册 if(temp) { return tem; //返回温度值 } else { return -tem; } } 2、main函数 int main() { short temperature; uart_init(115200); //串口初始化为115200 LED_Init(); //初始化与LED连接的硬件接口 OLED_Init(); //OLED初始化 OLED_Clear(); //OLED清屏 while(DS18B20_Init()) //DS18B20初始化 { OLED_ShowString(50,2,"error",12);//DS18B20通讯有问题 } while(1) { //读取温度 temperature=DS18B20_Get_Temp(); if(temperature<0)//温度低于0 { OLED_ShowString(50,4,"-",16); //显示负号 temperature=-temperature; //转为正数 } else //温度大于0 { OLED_ShowString(50,4," ",16); //不显示负号,也不显示正号 } OLED_ShowCHinese(0,4,0);//显示中文字体“温” OLED_ShowCHinese(16,4,1);//显示中文字体“度” OLED_ShowString(32,4,":",16); OLED_ShowNum(60,4,temperature/10,2,16); //显示整数部分 OLED_ShowString(80,4,".",16); OLED_ShowNum(88,4,temperature%10,1,16); //显示小数部分 OLED_ShowCHinese(100,4,9);//显示“℃” } |
||
|
||
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 04:52 , Processed in 0.696598 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号