赞
踩
目录
DS18B20是一款单总线(one wire)芯片,因此其DQ引脚与单片机相连的IO口既要是输入也要是输出,cubeMX的初始化引脚设置只能选择其一,这里我们使用手动配置引脚。
先用cubeMX生成一个工程模板,初始化时钟等等。
这里有两个重要的指令,0x44表示触发芯片进行温度转化,0xbe表示请求读取温度转化后的值。
还有一个常用指令为0xCC,意义是跳过读取芯片ROM而节约时间。
由于是单总线协议,要想写指令,收数据都要遵循其标准,下面查看其时序
单片机将DQ线拉低480us至960us后释放总线,ds18b20检测到总线电平变化,会等待15-60us,这段时间总线电平被电阻拉高,然后ds18b20会将总线拉低60-240us,作为应答信号,表明总线上存在ds18b20芯片。然后ds18b20释放总线,电阻将总线拉高。
整个过程为初始化
代码如下
- void onewire_init()
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pin=GPIO_PIN_9;
- GPIO_InitStruct.Pull=GPIO_NOPULL;
- GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
-
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(500);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
- HAL_Delay_us(50);
-
- onewire_release();
- HAL_Delay_us(500);
- }
用逻辑分析仪检测如下
实际应答时间约为110us
写时序分为写0时序和写1时序.
写0时序
单片机拉低总线,产生一个下降沿并保持总线低电平60us-120us,在这期间,18b20会在下降沿出现后大约15us-60us内读取总线电平。然后单片机释放总线,由上拉电阻拉高,直至下一次写时序,这段时间为恢复时间,需要大于1us
写1时序
单片机拉低总线,产生一个下降沿并保持总线低电平1-15us,在这期间,18b20会在下降沿出现后大约15us-60us内读取总线电平。然后单片机释放总线,由上拉电阻拉高,直至下一次写时序,这段时间为恢复时间,需要大于1us
- void onewire_write(uint8_t dat)
- {
- onewire_hold();
- if(dat==0)
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(60);
- onewire_release();
- HAL_Delay_us(2);
- }
- else
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(2);
- onewire_release();
- HAL_Delay_us(60);
- }
- }
读时序分为读0时序和读1时序
读0时序
单片机拉低总线并至少保持1us的总线低电平,然后释放总线,此时总线电平将由18b20决定,单片机在下降沿后15us处读取总线电平值,为低电平
读1时序
单片机拉低总线并至少保持1us的总线低电平,然后释放总线,此时总线电平将由18b20决定,单片机在下降沿后15us处读取总线电平值,为高电平
- uint8_t onewire_read()
- {
- uint8_t t;
- onewire_hold();
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(2);
- onewire_release();
- HAL_Delay_us(12);
- t=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9);
- HAL_Delay_us(50);
- return t;
- }
- float ds18b20_getTemp()
- {
- uint16_t temp;
- float value;
- uint8_t lsb,msb;
- onewire_init();
- onewire_sendbyte(0xcc);
- onewire_sendbyte(0x44);
- HAL_Delay(750);
- onewire_init();
- onewire_sendbyte(0xcc);
- onewire_sendbyte(0xbe);
- lsb=onewire_readbyte();
- msb=onewire_readbyte();
- temp=msb;
- temp=(temp<<8)+lsb;
- if((temp&0xf800)==0xf800)
- {
- temp=(~temp)+1;
- value=temp*(-0.0625);
- }
- else
- {
- value=temp*0.0625;
- }
- return value;
- }
逻辑分析仪波形
上图为开启温度转化的引脚逻辑电平变化
上图为读取温度值
读取到的值为0000 0001 1011 1110
由图可知为16*1+8*1+2*1+1*1+0.5+0.25+0.125=27.875°C
与串口显示温度值一致
至此,ds18b20的温度转化,温度读取已经完成
onewire.c
- #include "onewire.h"
-
- void HAL_Delay_us(uint32_t nus)
- {
- uint32_t ticks;
- uint32_t told,tnow,tcnt=0;
- uint32_t reload=SysTick->LOAD;
- ticks=nus*72;
- told=SysTick->VAL;
- while(1)
- {
- tnow=SysTick->VAL;
- if(tnow!=told)
- {
- if(tnow<told)tcnt+=told-tnow;
- else tcnt+=reload-tnow+told;
- told=tnow;
- if(tcnt>=ticks)break;
- }
- }
- }
- void onewire_release()
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull=GPIO_NOPULL;
- GPIO_InitStruct.Pin=GPIO_PIN_9;
- GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
- }
- void onewire_hold()
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pin=GPIO_PIN_9;
- GPIO_InitStruct.Pull=GPIO_PULLUP;
- GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
- }
- void onewire_init()
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pin=GPIO_PIN_9;
- GPIO_InitStruct.Pull=GPIO_NOPULL;
- GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
-
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(500);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
- HAL_Delay_us(50);
-
- onewire_release();
- HAL_Delay_us(500);
- }
-
- void onewire_write(uint8_t dat)
- {
- onewire_hold();
- if(dat==0)
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(60);
- onewire_release();
- HAL_Delay_us(2);
- }
- else
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(2);
- onewire_release();
- HAL_Delay_us(60);
- }
- }
-
- uint8_t onewire_read()
- {
- uint8_t t;
- onewire_hold();
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
- HAL_Delay_us(2);
- onewire_release();
- HAL_Delay_us(12);
- t=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9);
- HAL_Delay_us(50);
- return t;
- }
-
- void onewire_sendbyte(uint8_t dat)
- {
- uint8_t i;
- for(i=0;i<8;i++)
- {
- if((dat&0x01)==1)
- onewire_write(1);
- else
- onewire_write(0);
- dat=dat>>1;
- }
- }
- uint8_t onewire_readbyte(void) // read one byte
- {
- uint8_t i,j,dat;
- dat=0;
- for (i=1;i<=8;i++)
- {
- j=onewire_read();
- dat=(j<<7)|(dat>>1);
- }
- return dat;
- }
onewire.h
- #ifndef ONEWIRE_H
- #define ONEWIRE_H
- #include "main.h"
- void onewire_init();
- void onewire_write(uint8_t dat);
- uint8_t onewire_read();
- uint8_t onewire_readbyte(void);
- void onewire_sendbyte(uint8_t dat);
- #endif
ds18b20.c
- #include "ds18b20.h"
- #include "onewire.h"
- void ds18b20_init()
- {
- onewire_init();
- }
- float ds18b20_getTemp()
- {
- uint16_t temp;
- float value;
- uint8_t lsb,msb;
- onewire_init();
- onewire_sendbyte(0xcc);
- onewire_sendbyte(0x44);
- HAL_Delay(750);
- onewire_init();
- onewire_sendbyte(0xcc);
- onewire_sendbyte(0xbe);
- lsb=onewire_readbyte();
- msb=onewire_readbyte();
- temp=msb;
- temp=(temp<<8)+lsb;
- if((temp&0xf800)==0xf800)
- {
- temp=(~temp)+1;
- value=temp*(-0.0625);
- }
- else
- {
- value=temp*0.0625;
- }
- return value;
-
- }
ds18b20.h
- #ifndef DS18B20_H
- #define DS18B20_H
- #include "main.h"
-
- void ds18b20_init();
- float ds18b20_getTemp();
- #endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。