commit aa121b145f2ed4d312b927afcc02c14409203d8b
parent ebcaec6086118627e36090fb482b5c0546d7ed7f
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Mon, 23 Mar 2026 14:02:10 -0300
Mejorar lectura de datos de DS18B20
Usar funcion `HAL_UARTEx_ReceiveToIdle_DMA` en lugar de
`HAL_UART_Receive_DMA`, esto permite que el DMA detecte si la linea esta
en IDLE y de por termianda la tranmision evitando errores de lectura en
los cuales el DMA se queda esperando indefinidamente.
Diffstat:
2 files changed, 241 insertions(+), 99 deletions(-)
diff --git a/firmware/app/inc/ds18b20.h b/firmware/app/inc/ds18b20.h
@@ -49,6 +49,12 @@ extern "C" {
*
*/
+#define DS18B20_SKIP_ROM_CMD 0xCC
+#define DS18B20_CONVERT_T_CMD 0x44
+#define DS18B20_READ_SCRATCHPAD_CMD 0xBE
+#define DS18B20_WRITE_SCRATCHPAD_CMD 0x4E
+#define DS18B20_WRITE_SCRATCHPAD_TO_EEPROM_CMD 0x48
+
typedef enum {
ST_DS18B20_READY,
ST_DS18B20_BUSY_SENDING_RESET,
@@ -56,10 +62,12 @@ typedef enum {
ST_DS18B20_BUSY_SENDING_CONV_T,
ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD,
ST_DS18B20_BUSY_WAITING_CONV,
+ ST_DS18B20_BUSY_WAITING_LSB,
+ ST_DS18B20_BUSY_WAITING_MSB,
+ ST_DS18B20_BUSY_WAITING,
ST_DS18B20_BUSY_WAITING_DMA
} DS18B20_st_t;
-
void DS18B20_Init(void);
void DS18B20_Update(void);
diff --git a/firmware/app/src/ds18b20.c b/firmware/app/src/ds18b20.c
@@ -14,22 +14,25 @@
#include "task_menu_attribute.h"
#include "task_menu_interface.h"
-
-#define G_DS18B20_CONV_TIME_MS 100ul // ~188ms for 10 bit resolution
-#define G_DS18B20_DMA_TIMEOUT_MS 10ul
-#define G_TEMP_PERIOD_MS 1000ul
+#define G_DS18B20_CONV_TIME_MS 100ul // ~188ms for 10 bit resolution
+#define G_DS18B20_DMA_TIMEOUT_MS 200ul
+#define G_DS18B20_BYTE_READ_DELAY_MS 10ul
+#define G_TEMP_PERIOD_MS 1000ul
// Private global variables
volatile bool b_DS18B20_Received_data;
static uint8_t g_DS18B20_Received_data_buffer[8];
const uint8_t g_buffer[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-static bool b_DS18B20_Received_data_LSB;
DS18B20_st_t g_DS18B20_state, g_DS18B20_prev_state;
-uint32_t g_DS18B20_tick;
+uint32_t g_DS18B20_tick, g_DS18B20_tick_delay;
uint16_t g_DS18B20_temp;
uint8_t Temp_LSB, Temp_MSB;
+static uint8_t g_DS18B20_TX_buffer[8];
+bool b_DS18B20_DMA_TX_done = false;
+bool b_DS18B20_DMA_RX_done = false;
+
// Public global variables
uint16_t g_DS18B20_update_count;
uint16_t g_DS18B20_DMA_error_count;
@@ -62,6 +65,23 @@ uint8_t DS18B20_Reset(void)
return 0;
}
+const uint8_t g_DS18B20_Reset_data_tx = 0xF0;
+uint8_t g_DS18B20_Reset_data_rx = 0xF0;
+
+void DS18B20_Reset_DMA(void)
+{
+ g_DS18B20_prev_state = g_DS18B20_state;
+ g_DS18B20_state = ST_DS18B20_BUSY_SENDING_RESET;
+
+ __HAL_UART_DISABLE(&huart1);
+ LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 9600);
+ __HAL_UART_ENABLE(&huart1);
+
+ b_DS18B20_DMA_TX_done = b_DS18B20_DMA_RX_done = false;
+ HAL_UART_Receive_DMA(&huart1, &g_DS18B20_Reset_data_rx, 1);
+ HAL_UART_Transmit_DMA(&huart1, &g_DS18B20_Reset_data_tx, 1);
+}
+
void DS18B20_SetResolution(uint8_t resolution)
{
uint8_t config;
@@ -76,16 +96,16 @@ void DS18B20_SetResolution(uint8_t resolution)
}
DS18B20_Reset();
- DS18B20_Write(0xCC); // Send 'Skip ROM' command
- DS18B20_Write(0x4E); // Send 'write scratchpad' command
+ DS18B20_Write(DS18B20_SKIP_ROM_CMD);
+ DS18B20_Write(DS18B20_WRITE_SCRATCHPAD_CMD);
DS18B20_Write(0x00); // TH
DS18B20_Write(0x00); // TL
DS18B20_Write(config);
DS18B20_Reset();
- DS18B20_Write(0xCC); // Skip ROM
- DS18B20_Write(0x48); // Write scratchpad to EEPROM
+ DS18B20_Write(DS18B20_SKIP_ROM_CMD);
+ DS18B20_Write(DS18B20_WRITE_SCRATCHPAD_TO_EEPROM_CMD);
}
void DS18B20_Init(void)
@@ -96,7 +116,7 @@ void DS18B20_Init(void)
}
DS18B20_SetResolution(9);
g_DS18B20_state = g_DS18B20_prev_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ g_DS18B20_tick = g_DS18B20_tick_delay = G_TEMP_PERIOD_MS;
g_DS18B20_update_count = 0;
g_DS18B20_DMA_error_count = 0;
@@ -124,9 +144,6 @@ void DS18B20_Write(uint8_t data)
HAL_UART_Transmit(&huart1, buffer, 8, 100);
}
-uint8_t g_DS18B20_TX_buffer[8];
-bool b_DS18B20_DMA_done = false;
-
void DS18B20_Write_DMA(uint8_t data)
{
for (uint8_t i = 0; i < 8; ++i)
@@ -141,10 +158,29 @@ void DS18B20_Write_DMA(uint8_t data)
}
}
- b_DS18B20_DMA_done = false;
+ b_DS18B20_DMA_TX_done = false;
+
+ // HAL_StatusTypeDef st = HAL_UART_Transmit_DMA(&huart1, g_DS18B20_TX_buffer, 8);
+ // LOGGER_INFO("%d", st);
+
HAL_UART_Transmit_DMA(&huart1, g_DS18B20_TX_buffer, 8);
}
+void DS18B20_Read_DMA(void)
+{
+ HAL_UART_DMAStop(&huart1);
+ __HAL_UART_DISABLE(&huart1);
+ __HAL_UART_CLEAR_PEFLAG(&huart1);
+ __HAL_UART_CLEAR_FEFLAG(&huart1);
+ __HAL_UART_CLEAR_NEFLAG(&huart1);
+ __HAL_UART_CLEAR_OREFLAG(&huart1);
+ __HAL_UART_ENABLE(&huart1);
+ memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
+
+ b_DS18B20_DMA_RX_done = false;
+ // HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+ HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+}
void DS18B20_Start_conv(void)
{
@@ -164,41 +200,48 @@ void DS18B20_Update(void)
case ST_DS18B20_READY:
if (0 == g_DS18B20_tick)
{
- // DS18B20_Start_conv();
- g_DS18B20_prev_state = g_DS18B20_state;
- g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
l_DS18B20_DMA_error_count = 0;
- DS18B20_Reset(); // Blocking ~500us
- DS18B20_Write_DMA(0xCC); // Send 'Skip ROM' command
+ DS18B20_Reset_DMA();
}
else
{
g_DS18B20_tick--;
}
break;
+ case ST_DS18B20_BUSY_SENDING_RESET:
+ if (true == b_DS18B20_DMA_TX_done)
+ {
+ __HAL_UART_DISABLE(&huart1);
+ LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 115200);
+ __HAL_UART_ENABLE(&huart1);
+ g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
+ DS18B20_Write_DMA(DS18B20_SKIP_ROM_CMD);
+ }
+ break;
case ST_DS18B20_BUSY_SENDING_SKIP_ROM:
- if (true == b_DS18B20_DMA_done)
+ if (true == b_DS18B20_DMA_TX_done)
{
switch (g_DS18B20_prev_state)
{
case ST_DS18B20_READY:
g_DS18B20_prev_state = g_DS18B20_state;
g_DS18B20_state = ST_DS18B20_BUSY_SENDING_CONV_T;
- DS18B20_Write_DMA(0x44); // Send 'Convert T' command
- break;
+ DS18B20_Write_DMA(DS18B20_CONVERT_T_CMD);
+ break;
case ST_DS18B20_BUSY_WAITING_CONV:
g_DS18B20_prev_state = g_DS18B20_state;
g_DS18B20_state = ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD;
- DS18B20_Write_DMA(0xBE); // Send 'read scratchpad' command
- break;
+ g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
+ DS18B20_Write_DMA(DS18B20_READ_SCRATCHPAD_CMD);
+ break;
default:
g_DS18B20_state = ST_DS18B20_READY;
- break;
+ break;
}
}
break;
case ST_DS18B20_BUSY_SENDING_CONV_T:
- if (true == b_DS18B20_DMA_done)
+ if (true == b_DS18B20_DMA_TX_done)
{
g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
g_DS18B20_tick = G_DS18B20_CONV_TIME_MS;
@@ -207,48 +250,148 @@ void DS18B20_Update(void)
case ST_DS18B20_BUSY_WAITING_CONV:
if (0 == g_DS18B20_tick)
{
- DS18B20_Reset();
- DS18B20_Write_DMA(0xCC); // Send 'Skip ROM' command
+ // Start reading sensor data
+ DS18B20_Reset_DMA();
+ }
+ else
+ {
+ g_DS18B20_tick--;
+ }
+ break;
- g_DS18B20_prev_state = g_DS18B20_state;
- g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
+ case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
+ if (0 == g_DS18B20_tick)
+ {
+ if (true == b_DS18B20_DMA_TX_done)
+ {
+ // Read sensor LSB of data
+ DS18B20_Read_DMA();
+ DS18B20_Write_DMA(0xFF);
+
+ g_DS18B20_prev_state = ST_DS18B20_BUSY_WAITING_LSB;
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING;
+ g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
+ }
+ }
+ else
+ {
+ g_DS18B20_tick--;
+ }
+ break;
+
+ case ST_DS18B20_BUSY_WAITING_LSB:
+ if (true == b_DS18B20_DMA_RX_done)
+ {
+ // Process received byte
+ uint8_t received_value = 0;
+ for (uint8_t i = 0; i < 8; ++i)
+ {
+ if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+ {
+ received_value |= (1 << i);
+ }
+ }
- /*
- DS18B20_Write(0xBE); // Send 'read scratchpad' command
+ Temp_LSB = received_value;
+ g_DS18B20_prev_state = ST_DS18B20_BUSY_WAITING_MSB;
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING;
+ g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
- HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
- HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+ DS18B20_Read_DMA();
+ DS18B20_Write_DMA(0xFF);
+ }
- b_DS18B20_Received_data_LSB = true;
- g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
- g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
- */
+ if (0 == g_DS18B20_tick)
+ {
+ // Try again readying scratchpad
+ g_DS18B20_DMA_error_count++;
+ l_DS18B20_DMA_error_count++;
+ put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
+
+ // Give up on reading temp for this update
+ HAL_UART_DMAStop(&huart1);
+ __HAL_UART_DISABLE(&huart1);
+ __HAL_UART_CLEAR_PEFLAG(&huart1);
+ __HAL_UART_CLEAR_FEFLAG(&huart1);
+ __HAL_UART_CLEAR_NEFLAG(&huart1);
+ __HAL_UART_CLEAR_OREFLAG(&huart1);
+ __HAL_UART_ENABLE(&huart1);
+ memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
+
+ g_DS18B20_state = ST_DS18B20_READY;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
}
else
{
g_DS18B20_tick--;
}
-
break;
- case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
- if (true == b_DS18B20_DMA_done)
+ case ST_DS18B20_BUSY_WAITING_MSB:
+ if (true == b_DS18B20_DMA_RX_done)
{
- HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
- HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+ // Process received byte
+ uint8_t received_value = 0;
+ for (uint8_t i = 0; i < 8; ++i)
+ {
+ if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+ {
+ received_value |= (1 << i);
+ }
+ }
+
+ Temp_MSB = received_value;
+ g_DS18B20_temp = ((Temp_MSB << 8) | Temp_LSB) / 16;
+ g_DS18B20_state = ST_DS18B20_READY;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ g_DS18B20_update_count++;
+ put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
+ }
+
+ if (0 == g_DS18B20_tick)
+ {
+ // Try again readying scratchpad
+ g_DS18B20_DMA_error_count++;
+ l_DS18B20_DMA_error_count++;
+ put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
+
+ // Start again converting temp
+ HAL_UART_DMAStop(&huart1);
+ __HAL_UART_DISABLE(&huart1);
+ __HAL_UART_CLEAR_PEFLAG(&huart1);
+ __HAL_UART_CLEAR_FEFLAG(&huart1);
+ __HAL_UART_CLEAR_NEFLAG(&huart1);
+ __HAL_UART_CLEAR_OREFLAG(&huart1);
+ __HAL_UART_ENABLE(&huart1);
+ memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
+
+ g_DS18B20_state = ST_DS18B20_READY;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ }
+ else
+ {
+ g_DS18B20_tick--;
+ }
+ break;
- b_DS18B20_Received_data_LSB = true;
- g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
+ case ST_DS18B20_BUSY_WAITING:
+ if (0 == g_DS18B20_tick)
+ {
+ g_DS18B20_state = g_DS18B20_prev_state;
g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
}
+ else
+ {
+ g_DS18B20_tick--;
+ }
break;
+
case ST_DS18B20_BUSY_WAITING_DMA:
- // Process received byte if any
- if (true == b_DS18B20_Received_data)
+ /*
+ if (true == b_DS18B20_DMA_RX_done)
{
- b_DS18B20_Received_data = false;
-
+ // Process received byte
uint8_t received_value = 0;
for (uint8_t i = 0; i < 8; ++i)
{
@@ -258,40 +401,43 @@ void DS18B20_Update(void)
}
}
- if (true == b_DS18B20_Received_data_LSB)
- {
- b_DS18B20_Received_data_LSB = false;
- // LSB
- // g_DS18B20_temp = (0x00FF & received_value);
- Temp_LSB = received_value;
- g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
-
- HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
- HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
- }
- else
- {
- // MSB
- // g_DS18B20_temp = ((g_DS18B20_temp | (0xFF00 & (received_value << 8))) / 16.0);
- Temp_MSB = received_value;
- g_DS18B20_temp = ((Temp_MSB << 8) | Temp_LSB) / 16;
- g_DS18B20_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
-
- g_DS18B20_update_count++;
- put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
- }
+ Temp_MSB = received_value;
+ g_DS18B20_temp = ((Temp_MSB << 8) | Temp_LSB) / 16;
+ g_DS18B20_state = ST_DS18B20_READY;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ g_DS18B20_update_count++;
+ put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
+ }
+ */
+ if (0 == g_DS18B20_tick_delay)
+ {
+ g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
+ DS18B20_Read_DMA();
+ DS18B20_Write_DMA(0xFF);
+ }
+ else
+ {
+ g_DS18B20_tick_delay--;
}
- else if (0 == g_DS18B20_tick) // Error handling
+
+ if (0 == g_DS18B20_tick) // Error handling
{
- if (5 > l_DS18B20_DMA_error_count)
+ if (1 > l_DS18B20_DMA_error_count)
{
// Try again readying scratchpad
g_DS18B20_DMA_error_count++;
l_DS18B20_DMA_error_count++;
put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
- /*
+ g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
+ DS18B20_Read_DMA();
+ DS18B20_Write_DMA(0xFF);
+
+ // g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
+ }
+ else
+ {
+ // Give up on reading temp for this update
HAL_UART_DMAStop(&huart1);
__HAL_UART_DISABLE(&huart1);
__HAL_UART_CLEAR_PEFLAG(&huart1);
@@ -300,18 +446,6 @@ void DS18B20_Update(void)
__HAL_UART_CLEAR_OREFLAG(&huart1);
__HAL_UART_ENABLE(&huart1);
memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
-
- HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
- HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
- */
-
- g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
- }
- else
- {
- // Give up on reading temp for this update
- __HAL_UART_DISABLE(&huart1);
- __HAL_UART_ENABLE(&huart1);
g_DS18B20_state = ST_DS18B20_READY;
g_DS18B20_tick = G_TEMP_PERIOD_MS;
}
@@ -331,15 +465,7 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
- switch (g_DS18B20_state)
- {
- case ST_DS18B20_BUSY_SENDING_SKIP_ROM:
- case ST_DS18B20_BUSY_SENDING_CONV_T:
- case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
- b_DS18B20_DMA_done = true;
- break;
- default: break;
- }
+ b_DS18B20_DMA_TX_done = true;
}
}
@@ -347,6 +473,14 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
- b_DS18B20_Received_data = true;
+ b_DS18B20_DMA_RX_done = true;
+ }
+}
+
+void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
+{
+ if (huart->Instance == USART1)
+ {
+ b_DS18B20_DMA_RX_done = true;
}
}