2023-11-14 02:16 AM
Hi. I'm using STM32F030C8T6 MCU to communicate with multiple DS18B20. I'm using Timers to make 1us delay. I set my prescaler to 48-1. and I'm running on 48MHz clock. when i connect two sensors to my MCU, i can't read temperature, so for testing i disconnected one of the sensors and connect only one sensor to MCU. when i run skip command and convert temperature and read scratchpad its ok. so i decided to instead of ROM skip command use ROM match command to see what happened. when i use Search command thee output is always 255 or 0xff. i think timing is correct because 0xCC and 0xBE and reading data is ok. here is the code:
void delay (ds18Config* _ds18b20, uint16_t time)
{
/* change your code here for the delay in microseconds */
//test = HAL_GetTick();
__HAL_TIM_SET_COUNTER(_ds18b20->hTIMx, 0);
while ((__HAL_TIM_GET_COUNTER(_ds18b20->hTIMx))<time);
}
void DS18B20_Write_Command (ds18Config* _ds18b20, uint8_t data)
{
uint8_t bitMask;
Set_Pin_Output(_ds18b20->sensorPort, _ds18b20->sensorPin); // set as output
for (bitMask = 0x01; bitMask; bitMask <<= 1){
if ((data & bitMask)!=0){
Set_Pin_Output(_ds18b20->sensorPort, _ds18b20->sensorPin); // set as output
HAL_GPIO_WritePin (_ds18b20->sensorPort, _ds18b20->sensorPin, 0); // pull the pin LOW
delay (_ds18b20, 10); // wait for 1 us
Set_Pin_Input(_ds18b20->sensorPort, _ds18b20->sensorPin); // set as input
delay (_ds18b20, 55); // wait for 60 us
}else{
Set_Pin_Output(_ds18b20->sensorPort, _ds18b20->sensorPin);
HAL_GPIO_WritePin (_ds18b20->sensorPort, _ds18b20->sensorPin, 0); // pull the pin LOW
delay (_ds18b20, 65); // wait for 60 us
Set_Pin_Input(_ds18b20->sensorPort, _ds18b20->sensorPin);
delay (_ds18b20, 5);
}
}
}
uint8_t DS18B20_Read (ds18Config* _ds18b20)
{
uint8_t value=0;
Set_Pin_Input(_ds18b20->sensorPort, _ds18b20->sensorPin);
for (int i=0;i<8;i++){
Set_Pin_Output(_ds18b20->sensorPort, _ds18b20->sensorPin); // set as output
HAL_GPIO_WritePin (_ds18b20->sensorPort, _ds18b20->sensorPin, 0); // pull the data pin LOW
delay (_ds18b20, 3); // wait for > 1us
Set_Pin_Input(_ds18b20->sensorPort, _ds18b20->sensorPin); // set as input
if (HAL_GPIO_ReadPin (_ds18b20->sensorPort, _ds18b20->sensorPin)){
value |= 1<<i; // read = 1
}
delay (_ds18b20, 53); // wait for 60 us
}
return value;
}
void DS18B20_getTemperature(ds18Config *_ds18b20, ds18Data *_sensors) {
uint8_t Temp_byte1, Temp_byte2;
uint16_t TEMP;
uint8_t data[1];
uint8_t address0[8] = {0x28, 0xFF, 0x64, 0x1E, 0x85, 0xF5, 0xFD, 0xD3};
DS18B20_Start(_ds18b20);
HAL_Delay (1);
DS18B20_Write_Command (_ds18b20, 0xcc); // skip ROM
DS18B20_Write_Command (_ds18b20, 0x44); // convert t
HAL_Delay (800);
DS18B20_Start(_ds18b20);
HAL_Delay (1);
DS18B20_Write_Command (_ds18b20, 0x55);
for (int i = 0; i <8; i++){
DS18B20_Write_Command (_ds18b20, address0[i]);
}
DS18B20_Write_Command (_ds18b20, 0xBE);
Temp_byte1 = DS18B20_Read(_ds18b20);
Temp_byte2 = DS18B20_Read(_ds18b20);
TEMP = (Temp_byte2<<8)|Temp_byte1;
data[0] = (int)TEMP/16;
}
2023-11-14 03:54 AM - edited 2023-11-14 10:14 AM
None of the delays match the comments.
These types of delay are prone to change if interrupts occur.
For better resolution at a micro second level I'd probably use a zero prescaler, and multiple the time value by 48 in the subroutine.
Use a scope or logic analyzer to review the signals and responses from the sensor
2023-11-14 10:17 AM
The delay also isn't thread safe. Perhaps you could just free-run the TIM instead of zeroing every time? ie measure the elapsed time.
Not clear how you separate access to the multiple DS18B20, or how many of them you are using. I see the use of different pins, but how do you separate access in the time domain?
Are these functions used in interrupt context? ie IRQ Handler, or call-backs