#include <modbus.h> предоставляет синхронный Modbus RTU Master для чтения и записи holding-регистров через порт Master контроллера. Для начала работы нужен успешный mbInit(). Вызовы ждут завершения транзакции и задерживают остальные callback планировщика C. Не используйте одновременно разных владельцев одного последовательного порта.

Параметры и коды результата

Параметры устройства: addr=1..248 по проверке текущей прошивки (для стандартных устройств используйте 1..247; 248 не является обычным адресом Modbus). Broadcast с адресом 0 этот C API не принимает. start — нулевой 16-битный адрес регистра, а не обозначение 40001: регистру 40001 обычно соответствует start=0, но адрес уточняйте в документации ведомого устройства.

values указывает на массив uint16_t минимум из count элементов. NULL запрещён. Требуется start + count <= 65536; переход за конец адресного пространства отклоняется.

Константы ответа:

  • MB_ERR_OK = 0 — успех.
  • MB_ERR_INIT = -1 — нет инициализации; -1 также возможен при остановке сценария и отказе mbInit().
  • MB_ERR_PARAM_FUNC = -2 — параметры транзакции.
  • MB_ERR_FORMAT_SEND = -3 — формат исходящего кадра.
  • MB_ERR_TIMEOUT_SEND = -4 — тайм-аут передачи.
  • MB_ERR_TIMEOUT_RECEIVE = -5 — тайм-аут ответа.
  • MB_ERR_PDU_CRC = -6 — CRC ответа.
  • MB_ERR_PDU_FORMAT = -7 — формат ответа.
  • MB_ERR_PDU_ERR = -8 — исключение ведомого устройства.

mbInit() может возвращать собственный код низкоуровневой инициализации; этот список относится прежде всего к mbRead()/mbWrite(). Диагностика транзакций выводится в /txt?log.

mbInit

  int mbInit(uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity, uint8_t answerDelay);
  

baudrate — от 1200 до 230400; databits — 8 или 9; stopbits — 1 или 2; parity — MB_PARITY_NONE (0), MB_PARITY_EVEN (1), MB_PARITY_ODD (2). Убедитесь в соответствии настройкам ведомого устройства; аппаратная интерпретация числа бит зависит от режима parity. answerDelay — дополнительная задержка в миллисекундах, которая на порту квантуется в тики по 750 мкс; отдельной проверки диапазона здесь нет. Для Master её влияние зависит от нижнего уровня, поэтому это не замена timeout чтения. Не используйте большие значения без проверки на своей прошивке: результат пересчёта хранится в uint8_t. Возвращает 0 при успехе. Инициализация сбрасывает счётчики успешных чтений/записей.

Ограничение нечётного parity

В текущем C-заголовке MB_PARITY_ODD равен 2, но драйвер USART APM32 использует значение 3 для нечётной чётности. Порт выполняет прямое приведение без преобразования, поэтому режим ODD сейчас не соответствует заявленному. Передать 3 через C API нельзя: проверка mbInit отклонит значение больше 2. До исправления порта не рассчитывайте на нечётную чётность; успешный mbInit сам по себе не подтверждает правильную конфигурацию ODD. Это установлено сверкой исходников, аппаратная проверка линии с parity не выполнялась.

mbRead

  int mbRead(uint8_t addr, uint16_t start, uint16_t count, uint16_t * values, uint16_t timeout);
  

Читает holding-регистры функцией 0x03. timeout задаёт ожидание ответа в миллисекундах и допускается от 1 до 1000. В текущей конфигурации count от 1 до 125. Возвращает 0 либо отрицательный код; используйте результат массива только при успехе.

mbWrite

  int mbWrite(uint8_t addr, uint16_t start, uint16_t count, uint16_t * values);
  

Записывает holding-регистры функцией 0x10. В текущей конфигурации count от 1 до 123. Отдельного аргумента timeout у C-функции нет: используется RECEIVING_TIMEOUT нижнего уровня, сейчас 500 мс. Адрес устройства передаётся явно. Возвращает 0 либо отрицательный код.

Пределы вычисляются из размера буфера прошивки: чтение min(125, (MB_BUFF_LEN-5)/2), запись min(123, (MB_BUFF_LEN-9)/2). Здесь MB_BUFF_LEN=255. Для чтения это максимум 250 байт данных, для записи — 246 байт. Большой прикладной массив разбивайте на несколько транзакций.

mbGetCountRead

  uint32_t mbGetCountRead(void);
  

Возвращает uint32_t-счётчик только успешно завершённых операций соответствующего вида после последней инициализации. Ошибочные транзакции его не увеличивают. Новый C-сценарий должен заново вызвать mbInit().

mbGetCountWrite

  uint32_t mbGetCountWrite(void);
  

Возвращает uint32_t-счётчик только успешно завершённых операций соответствующего вида после последней инициализации. Ошибочные транзакции его не увеличивают. Новый C-сценарий должен заново вызвать mbInit().

Пример

Пример перенастраивает порт Master и выполняет реальную транзакцию. Укажите параметры своего стенда.

  #include <dev.h>
#include <modbus.h>
#include <stdio.h>

int main(void) {
    if (mbInit(9600, 8, 1, MB_PARITY_NONE, 0) != 0) {return 1;}
    uint16_t values[2];
    int result = mbRead(1, 0, 2, values, 200);
    if (result != MB_ERR_OK) {
        printf("Modbus error: %d\n", result);
        return 1;
    }
    printf("Registers: %u, %u\n", (unsigned int)values[0], (unsigned int)values[1]);
    return 0;
}