Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Теряются данные при считывании по UART
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Atlantis-
Здравствуйте!
Столкнулся с проблемой потери данных и не понимаю откуда ноги растут.
Суть такая: по таймеру с частотой 500 Гц я опрашиваю датчики. На одной шине UART расположены два датчика. То есть я отправляю команду, считываю данные (по DMA) с одного датчика, переключаю на другой датчик - считываю данные с него. Раньше у меня была передача по USB и я в прерывании, каждую 1 мс проверял, есть ли данные от датчиков, копировал в отдельный массив и передавал.
Сейчас мне надо перейти на UART и тот же самый алгоритм почему то дает непонятный сбой. Каждую 1 мс по UART присылаю команду "передать данные", в прерывании проверяю есть ли данные, перекопирую их в массив, в начало массива добавляю счетчик и кол-во данных. После запуска через несколько секунд возникает сбой - байт "кол-во данных" пропадает.
=GM=
Цитата(Atlantis- @ Oct 23 2015, 10:02) *
На одной шине UART расположены два датчика

Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц...
r_dot
Цитата(Atlantis- @ Oct 23 2015, 13:02) *
... с частотой 500 Гц я опрашиваю датчики.
... Каждую 1 мс по UART присылаю команду "передать данные"...

"С частотой 500 Гц" - это каждые 2 мс...
Где наврали?

И очень подозрительно реализован опрос: может, после посылки команды "передать данные" надо дожидаться ответа на неё, а не посылать следующую команду? В приёмнике ведь наверняка есть приёмный буфер?
Atlantis-
Цитата(=GM= @ Oct 23 2015, 13:17) *
Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц...

переключаю микросхемой 74HC126D, скорость 350 000 бит/с
но какая разница? в варианте, когда я считывал данные по USB ничего не терялось, иначе на ПК все бы полетело.
uriy
А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена?
Atlantis-
Цитата(r_dot @ Oct 23 2015, 13:37) *
"С частотой 500 Гц" - это каждые 2 мс...
Где наврали?

И очень подозрительно реализован опрос: может, после посылки команды "передать данные" надо дожидаться ответа на неё, а не посылать следующую команду? В приёмнике ведь наверняка есть приёмный буфер?

там устроено так:посылается первый запрос данных, запускается таймер, после приема данных линии UART переключаются на второй датчик, через 1 мс срабатывает прерывание таймера - считываем данные от второго датчика, переключаем UART на первый датчик, через 2 мс (от старта) считываем данные с первого датчика и т.д.
То есть датчик опрашивается каждые 2 мс.

Далее, чтобы отправить то что пришло с датчиков по RS-485, я опрашиваю МК каждые 1 мс, есть ли данные

Цитата(uriy @ Oct 23 2015, 14:47) *
А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена?

переключение происходит в прерывании от DMA - то есть при условии, когда нужное кол-во данных пришло
Atlantis-
Сделал на стороне STM32 постоянный массив, который считываю каждые 1 мс - все равно через некоторое время байт пропадает. Получается ошибка происходит в момент передачи по USB. Посмотрел - там какие то диковинные процессы происходят. У меня там два массива и бит, который их переключает. Алгоритм такой: каждые 1 мс инвертирую этот бит и посылаю запрос данных. если бит =1, то из UART данные приходят в массив 1, а в USB передаются данные из массива 2, если бит =0, то наоборот.
По UART всегда передается 19 байт за 1 мс. Я поставил точку остановки в момент передачи по USB - в обоих массивах как то оказалось больше 19 байт. Не понимаю, как это вообще возможно. Вроде бы все просто: пока один буфер заполняется, другой вычитывается, потом наоборот, как они могут переполниться?
=GM=
Цитата(Atlantis- @ Oct 24 2015, 13:34) *
По UART всегда передается 19 байт за 1 мс

1000/19/10 = 5.26 мкс,что соответствует 190 кбит/с. Это что ж у вас за скорость такая нестандартная?
Цитата(Atlantis- @ Oct 24 2015, 13:34) *
пока один буфер заполняется, другой вычитывается, потом наоборот, как они могут переполниться?

Что ж, пора взглянуть на вашу программу. Интересно, как вы буфера переполняете.
Atlantis-
Цитата(=GM= @ Oct 26 2015, 13:14) *
1000/19/10 = 5.26 мкс,что соответствует 190 кбит/с. Это что ж у вас за скорость такая нестандартная?

Что ж, пора взглянуть на вашу программу. Интересно, как вы буфера переполняете.

скорость 1 Мбит/с, а что какие то проблемы с нестандартными скоростями?
программа осталась на работе, но напишу все, что вспомню, там несложно

итак, у меня есть два буфера, два индекса элементов и бит - переключатель буферов
Код
BYTE Buff0[76];
BYTE Buff1[76];
BYTE InPtr0 =0;
BYTE InPtr1 =0;
bit ToggleBuff =0;


переключение буферов происходит в прерывании USB Start of Frame при условии, что передача данных запущена. Что-то типа такого
Код
void USB_Isr
{

if (пришел Start of Frame)
{
    if(transmit !=0)//бит, устанавливается командой USB
      {

      ToggleBuff = ~ToggleBuff;
      SBUF =0x38;//посылаем запрос данных по UART
      
       }


}

if(Endpoint свободна)
{
  DataOut =1;//разрешили передачу данных
}



}


в main опрашиваю флаги, передаю данные
Код
if ((transmit ==1) && (DataOut ==1))
{
DataOut =0;

if (ToggleBuff)
{
  //передаю данные из Buff0, сбрасываю InPtr0 =0
}
else
{
  //передаю данные из Buff1, сбрасываю InPtr1 =0
}

}


