Например TDA7294

Форум РадиоКот • Просмотр темы - STM32 - отправляет нули в UART
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вс дек 28, 2025 01:33:17

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 2 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: STM32 - отправляет нули в UART
СообщениеДобавлено: Сб дек 03, 2022 20:47:29 
Родился

Зарегистрирован: Сб дек 03, 2022 20:20:38
Сообщений: 1
Рейтинг сообщения: 0
Всем добрый день!
Имеется STM32F103 и стоит задача сделать устройство MODBUS slave
Реализовал так:

Создал структуру:
Код:
typedef struct {
   uint8_t update; // флаг того что данные обновились
   uint8_t rx_buffer_uart[256]; // буфер по максимальному размеру пакета MODBUS
   uint8_t size; // размер принятных данных
} receive_data;


Затем разрешил приём:
Код:
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t*)receive_data_slave.rx_buffer_uart, BUFFER_SIZE); // разрешить ожидание приёма пакета


В бесконечном цикле основной программы проверяю не обновились ли данные и если данные обновились, то приступаю к обработке:
Код:
  while (1)
  {
     if (receive_data_slave.update == 1)  // если данные обновились
     {
        uint8_t response[256] = {0};  // создать пустой массив для ответа
        process_receive_slave(&receive_data_slave, &slave_hold_reg, &response);  // передать в обработчик полученные данные, регистры для чтения/записи, указатель на массив для ответа
        if (response[0] != 0)  // если массив для ответа не пустой
           while(HAL_UART_Transmit_DMA(&huart1, (uint8_t*)response, sizeof(response)) == HAL_BUSY);  // отправить ответ
        receive_data_slave.update = 0;  // данные обработаны, снимаю флаг обновления
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t*)receive_data_slave.rx_buffer_uart, BUFFER_SIZE);  // разрешаю приём следующих данных
     }
  }


Обработчик выглядит так:
Код:
void process_receive_slave (receive_data* data, uint16_t *reg, uint8_t *response)
{
   if (data->rx_buffer_uart[0] != SLAVE_ADDRESS)  // если данные не для нашего адреса - сразу выходим
      return;

   int crc;
   crc = crc_chk(data->rx_buffer_uart, (data->size)-2);
   if ((data->rx_buffer_uart[(data->size)-1] == (crc & 0xFF00) >> 8) &&  //проверка чек-суммы пакета
         (data->rx_buffer_uart[(data->size)-2] == (crc & 0x00FF)))
   {
      uint16_t addr_reg, quantity;
      addr_reg = ((data->rx_buffer_uart[2]) << 8) + (data->rx_buffer_uart[3]);  // определение адреса регистра указанного в пакете
      switch(data->rx_buffer_uart[1]) {
      case 3:  // если команда на чтение
         quantity = ((data->rx_buffer_uart[4]) << 8) + (data->rx_buffer_uart[5]); // сколько запрошено регистров считать
         response[0] = SLAVE_ADDRESS;  // далее формирование ответа
         response[1] = 0x03;  // команда
         response[2] = quantity * 2;
         uint8_t i = 0;
         uint8_t j = 3;
         while(i < quantity)
         {
            response[j] = (reg[addr_reg-SLAVE_REG_START+i] & 0xFF00) >> 8;
            j++;
            response[j] = reg[addr_reg-SLAVE_REG_START+i] & 0x00FF;
            j++;
            i++;
         }
         crc = crc_chk(response, j);
         response[j] = crc & 0x00FF;
         j++;
         response[j] = (crc & 0xFF00) >> 8;
         break;
      case 6:  // если команда на запись
         reg[addr_reg-SLAVE_REG_START] = ((data->rx_buffer_uart[4]) << 8) + (data->rx_buffer_uart[5]);  // записать данные в регистр

         for (int i=0; i < data->size; i++)  // сформировать ответ - копия запроса
          {
             response[i] = data->rx_buffer_uart[i];
          }
         break;
      default:
         break;
      }
   }
}


Читаю 100 регистров разом с периодом 100 мс - всё ОК. (командой 01 03 00 01 00 64 15 E1)
Но есть проблема, при попытке записи (командой 01 06 00 01 01 F4 D8 1D) (при этом чтение идёт всё также с периодом 100 мс) я иногда получаю ответ состоящий из всех нулей либо на команду записи, либо на команду чтения, следующую за командой записи.

Подскажите, пожалуйста, откуда берутся эти нули?
Ведь стоит защита от оправки пустого ответа и ожидание освобождения передатчика:
Код:
        if (response[0] != 0)
           while(HAL_UART_Transmit_DMA(&huart1, (uint8_t*)response, sizeof(response)) == HAL_BUSY);


Ошибка возникает только при чтении с небольшим периодом или быстрой последовательной записи. Если редко читать и редко писать - ошибки не возникает

Заранее благодарю за помощь


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32 - отправляет нули в UART
СообщениеДобавлено: Вс дек 04, 2022 08:55:01 
Сверлит текстолит когтями

Зарегистрирован: Вт ноя 19, 2019 06:10:18
Сообщений: 1270
Рейтинг сообщения: 0
Цитата:
uint8_t rx_buffer_uart[256];

Цитата:
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t*)receive_data_slave.rx_buffer_uart, BUFFER_SIZE);

Так не хорошо, или везде число, или- имя, что гораздо лучше.

Цитата:
uint8_t response[256] = {0}; // создать пустой массив для ответа

Зачем ещё один массив? Если не собираешься передавать пакеты из RTU-сегмента в TCP/UDP-сегмент, то достаточно одного массива.

Цитата:
while(HAL_UART_Transmit_DMA(&huart1, (uint8_t*)response, sizeof(response)) == HAL_BUSY);

То есть тупо стоим и жгём время, пока посылка не уйдёт? А ведь могли бы заниматься чем-то полезным.

Цитата:
crc = crc_chk(data->rx_buffer_uart, (data->size)-2);

Считай КС _всего_ пакета. В целом пакете она будет 0. Нет?

Я ХАЛом не пользуюсь, но не вижу управления направлением приёма-передачей у трансивера. Или Tx и Rx в физической линии разделены?

Цитата:
я иногда получаю ответ состоящий из всех нулей

В чём смотришь? Я пользовался Termit. Покажи весь ответ.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y