NUCLEO-F446RE Modbus Slave - Writes Work (LED dimming via PWM), Reads Fail with Truncated Exception Responses
- June 17, 2026
- 2 replies
- 26 views
The Issue
I'm using **nanoMODBUS** (slave mode) on NUCLEO-F446RE via USART2 (115200 baud, 8N1). The slave exposes two holding registers:
- `0x0000`: Potentiometer value (read-only) → `usPotValue`
- `0x0001`: LED brightness (read/write) → `usLedBrightness`
**The LED is controlled via PWM (TIM2).**
Behavior
Operation Result
**Write to `0x0001`** (set LED brightness) Works consistently — LED dims
**Read from `0x0000`** (potentiometer) Fails most of the time
**Read from `0x0001`** (LED brightness) Fails most of the time
**Rare successful read** Both registers return correct values
Master Log
```
Response: empty
Response: empty
Read OK: [609] ← Rare success
Response: empty
Response: empty
Response: 0180018000 ← Truncated exception (5 bytes instead of 7+)
Response: empty
Read OK: [609] ← Another rare success
```
The 5-byte response `0180018000`
- `01` = Slave address (0x01)
- `80` = Function code 0x03 + error bit (exception)
- `01 80 00` = Truncated exception data
Observation and Implication
| Writes work | UART RX is working, Modbus parser is working |
| PWM updates work | `write_single_register_cb()` is called and executes correctly |
| Reads fail | `read_holding_registers_cb()` is **not called consistently**, or returns an error that truncates the response |
| 5-byte exception response | The slave is generating an **exception response** (likely `ILLEGAL_DATA_ADDRESS` or `ILLEGAL_FUNCTION`) but the UART TX stops mid-frame |
1. **Does nanoMODBUS handle the case where `read_holding_registers_cb()` returns an error after already writing some registers to `registers_out`?** Could this cause the truncated response?
2. **Should the master read exactly one register at a time** to avoid the callback returning `ILLEGAL_DATA_ADDRESS` for the second register? Or should the callback handle `quantity > 1` differently?
3. **Could `HAL_Delay(5)` in the main loop** be causing the slave to miss the 3.5 character gap between bytes, causing the frame to be interpreted as incomplete?
4. **Would moving Modbus polling to a timer interrupt** (e.g., 1ms) improve stability by guaranteeing consistent RTU timing?
5. **Are there known issues with `HAL_UART_Transmit()` in polling mode** when used with PWM (TIM2) on STM32F4? Should I use `HAL_UART_Transmit_IT()` instead?
Environment
| **MCU** | STM32F446RE (NUCLEO-F446RE) |
| **Modbus Library** | nanoMODBUS (Slave) |
| **UART** | USART2, 115200, 8N1 |
| **PWM** | TIM2 Channel 1 on PA5 |
| **ADC** | ADC1 Channel 0 on PA0 |
| **CubeIDE** | 2.1.1 |
| **CubeF4** | 1.28.3 |
| **OS** | Windows 11 (ST-Link VCP driver 2.2.0.0) |
thank you for you help
