/****************************************************************************
|
* Copyright: (C)2021 武汉凌云物网智科实验室 www.iot-yun.com
|
* Author: GuoWenxue<guowenxue@gmail.com> QQ: 281143292
|
* Description: 凌云IoT Starter IoT Kits开发板 温度传感器DS18B20采样API函数。
|
*
|
* SHT20温度传感器使用GPIO模拟I2C总线I2C0
|
*
|
* ChangeLog:
|
* 版本号 日期 作者 说明
|
* V1.0.0 2021.06.18 GuoWenxue 发布该版本
|
****************************************************************************/
|
|
#include <stdio.h>
|
#include "stm32f1xx_hal.h"
|
#include "tim.h"
|
|
#define W1DQ_Set_Input() \
|
{ \
|
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
|
GPIO_InitStruct.Pin = W1Dat_Pin; \
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
|
GPIO_InitStruct.Pull = GPIO_PULLUP; \
|
HAL_GPIO_Init(W1Dat_GPIO_Port, &GPIO_InitStruct); \
|
}
|
|
#define W1DQ_Set_Output() \
|
{ \
|
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
|
GPIO_InitStruct.Pin = W1Dat_Pin; \
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
|
GPIO_InitStruct.Pull = GPIO_PULLUP; \
|
HAL_GPIO_Init(W1Dat_GPIO_Port, &GPIO_InitStruct); \
|
}
|
|
#define HIGH 1
|
#define LOW 0
|
|
#define W1DQ_WritePin(N) HAL_GPIO_WritePin(W1Dat_GPIO_Port, W1Dat_Pin, N!=0?GPIO_PIN_SET:GPIO_PIN_RESET)
|
#define W1DQ_ReadPin() HAL_GPIO_ReadPin(W1Dat_GPIO_Port, W1Dat_Pin)
|
|
/* Description: reset DS18B20 and wait for respond signal
|
* Return Value: 0: OK -1: No respond signal -2: No reset end signal
|
*/
|
int ds18b20_init(void)
|
{
|
uint8_t retry=0;
|
int rv = 0;
|
|
/* 1-Wire Data Pin set as output mode */
|
W1DQ_Set_Output();
|
|
/* Master send a reset signal of 480~960 µs */
|
W1DQ_WritePin(LOW);
|
delay_us(750);
|
W1DQ_WritePin(HIGH);
|
|
/* When the DS18B20 detects this rising edge, it waits 15~60µs */
|
delay_us(15);
|
|
/* Master then releases the bus and goes into receive mode. When the
|
* bus is released, the 5kΩ pullup resistor pulls the 1-Wire bus high. */
|
W1DQ_Set_Input();
|
|
/* Then DS18B20 will transmits a presence pulse by pulling the 1-Wire bus low for 60~240µs. */
|
while ( W1DQ_ReadPin() && retry<240 )
|
{
|
retry++;
|
delay_us(1);
|
}
|
|
if(retry>=240)
|
{
|
rv = -1;
|
goto OUT;
|
}
|
|
/* Then DS18B20 release bus and resistor will pull-up the bus high for 60~240µs. */
|
retry=0;
|
while ( !W1DQ_ReadPin() && retry<240 )
|
{
|
retry++;
|
delay_us(1);
|
}
|
|
if(retry>=240)
|
{
|
rv = -2;
|
goto OUT;
|
}
|
|
OUT:
|
if( rv )
|
{
|
printf("ERROR: DS18B20 check respond signal failure, rv=%d\r\n", rv);
|
}
|
return rv;
|
}
|
|
|
|
/* Description: Write a byte data to DS18B20 */
|
void w1bus_write_byte(uint8_t byte)
|
{
|
uint8_t i;
|
uint8_t testb;
|
|
/* 1-Wire Data Pin set as output mode */
|
W1DQ_Set_Output();
|
|
for(i=1; i<=8; i++)
|
{
|
testb=byte&0x01; //取最低位
|
byte=byte>>1;
|
|
if (testb)
|
{
|
/* write bit 1: */
|
W1DQ_WritePin(LOW);
|
delay_us(2);
|
|
W1DQ_WritePin(HIGH);
|
delay_us(60);
|
}
|
else
|
{
|
/* write bit 0 */
|
W1DQ_WritePin(LOW);
|
delay_us(60);
|
|
W1DQ_WritePin(HIGH);
|
delay_us(2);
|
}
|
}
|
}
|
|
/* Description: Read a bit from DS18B20 */
|
uint8_t w1bus_read_bit(void)
|
{
|
uint8_t bit;
|
|
/* 1-Wire Data Pin set as output mode */
|
W1DQ_Set_Output();
|
|
/*Generate read time slot*/
|
W1DQ_WritePin(LOW);
|
delay_us(2);
|
//W1DQ_WritePin(HIGH);
|
|
/*Master must read data from slave in 15us*/
|
W1DQ_Set_Input();
|
delay_us(8);
|
bit = W1DQ_ReadPin() ? 1 : 0;
|
|
delay_us(50);
|
|
return bit;
|
}
|
|
/* 从DS18B20读取一个字节 */
|
uint8_t w1bus_read_byte(void)
|
{
|
uint8_t i,j,byte;
|
|
byte=0;
|
for(i=1; i<=8; i++)
|
{
|
j=w1bus_read_bit();
|
byte=(j<<7)|(byte>>1);
|
}
|
|
return byte;
|
}
|
|
|
int ds18b20_start_convert(void)
|
{
|
int rv = 0;
|
|
if( 0 != (rv=ds18b20_init()) )
|
return rv;
|
|
w1bus_write_byte(0xCC); // Master issues Skip ROM command.
|
w1bus_write_byte(0x44); // Master issues Convert T command.
|
|
return 0;
|
}
|
|
|
int ds18b20_start_readreg(void)
|
{
|
int rv = 0;
|
|
if( 0 != (rv=ds18b20_init()) )
|
return rv;
|
|
w1bus_write_byte(0xCC); // Master issues Skip ROM command.
|
w1bus_write_byte(0xBE); // Master issues Read Scratchpad command.
|
|
return 0;
|
}
|
|
int ds18b20_get_temperature(float *temperature)
|
{
|
uint8_t sign;
|
uint8_t TL,TH;
|
uint16_t tmp;
|
int rv;
|
float temp;
|
|
|
if( 0 != (rv=ds18b20_start_convert()) )
|
return rv;
|
|
if( 0 != (rv=ds18b20_start_readreg()) )
|
return rv;
|
|
TL=w1bus_read_byte(); // LSB
|
TH=w1bus_read_byte(); // MSB
|
|
printf("DS18B20 Read TH[0x%02x] TH[0x%02x]\r\n", TH, TL);
|
|
if(TH>7) /* 高5位为1,说明温度为负 */
|
{
|
tmp = ~(TH<<8|TL) + 1; //补码
|
sign=0;//温度为负
|
}
|
else
|
{
|
sign=1;//温度为正
|
tmp = TH<<8 | TL;
|
}
|
|
/*12位精度转换时,TH的低三位和TL的高四位组成温度值的整数部分, 而TL的低四位为小数精度部分,并且精度系数为0.0625 */
|
temp = (tmp>>4) + (tmp&0xF)*0.0625 ;
|
|
*temperature = sign ? temp : -temp;
|
|
return 0;
|
}
|