I am using STM32 to read the DS18B20 with the HAL library.
I think the initialisation is correct, but the read and write is not.
Why is it not right?
For the write, here is the code
if ((data & (1 << i)) != 0)
{
MX_GPIO_Set(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
delay_ms(1);
MX_GPIO_Set(0);
delay_ms(60);
}
else
{
MX_GPIO_Set(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
delay_ms(60);
MX_GPIO_Set(0);
}
It is writing one bit data.
And for the read code
MX_GPIO_Set(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
delay_ms(2);
MX_GPIO_Set(0);
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET)
{
value |= 1 << i;
}
delay_ms(60);
The MX_GPIO_Set(1) means set the GPIO output.
Where is it wrong?
Please do not tell me use a library or code on GitHub. I want to write code myself, so I can understand the DS18B20.
The DS18B20 uses the 1-Wire protocol.
Each bit takes about 60 microseconds to transmit. 1s are HIGH during most of the transmission and 0s are LOW during most of the transmission. The start of the next bit is indicated by a pulse.
One thing that stands out to me is that you're using delay_ms
(milliseconds), when you likely want to be using delay_us
(microseconds).
Also, you're relying on the bit's timing to be exact (which it probably won't be). Instead, base your timing on the pulse.
It's more complicated than that. When reading, you need to be continually checking the pin's value and interpreting what it means rather than putting in delays and hoping that the timing matches up.
I have not tested this code and it's incomplete. This is just to illustrate a technique.
To start off, we're going to set our output to LOW and wait for the sensor to go LOW for at least 200 µs. (Ideally 500 µs. 200 µs is our minimum requirement.) This is the "RESET" sequence that tells us that new data is about to start.
const int SleepIntervalMircoseconds = 5;
// Start off by setting our output to LOW (aka GPIO_PIN_RESET).
MX_GPIO_Set(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
// Switch back to reading mode.
MX_GPIO_Set(0);
const int ResetRequiredMiroseconds = 200;
int pinState = GPIO_PIN_SET;
int resetElapsedMicroseconds = 0;
while (pinState != GPIO_PIN_RESET || resetElapsedMicroseconds < ResetRequiredMiroseconds) {
pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
if (pinState != GPIO_PIN_RESET) {
resetElapsedMicroseconds = 0;
continue;
}
delay_us(SleepIntervalMircoseconds);
// Note that the elapsed microseconds is really an estimate here.
// The actual elapsed time will be 5 µs + the amount
// of time it took to execute the code.
resetElapsedMicroseconds += SleepIntervalMircoseconds;
}
This only gets us started. After you've received the reset signal, you need to indicate to the other side that you've received it by setting your value HIGH for certain amount of time.