/**************************************************************************** * Copyright: (C)2021 武汉凌云物网智科实验室 www.iot-yun.com * Author: GuoWenxue QQ: 281143292 * Description: 凌云IoT Starter IoT Kits开发板 温度传感器DS18B20采样API函数。 * * SHT20温度传感器使用GPIO模拟I2C总线I2C0 * * ChangeLog: * 版本号 日期 作者 说明 * V1.0.0 2021.06.18 GuoWenxue 发布该版本 ****************************************************************************/ #include #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; }