Всем привет!
Имеется отладочная плата (https://tellur-el.ru/upload/iblock/ac0/r4rucl3gy3hbt0f9sw90cgoz8qmq20p6.pdf).
Пытаюсь принять набор байтов по UART. На UART'е сигнал формируется через преобразователь UART-RS485 на плате (DA2),- точную модель не скажу, в дш её нет, а физически на плате маркировка стёрлась, но по сути это что-то около MAX485. На неё сигнал идёт от преобразователя USB-RS (он точно абсолютно исправен, проверял 100 раз)
Условимся, что я передаю сообщение 0x02320203. Принимаю его в прерывании, код следующий:
rx_buffer имеет вид
В main'е следующее:
Т.е. просто инициализация и установка приёмника на состояние "принимай". В while'е - проверка флага и простенькая функция обработки принятого сообщения:
По идее, я должен передать сообщение контроллеру с ПК, контроллер это сообщение обработает и засветит мне 2 светодиода, если сообщение принято верно, т.е. адрес, команда и 2 информационных байта корректны (напомню - от ПК идёт сообщение 0x02320203).
Итак, сама проблема. Если я засуну функции RED_LED_ON() и GREEN_LED_ON() в обработчик прерывания, вот сюда:
То загорится ТОЛЬКО красный диод! Т.е. последний байт (0x03) почему-то не записывается.
И это ещё не всё.
Если сделать такую же проверку, но уже в основной функции (после проверки флага, зайдя в функцию comand_processing()) - вообще ничего не сработает, т.е. comand_processing(), описанная выше, вообще не зажжёт светодиоды, однако если немного поменять условие:
То красный диод загорается! Т.е. в прерывании, после обработки принятых байтов, 0x02 лежит в rx_buffer.data[0], а когда я делаю проверку в основной функции, то байт перемещается в rx_buffer.data[1]. Последний байт всё ещё не принимается. Однако зелёный светодиод загорается, т.е. в этом элементе массива (rx_buffer.data[2]) изменение при переходе от прерывания в основную функцию не происходит.
Дополню, что в результате проверки выяснил, что в rx_buffer.data[1] (при обработке прерывания) просто ничего не записывается. Этот байт остается равен нулю, как при инициализации.
Подскажите, где тут собака зарыта)
Уже кажется, что что-то абсолютно очевидное, просто глаза замылились и я этого в упор не вижу.
P.s. на линии всё ок - все байты на месте в нужной последовательности.