в прерывании UART пишу в буфер, в зависимости от флага
Код
void UART_Isr
{
//сбрасываю флаг прерывания
if (ToggleBuff)
{
  //пишу данные в Buff1, инкрементирую InPtr1++
}
else
{
  //пишу данные в Buff0, инкрементирую InPtr0++
}

}

}
esaulenka
Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету.
Atlantis-
Цитата(esaulenka @ Oct 27 2015, 12:06) *
Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету.

тогда бы сбои были систематическими, а у меня они в разное время происходят, порой после 20-30 секунд, а это уже тысячи переданных пакетов.

Походу я ошибся в определении источника ошибок...установил в одном из буферов приемника условие, что принято меньше 19 байт и точку остановки там - в процессе передачи улетел в эту точку, посмотрел приемный буфер - не хватает второго байта. Значит дело все таки в STM32. Но там вообще мистика, я не понимаю как так может быть. Вот мой обработчик прерываний UART
CODE

void UART5_IRQHandler(void)
{
uint8_t Data;
uint16_t Length;

if ((UART5->SR & USART_SR_TC) != 0)
{

UART5->SR &= ~USART_SR_TC;//очистить флаг окончания передачи по UART

if(OUT_buf < IN_buf)
{
USART_SendData(UART5, BuffUART[OUT_buf]);
OUT_buf++;
}


}
else if ((UART5->SR & USART_SR_RXNE) != 0)
{

switch (USART_ReceiveData(UART5))
{


case 0x38:
//передать данные

if (Transfer != 0)
{


BuffUART[0] = 19;
BuffUART[1] = 16;
BuffUART[2] = 1;
BuffUART[3] = 0x55;
BuffUART[4] = 0xCC;
BuffUART[5] = 0;
BuffUART[6] = counter1;
BuffUART[7] = 0;
BuffUART[8] = counter1;
BuffUART[9] = 0;
BuffUART[10] = counter1;
counter1++;
BuffUART[11] = 0;
BuffUART[12] = counter1;
BuffUART[13] = 0;
BuffUART[14] = counter1;
BuffUART[15] = 0;
BuffUART[16] = counter1;
BuffUART[17] = 0x0D;
BuffUART[18] = 0xAA;

if (ToggleFlag ==1)
{
BuffUART[2] = 1;
ToggleFlag =0;
}
else
{
BuffUART[2] = 1;//если тут 2, то происходят сбои! если 1, то сбоев нет
ToggleFlag++;
}
OUT_buf=0;
IN_buf = 19;
USART_SendData(UART5, BuffUART[OUT_buf]);
OUT_buf++;
}



break;

}

UART5->SR &= ~USART_SR_RXNE;//очистить флаг приема данных по UART

}



}


изменение значения BuffUART[2] почему то приводит к сбоям
esaulenka
Ничего не понял.
Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК.
Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-)

Кто такой BuffUART[2] вообще неясно. Если он нигде не анализируется, на выполнение программы влиять он не должен никак.
psL
uart вообще может мусор с линии принимать, тем более на больших скоростях. Как минимум нужна синхронизация по началу кадра и crc данных кадра
Atlantis-
Цитата(esaulenka @ Oct 27 2015, 15:28) *
Ничего не понял.
Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК.
Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-)

Кто такой BuffUART[2] вообще неясно. Если он нигде не анализируется, на выполнение программы влиять он не должен никак.

Даа не так. Данные приходят с датчиков на STM32, он по UART передает на C8051F320, а тот передает по USB. Чтобы вычленить проблему, я данные с датчиков вообще не трогаю. А по запросу от C8051F320 передаю ему фиксированный массив из 19 байт. И если меняю значение BuffUART[2], то получаю сбои.

Цитата(esaulenka @ Oct 27 2015, 15:28) *
Если он нигде не анализируется, на выполнение программы влиять он не должен никак.

вот именно!
wangan
А ты не рассматривал вариант что когда когда ты переключаешь 74HC126D на уарт пролазит байт нулевой, попробуй после каждого переключения очищать аппаратный буфер уарта.
Atlantis-
Кстати проблема появилась, когда стал передавать данные с двух датчиков. С одним датчиком проблем не было. Частота запроса данных - 1 кГц, всегда. Данные от датчика поступают раз в 2,25 мс. То есть получалось, что данные мне отправлялись примерно через раз. Два датчика соответственно передают данные в 2 раза чаще, но все равно реже чем раз за 1 мс. У меня получалось (смотрел пакеты на верхнем уровне), что как раз данные приходят через один - сначала от первого датчика, потом пакет от второго и т.д.

Тогда, чтобы убрать влияние датчиков, я стал передавать просто фиксированный массив из 19 байт.
BuffUART[2] показывает, от какого датчика пришли данные, поэтому я периодически меняю ее значение, чтобы один и тот же пакет данных на верхнем уровне интерпретировался как данные от первого или второго датчика.

Вот тут и получается непонятный фокус...
если делать такое условие, то все работает
Код
if (ToggleFlag ==1)
{
BuffUART[2] = 1;
ToggleFlag =0;
}
else
{
BuffUART[2] = 1;//если тут 2, то происходят сбои! если 1, то сбоев нет
ToggleFlag++;
}


а если написать там 2, то через какое то время происходит сбой - теряется BuffUART[1]...

Цитата(wangan @ Oct 27 2015, 18:20) *
А ты не рассматривал вариант что когда когда ты переключаешь 74HC126D на уарт пролазит байт нулевой, попробуй после каждого переключения очищать аппаратный буфер уарта.

чтобы отсечь такие ошибки, я не трогаю то, что приходит от датчиков, а передаю фиксированный массив. датчики расположены на USART1, а я по запросу я передаю по UART5
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.