Перейти к содержанию
    

Теряются данные при считывании по UART

Здравствуйте!

Столкнулся с проблемой потери данных и не понимаю откуда ноги растут.

Суть такая: по таймеру с частотой 500 Гц я опрашиваю датчики. На одной шине UART расположены два датчика. То есть я отправляю команду, считываю данные (по DMA) с одного датчика, переключаю на другой датчик - считываю данные с него. Раньше у меня была передача по USB и я в прерывании, каждую 1 мс проверял, есть ли данные от датчиков, копировал в отдельный массив и передавал.

Сейчас мне надо перейти на UART и тот же самый алгоритм почему то дает непонятный сбой. Каждую 1 мс по UART присылаю команду "передать данные", в прерывании проверяю есть ли данные, перекопирую их в массив, в начало массива добавляю счетчик и кол-во данных. После запуска через несколько секунд возникает сбой - байт "кол-во данных" пропадает.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На одной шине UART расположены два датчика

Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... с частотой 500 Гц я опрашиваю датчики.

... Каждую 1 мс по UART присылаю команду "передать данные"...

"С частотой 500 Гц" - это каждые 2 мс...

Где наврали?

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц...

переключаю микросхемой 74HC126D, скорость 350 000 бит/с

но какая разница? в варианте, когда я считывал данные по USB ничего не терялось, иначе на ПК все бы полетело.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"С частотой 500 Гц" - это каждые 2 мс...

Где наврали?

 

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

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

То есть датчик опрашивается каждые 2 мс.

 

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

 

А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена?

переключение происходит в прерывании от DMA - то есть при условии, когда нужное кол-во данных пришло

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал на стороне STM32 постоянный массив, который считываю каждые 1 мс - все равно через некоторое время байт пропадает. Получается ошибка происходит в момент передачи по USB. Посмотрел - там какие то диковинные процессы происходят. У меня там два массива и бит, который их переключает. Алгоритм такой: каждые 1 мс инвертирую этот бит и посылаю запрос данных. если бит =1, то из UART данные приходят в массив 1, а в USB передаются данные из массива 2, если бит =0, то наоборот.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По UART всегда передается 19 байт за 1 мс

1000/19/10 = 5.26 мкс,что соответствует 190 кбит/с. Это что ж у вас за скорость такая нестандартная?

пока один буфер заполняется, другой вычитывается, потом наоборот, как они могут переполниться?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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++
}

}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету.

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

 

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

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] почему то приводит к сбоям

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ничего не понял.

Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК.

Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-)

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

uart вообще может мусор с линии принимать, тем более на больших скоростях. Как минимум нужна синхронизация по началу кадра и crc данных кадра

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ничего не понял.

Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК.

Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-)

 

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

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

 

Если он нигде не анализируется, на выполнение программы влиять он не должен никак.

вот именно!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ты не рассматривал вариант что когда когда ты переключаешь 74HC126D на уарт пролазит байт нулевой, попробуй после каждого переключения очищать аппаратный буфер уарта.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...