2025-02-13 07:48 AM
Hello,
I am trying to use the HAL_UARTEx_ReceiveToIdle_DMA function() but the IDLE function don't work.
I call the function here :
/* Extern variables */
extern UART_HandleTypeDef huart4;
extern osEventFlagsId_t comEventHandle;
extern osMessageQueueId_t sensorQueueHandle;
extern osEventFlagsId_t regEventHandle;
extern DMA_HandleTypeDef hdma_uart4_rx;
static void modbus_receive_DMA(void) {
buf_rec = 0; // reset the counter of received bytes in the buffer
/* Reset pin for receiving data */
HAL_GPIO_WritePin(RS485_SIEMENS_RE_GPIO_Port, RS485_SIEMENS_RE_Pin, GPIO_PIN_RESET);
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart4, nmbs.msg.buf, sizeof(nmbs.msg.buf)) != HAL_OK) {
log_debug("HAL_UARTEx_ReceiveToIdle_DMA error");
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart4) {
modbus_receive_DMA();
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart == &huart4) {
switch (HAL_UARTEx_GetRxEventType(huart)) {
case HAL_UART_RXEVENT_IDLE: // when Idle event occurred prior reception has
// been completed (nb of received data is lower
// than expected one).
packet_sended = 0; // clear flag of transmit
buf_rec = Size; // set size of received data
nmbs_error res_poll = nmbs_server_poll(&nmbs);
if (NMBS_ERROR_NONE != res_poll) {
// This will probably never happen, since we don't return < 0 in our
// platform funcs
}
// If there was no packet transmission, then we immediately switch to
// receive mode. Otherwise, this function will trigger an interrupt at the
// end of DMA packet transmission
if (!packet_sended)
modbus_receive_DMA();
break;
}
}
}
I have tryed to replace sizeof(nmbs.msg.buf) by 1 or 2 or 3 and it works but not in IDLE mode. So the function HAL_UARTEx_RxEventCallback works but not in the right way. I have seen on the forum lot of topics with the same problem but I am not able to fix it with my micro..
Do you have any idea ?
Solved! Go to Solution.
2025-02-14 12:30 PM
@simon_EQUIUM wrote:@Karl Yamashita If I have a problem with in the trame, does the function is called ? For example, the CRC is not complet.
Once the parser finds the Line Feed (0x0A), it will queue the packet. You'll have to parse the packet and make sure it's valid. If the packet doesn't have a CRC, then it's a bad packet. So it's up to you on how you want to report the error to the end user.
2025-02-17 01:23 AM
After your reply I have checked something, and I thing I have something interesting.
When I use Putty and I send only 1 bytes the IDLE work every time.
If I send 2 bytes, the IDLE is never called and its never re-works.
I have to reboot the micro to re-send 1 bytes.
Do you have any idea ?
2025-02-17 02:40 AM
Show what code you have now.
2025-02-17 03:03 AM
2025-02-17 05:31 AM
I have tried something, if I use Realterm and I send some ASCII byte, it works like a charm.
BUT If I use KScada Modbus Doctor V2.10 the IDLE doesn't work.
I am wondering if the frame is ok on modbus doctor. But my other question is, if I have a problem with an RS485 frame, how can I prevent my software from being bricked?
2025-02-17 09:23 AM
Use a USB<>Serial adapter and monitor the Rx input of the STM32. Then you can see what the Modbus Doctor does differently than the RealTerm.
A better serial program to use would be Docklight https://docklight.de/
2025-02-18 03:20 AM
Here some frames KO (modbus) :
Here some frames OK (UART ASCII) :
2025-02-18 09:40 AM
I have tryed to replace sizeof(nmbs.msg.buf) by 1 or 2 or 3 and it works but not in IDLE mode.
It may have something to do with the amount of bytes you are trying to receive versus the actual amount being received.
Take a look at this project as it might help you set the amount of bytes you want the DMA ro receive in idle mode. https://github.com/karlyamashita/Nucleo-G431RB_Three_UART/wiki
2025-02-24 02:41 AM - edited 2025-02-24 02:43 AM
Thank you Karl,
The DMA doesn't work since the new STM32G473. I have tried with your example but it is not working with the G473 and the NULL byte. I have gave up, and change to normal UART IT. Thank you for your help.