Dima1060 0 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба Здравствуйте! Столкнулся с проблемой потери данных и не понимаю откуда ноги растут. Суть такая: по таймеру с частотой 500 Гц я опрашиваю датчики. На одной шине UART расположены два датчика. То есть я отправляю команду, считываю данные (по DMA) с одного датчика, переключаю на другой датчик - считываю данные с него. Раньше у меня была передача по USB и я в прерывании, каждую 1 мс проверял, есть ли данные от датчиков, копировал в отдельный массив и передавал. Сейчас мне надо перейти на UART и тот же самый алгоритм почему то дает непонятный сбой. Каждую 1 мс по UART присылаю команду "передать данные", в прерывании проверяю есть ли данные, перекопирую их в массив, в начало массива добавляю счетчик и кол-во данных. После запуска через несколько секунд возникает сбой - байт "кол-во данных" пропадает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба На одной шине UART расположены два датчика Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
r_dot 0 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба ... с частотой 500 Гц я опрашиваю датчики. ... Каждую 1 мс по UART присылаю команду "передать данные"... "С частотой 500 Гц" - это каждые 2 мс... Где наврали? И очень подозрительно реализован опрос: может, после посылки команды "передать данные" надо дожидаться ответа на неё, а не посылать следующую команду? В приёмнике ведь наверняка есть приёмный буфер? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц... переключаю микросхемой 74HC126D, скорость 350 000 бит/с но какая разница? в варианте, когда я считывал данные по USB ничего не терялось, иначе на ПК все бы полетело. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 23 октября, 2015 Опубликовано 23 октября, 2015 · Жалоба "С частотой 500 Гц" - это каждые 2 мс... Где наврали? И очень подозрительно реализован опрос: может, после посылки команды "передать данные" надо дожидаться ответа на неё, а не посылать следующую команду? В приёмнике ведь наверняка есть приёмный буфер? там устроено так:посылается первый запрос данных, запускается таймер, после приема данных линии UART переключаются на второй датчик, через 1 мс срабатывает прерывание таймера - считываем данные от второго датчика, переключаем UART на первый датчик, через 2 мс (от старта) считываем данные с первого датчика и т.д. То есть датчик опрашивается каждые 2 мс. Далее, чтобы отправить то что пришло с датчиков по RS-485, я опрашиваю МК каждые 1 мс, есть ли данные А вы уверены что микросхему 74HC126D переключаете когда передача данных уже завершена? переключение происходит в прерывании от DMA - то есть при условии, когда нужное кол-во данных пришло Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 24 октября, 2015 Опубликовано 24 октября, 2015 · Жалоба Сделал на стороне STM32 постоянный массив, который считываю каждые 1 мс - все равно через некоторое время байт пропадает. Получается ошибка происходит в момент передачи по USB. Посмотрел - там какие то диковинные процессы происходят. У меня там два массива и бит, который их переключает. Алгоритм такой: каждые 1 мс инвертирую этот бит и посылаю запрос данных. если бит =1, то из UART данные приходят в массив 1, а в USB передаются данные из массива 2, если бит =0, то наоборот. По UART всегда передается 19 байт за 1 мс. Я поставил точку остановки в момент передачи по USB - в обоих массивах как то оказалось больше 19 байт. Не понимаю, как это вообще возможно. Вроде бы все просто: пока один буфер заполняется, другой вычитывается, потом наоборот, как они могут переполниться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 26 октября, 2015 Опубликовано 26 октября, 2015 · Жалоба По UART всегда передается 19 байт за 1 мс 1000/19/10 = 5.26 мкс,что соответствует 190 кбит/с. Это что ж у вас за скорость такая нестандартная? пока один буфер заполняется, другой вычитывается, потом наоборот, как они могут переполниться? Что ж, пора взглянуть на вашу программу. Интересно, как вы буфера переполняете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 26 октября, 2015 Опубликовано 26 октября, 2015 · Жалоба 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 7 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба Первый признак любимых граблей эмбеддера: слово "прерывание" есть, а слова "волатайл" - нету. тогда бы сбои были систематическими, а у меня они в разное время происходят, порой после 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] почему то приводит к сбоям Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба Ничего не понял. Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК. Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-) Кто такой BuffUART[2] вообще неясно. Если он нигде не анализируется, на выполнение программы влиять он не должен никак. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба uart вообще может мусор с линии принимать, тем более на больших скоростях. Как минимум нужна синхронизация по началу кадра и crc данных кадра Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба Ничего не понял. Данные из датчиков попадают в два разных массива, переключение между массивами - по команде с ПК. Два этих процесса не синхронизированы. Так почему же оно почти всегда работает? :-) Кто такой BuffUART[2] вообще неясно. Если он нигде не анализируется, на выполнение программы влиять он не должен никак. Даа не так. Данные приходят с датчиков на STM32, он по UART передает на C8051F320, а тот передает по USB. Чтобы вычленить проблему, я данные с датчиков вообще не трогаю. А по запросу от C8051F320 передаю ему фиксированный массив из 19 байт. И если меняю значение BuffUART[2], то получаю сбои. Если он нигде не анализируется, на выполнение программы влиять он не должен никак. вот именно! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
walsv 0 27 октября, 2015 Опубликовано 27 октября, 2015 · Жалоба А ты не рассматривал вариант что когда когда ты переключаешь 74HC126D на уарт пролазит байт нулевой, попробуй после каждого переключения очищать аппаратный буфер уарта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться