Files
ds18b20-MODBUS/john103C6T6NewVer/MODBUS_MAP.md
2026-06-25 17:25:41 +03:00

202 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Modbus Map
Документ составлен по прошивке:
- `..\new rev\john103C8T6\Modbus\modbus_config.h`
- `..\new rev\john103C8T6\Modbus\modbus_data.h`
- `..\new rev\john103C8T6\Modbus\modbus_data.c`
- `..\new rev\john103C8T6\Core\Src\main.c`
- `..\new rev\john103C8T6\Core\Inc\PROJ_setup.h`
Адреса ниже указаны в 0-based формате, как они используются в прошивке. В некоторых Modbus-терминалах эти же адреса отображаются как `30001`, `40001`, `00001` и т.п. В таком терминале к адресу обычно надо прибавить `1` и выбрать нужный тип таблицы.
## Общие параметры
| Параметр | Значение |
|---|---|
| Протокол | Modbus RTU |
| Slave ID | `3` |
| Slave UART | `USART1`, `PB6 TX`, `PB7 RX` |
| Slave UART настройки | `115200`, `8N1` |
| Slave таймер | `TIM2` |
| Master UART | `USART2`, `PA2 TX`, `PA3 RX` |
| Master UART настройки | `115200`, `8N1` |
| Master таймер | `TIM4` |
| `MAX_SENSE` | `32` |
| Включенные таблицы | Coils, Holding Registers, Input Registers |
## Input Registers, function `0x04`
Базовый массив: `MB_DATA.InRegs`, адресный диапазон прошивки `0..1999`.
| Адрес | Кол-во | Имя | Тип | Описание |
|---:|---:|---|---|---|
| `0` | `32` | `sens_Temp[0..31]` | `uint16_t` | Температура DS18B20, в коде записывается как `temperature * 10`. Рекомендуется читать как `int16_t / 10.0`, если возможны отрицательные температуры |
| `32` | `968` | `reserve` | `uint16_t[]` | Резерв до адреса `999` |
| `1000` | `128` | `ID.DevAddr[32][8]` | raw bytes as registers | ROM-коды DS18B20: 32 датчика по 8 байт. Для датчика `N`: базовый регистр `1000 + N * 4` |
| `1128` | `72` | `reserve1` | `uint16_t[]` | Резерв до адреса `1199` |
| `1200` | `1` | `num_Tsens` | `uint16_t` | Количество найденных датчиков DS18B20 |
| `1201` | `1` | `rtc.hours` | `uint16_t` | Текущие часы RTC |
| `1202` | `1` | `rtc.minutes` | `uint16_t` | Текущие минуты RTC |
| `1203` | `1` | `rtc.seconds` | `uint16_t` | Текущие секунды RTC |
| `1204` | `1` | `rtc.date` | `uint16_t` | День месяца |
| `1205` | `1` | `rtc.month` | `uint16_t` | Месяц |
| `1206` | `1` | `rtc.year` | `uint16_t` | Год в формате RTC проекта |
| `1207` | `1` | `rtc.weekday` | `uint16_t` | День недели |
| `1208` | `1` | `rtc.apply` | `uint16_t` | Для input-регистров обычно `0` |
| `1209` | `1` | `rtc.status` | `uint16_t` | Статус RTC |
| `1210` | `790` | reserved | `uint16_t[]` | Адреса доступны в общем диапазоне, прикладного поля нет |
## Holding Registers, functions `0x03`, `0x06`, `0x10`
Базовый массив: `MB_DATA.HoldRegs`, адресный диапазон прошивки `0..1999`.
| Адрес | Кол-во | Имя | Тип | Описание |
|---:|---:|---|---|---|
| `0` | `32` | `set_Temp[0..31]` | `uint16_t` | Уставки температуры для датчиков. В текущем коде используются как градусы без умножения на 10 |
| `32` | `68` | `reserve` | `uint16_t[]` | Резерв до адреса `99` |
| `100` | `32` | `set_hyst[0..31]` | `uint16_t` | Гистерезис температуры для датчиков. В текущем коде используется как градусы |
| `132` | `68` | `reserve1` | `uint16_t[]` | Резерв до адреса `199` |
| `200` | `1` | `rtc.hours` | `uint16_t` | Часы для установки RTC |
| `201` | `1` | `rtc.minutes` | `uint16_t` | Минуты для установки RTC |
| `202` | `1` | `rtc.seconds` | `uint16_t` | Секунды для установки RTC |
| `203` | `1` | `rtc.date` | `uint16_t` | День месяца |
| `204` | `1` | `rtc.month` | `uint16_t` | Месяц |
| `205` | `1` | `rtc.year` | `uint16_t` | Год в формате RTC проекта |
| `206` | `1` | `rtc.weekday` | `uint16_t` | День недели |
| `207` | `1` | `rtc.apply` | `uint16_t` | Записать `1`, чтобы применить время RTC |
| `208` | `1` | `rtc.status` | `uint16_t` | Статус установки RTC |
| `209` | `1791` | reserved | `uint16_t[]` | Адреса доступны в общем диапазоне, прикладного поля нет |
RTC status:
| Значение | Имя | Описание |
|---:|---|---|
| `0` | `MB_RTC_STATUS_IDLE` | Нет операции |
| `1` | `MB_RTC_STATUS_SET_OK` | Время установлено |
| `2` | `MB_RTC_STATUS_VALUE_ERROR` | Ошибка значения времени/даты |
| `3` | `MB_RTC_STATUS_HAL_ERROR` | Ошибка HAL RTC |
## Coils, functions `0x01`, `0x05`, `0x0F`
Базовый массив: `MB_DATA.Coils`, адресный диапазон прошивки `0..999`.
| Coil address | Кол-во | Имя | Описание |
|---:|---:|---|---|
| `0` | `48` | `coils[0..2]` | Общие управляющие биты `state_val_01..state_val_16` в трех 16-битных словах |
| `20` | `1` | `coils[1].state_val_05` | Управляет `PA10 / Relay_dc5v` в основном цикле |
| `48` | `80` | `reserve_coils` | Резерв до coil `127` |
| `128` | `32` | `status_tSens[0..1]` | Статусы подключения DS18B20: `Temp1_isConnected..Temp32_isConnected` |
| `160` | `96` | `reserve_status_tSens` | Резерв до coil `255` |
| `256` | `16` | `relay_struct_on` | Расчетные биты включения реле по датчикам `Temp1..Temp16` |
| `272` | `16` | `reserve_relay_struct_on` | Резерв |
| `288` | `16` | `relay_struct_off` | Расчетные биты выключения реле по датчикам `Temp1..Temp16` |
| `304` | `80` | reserved | Резерв до coil `383` |
| `384` | `1` | `init_param` | При записи `1` прошивка применяет `set_Temp[]` и `set_hyst[]`, затем сбрасывает бит |
| `385` | `1` | `init_Tsens` | При записи `1` прошивка повторно ищет DS18B20, затем сбрасывает бит |
| `386` | `1` | `Save_Param_to_Flash` | Поле объявлено, активного использования в текущем `main.c` не найдено |
| `387` | `13` | reserved2 | Резервные биты |
| `400` | `600` | reserved | Адреса доступны в общем диапазоне, прикладного поля нет |
## Привязка температур и реле
В `value_control()` прошивка сравнивает `sens[i].temperature` с уставкой и гистерезисом:
- если `temperature < set_temp - hyst`, выставляется `relay_struct_off` для датчика `i`;
- если `temperature > set_temp + hyst`, выставляется `relay_struct_on` для датчика `i`;
- если `temperature == set_temp`, оба бита для датчика сбрасываются.
Эти расчетные биты лежат в coils `256..271` и `288..303`. Прямая аппаратная привязка этих расчетных битов к GPIO-выходам в текущем `main.c` не найдена. Прямое управление GPIO найдено только для `PA10 / Relay_dc5v` через coil `20`.
## GUI binding to the real STM project
Source project checked: `..\new rev\john103C8T6`.
The PC GUI bridge is bound to the actual STM Modbus layout from:
- `Modbus\modbus_config.h`
- `Modbus\modbus_data.h`
- `Core\Src\main.c`
- `Core\Inc\ds18b20_driver.h`
- `Core\Inc\PROJ_setup.h`
Active STM settings:
| Item | Value |
|---|---:|
| Default slave ID | `3` |
| `MAX_SENSE` in STM | `32` |
| GUI channels used | first `16` |
| STM protocol on COM | Modbus RTU |
| Optional GUI network mode | Modbus TCP gateway/device with the same register map |
GUI runtime map:
| GUI value | STM source | Modbus function | 0-based address |
|---|---|---:|---:|
| Current temperature channel `N` | `MB_DATA.InRegs.sens_Temp[N]` | `0x04` | `0 + N` |
| DS18B20 ROM ID channel `N` | `MB_DATA.InRegs.ID.DevAddr[N][8]` | `0x04` | `1000 + N * 4` |
| Sensor connected channel `N` | `MB_DATA.Coils.status_tSens` | `0x01` | `128 + N` |
| Setpoint channel `N` | `MB_DATA.HoldRegs.set_Temp[N]`, value = `degC * 10` | `0x03` / `0x06` | `0 + N` |
| Apply setpoints | `MB_DATA.Coils.init_param` | `0x05` | `384` |
| Open command/state channel `N` | `MB_DATA.Coils.relay_struct_on` | `0x01` / `0x05` | `256 + N` |
| Close command/state channel `N` | `MB_DATA.Coils.relay_struct_off` | `0x01` / `0x05` | `288 + N` |
Notes:
- GUI channel `1` uses index `N = 0`; GUI channel `16` uses index `N = 15`.
- Setpoints are written as tenths of a degree: GUI `28.5°C` -> Modbus holding value `285`; readback `285` -> GUI `28.5°C`.
- DS18B20 IDs are stored by STM as `uint8_t DevAddr[32][8]` and exposed through 16-bit input registers. The bridge restores each register in little-endian byte order to display the ROM ID correctly.
- The current STM project does not expose analog valve position or opening angle registers. GUI position/angle are therefore derived from binary relay state: open = `100% / 90°`, close = `0% / 0°`.
- `value_control()` in `Core\Src\main.c` calculates `relay_struct_on/off` from temperature, setpoint, and hysteresis. Direct manual coil writes from GUI can be overwritten by that firmware logic unless STM firmware adds a manual override register/coil.
## STM room/channel structure added for GUI
Added to Keil STM project `..\new rev\john103C8T6`.
### Input registers: room status block
Base address: `400`. One room/channel uses `18` registers. Channel `N` uses base `400 + N * 18`, where GUI channel 1 is `N = 0`.
| Offset | Field | Scale / meaning |
|---:|---|---|
| 0 | `channel` | 1-based channel number |
| 1 | `location` | numeric location code |
| 2..5 | `ds18b20_id[4]` | 8-byte DS18B20 ROM ID, little-endian bytes per register |
| 6 | `temperature_x10` | current temperature, degC * 10 |
| 7 | `setpoint_x10` | setpoint, degC * 10 |
| 8 | `hysteresis_x10` | hysteresis, degC * 10 |
| 9 | `valve_position_pct` | valve opening percent, 0..100 |
| 10 | `valve_angle_deg` | opening angle in degrees |
| 11 | `valve_angle_max_deg` | max opening angle, default 90 |
| 12 | `is_connected` | DS18B20 connected flag |
| 13 | `valve_open` | open relay/command state |
| 14 | `valve_close` | close relay/command state |
| 15 | `mode` | 0 auto, 1 manual |
| 16 | `command_state` | 0 stop, 1 open, 2 close |
| 17 | `reserved` | reserved |
### Holding registers: room control block
Base address: `300`. One room/channel uses `8` registers. Channel `N` uses base `300 + N * 8`.
| Offset | Field | Scale / meaning |
|---:|---|---|
| 0 | `setpoint_x10` | writable setpoint, degC * 10 |
| 1 | `hysteresis_x10` | writable hysteresis, degC * 10 |
| 2 | `valve_position_pct` | writable manual opening percent, 0..100 |
| 3 | `valve_angle_max_deg` | max opening angle, default 90 |
| 4 | `mode` | 0 auto, 1 manual |
| 5 | `command` | 0 stop, 1 open, 2 close |
| 6 | `location` | numeric location code |
| 7 | `apply` | write 1 to apply room setpoint/hysteresis |
Compatibility:
- Legacy `set_Temp[0..31]` at holding `0..31` is kept.
- Legacy `set_hyst[0..31]` at holding `100..131` is kept.
- Legacy coils `256..271` and `288..303` are kept.
- The Python bridge writes both the legacy map and the new room control block.