Имеется отладочная плата (https://tellur-el.ru/upload/iblock/ac0/r4rucl3gy3hbt0f9sw90cgoz8qmq20p6.pdf).
Пытаюсь принять набор байтов по UART. На UART'е сигнал формируется через преобразователь UART-RS485 на плате (DA2),- точную модель не скажу, в дш её нет, а физически на плате маркировка стёрлась, но по сути это что-то около MAX485. На неё сигнал идёт от преобразователя USB-RS (он точно абсолютно исправен, проверял 100 раз)
Условимся, что я передаю сообщение 0x02320203. Принимаю его в прерывании, код следующий:
C:
if (EPIC_CHECK_UART_0())
{
if (UART_IsRxFifoFull(UART_0)) //данные принялись
{
if((rx_buffer.length == 0)) //проверяю условие на длину информации, которая лежит в буфере
{
rx_buffer.address = UART_0->RXDATA;//если буфер пустой, первый принятый байт засунь в rx_buffer.address
rx_buffer.length++; // увеличь переменную - теперь в буфере лежит 1 байт
}
else if((rx_buffer.length == 1)) // аналогичная проверка
{
rx_buffer.comand = UART_0->RXDATA; // положи второй принятый байт в rx_buffer.comand
switch(rx_buffer.comand) // в зависимости от команды задай значение переменной expected_lenght
{
case 0x32:
expected_lenght = 4;
break;
case 0x46:
case 0x47:
case 0x48:
expected_lenght = 2;
break;
case 0x55:
expected_lenght = 3;
break;
default:
expected_lenght = 0;
}
rx_buffer.length++; //ещё раз увеличь length
}
if((rx_buffer.length < expected_lenght)) // Если сейчас в буфере лежит меньше даты, чем ожидается, то продолжаем принимать
{
rx_buffer.data[rx_buffer.length-2] = UART_ReadByte(UART_0); // клади принятый байт в rx_buffer.data[rx_buffer.length-2]. В первой итерации rx_buffer.length-2 = 0, во второй - единице. Соответственно, нулевой и первый элемент массива.
rx_buffer.length++;
if(rx_buffer.length == expected_lenght) rx_buffer.data[2] = 0xFF;//когда длина станет равной ожидаемой - третий элемент массива сделай 0xFF.
}
if(rx_buffer.length == expected_lenght)
{
flag_msg_received = 1; //если длина равна ожидаемой - установи флаг принятого полностью сообщения.
}
}
}
rx_buffer имеет вид
C:
typedef struct
{
volatile uint8_t address;
volatile uint8_t comand;
volatile uint8_t data[8];
volatile uint8_t length;
volatile uint8_t error;
volatile uint16_t error_counter;
} uart_buffer;
volatile uart_buffer rx_buffer = {0};
В main'е следующее:
C:
int main()
{
write_csr(mtvec, &__TEXT_START__);
SystemClock_Config();
GPIO_Init();
Timer16_0_Init();
HAL_MspInit();
HAL_EPIC_Clear(0xFFFFFFFF);
HAL_EPIC_MaskLevelSet(HAL_EPIC_UART_0_MASK);
HAL_IRQ_EnableInterrupts();
GREEN_LED_OFF();
RED_LED_OFF();
UART_Init(UART_0, (uint32_t)555, UART_CONTROL1_TE_M | UART_CONTROL1_RE_M | UART_CONTROL1_M_8BIT_M
| UART_CONTROL1_RXNEIE_M, 0, UART_CONTROL3_OVRDIS_M);
RS_Receive_MSG();
while (1)
{
if(flag_msg_received == 1)
{
comand_processing();
}
}
}
Т.е. просто инициализация и установка приёмника на состояние "принимай". В while'е - проверка флага и простенькая функция обработки принятого сообщения:
C:
void comand_processing(void)
{
if(rx_buffer.address == 0x02)
{
if(rx_buffer.comand == 0x32)
{
if (rx_buffer.data[0] == 0x02)
{
RED_LED_ON();
if(rx_buffer.data[1] == 0x03)
{
GREEN_LED_ON();
}
}
}
}
}
По идее, я должен передать сообщение контроллеру с ПК, контроллер это сообщение обработает и засветит мне 2 светодиода, если сообщение принято верно, т.е. адрес, команда и 2 информационных байта корректны (напомню - от ПК идёт сообщение 0x02320203).
Итак, сама проблема. Если я засуну функции RED_LED_ON() и GREEN_LED_ON() в обработчик прерывания, вот сюда:
C:
if((rx_buffer.length < expected_lenght))
{
rx_buffer.data[rx_buffer.length-2] = UART_ReadByte(UART_0);
rx_buffer.length++;
if(rx_buffer.data[0] == 0x02) RED_LED_ON();
if(rx_buffer.data[1] == 0x03) GREEN_LED_ON();
if(rx_buffer.length == expected_lenght) rx_buffer.data[2] = 0xFF;
}
И это ещё не всё.
Если сделать такую же проверку, но уже в основной функции (после проверки флага, зайдя в функцию comand_processing()) - вообще ничего не сработает, т.е. comand_processing(), описанная выше, вообще не зажжёт светодиоды, однако если немного поменять условие:
C:
void comand_processing(void)
{
if(rx_buffer.address == 0x02)
{
if(rx_buffer.comand == 0x32)
{
if (rx_buffer.data[1] == 0x02)
{
RED_LED_ON();
if(rx_buffer.data[2] == 0xFF)
{
GREEN_LED_ON();
}
}
}
}
}
То красный диод загорается! Т.е. в прерывании, после обработки принятых байтов, 0x02 лежит в rx_buffer.data[0], а когда я делаю проверку в основной функции, то байт перемещается в rx_buffer.data[1]. Последний байт всё ещё не принимается. Однако зелёный светодиод загорается, т.е. в этом элементе массива (rx_buffer.data[2]) изменение при переходе от прерывания в основную функцию не происходит.
Дополню, что в результате проверки выяснил, что в rx_buffer.data[1] (при обработке прерывания) просто ничего не записывается. Этот байт остается равен нулю, как при инициализации.
Подскажите, где тут собака зарыта)
Уже кажется, что что-то абсолютно очевидное, просто глаза замылились и я этого в упор не вижу.
P.s. на линии всё ок - все байты на месте в нужной последовательности.

Последнее редактирование: