реклама на сайте
подробности

 
 
> Мост между юсартами, STM32F205, usart2 - usart3
Volldemar
сообщение Mar 19 2014, 05:09
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342



Задача: по юсарт2 идут данные с темпом 1 сек, но разного объёма, типа:
Код
$GPRMC,074038.00,A,4912.3940,N,03151.9618,E,00.00,314.7,190314,,,A*59
$GPGSV,4,1,14,01,39,183,24,04,20,314,00,11,12,181,00,13,27,237,29*7F
$GPGSV,4,2,14,17,17,275,01,20,86,111,18,23,63,242,45,25,05,022,00*7C
$GPGSV,4,3,14,31,39,059,00,32,44,102,00,33,18,235,00,37,33,193,00*7F
$GPGSV,4,4,14,39,33,189,00,40,29,150,00*7D

эти данные нужно обрабатывать и выдавать в юсарт3.

Как задумывалось решение:
Настраиваю аппаратный таймер (ТИМ2) на длительность передачи одного байта при скорости 115200. В прерывании юсарт2 принятые байты складываю в массив и обнуляю ТИМ2:
Код
if( USART_GetITStatus( USART2, USART_IT_RXNE ) == SET )
      {
         cChar = USART_ReceiveData( USART2 );
         if ((USART2_Idx == USART2_SIZE-1) || (cChar == '$'))
            {
               USART2_Idx = 0;
            }
         USART2_Buf[USART2_Idx] = cChar;
         USART2_Idx++;
         TIM_SetCounter(TIM2, 0);
         TIM_Cmd(TIM2, ENABLE);
      }

В прерывании ТИМ2, если он таки досчитает до конца, значит байтов больше нет, выставляю семафор:
Код
void TIM2_IRQHandler(void)
{
   portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

   if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
      {
         TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //Очищаем бит обрабатываемого прерывания
         TIM_Cmd(TIM2, DISABLE); //выключаю таймер
         xSemaphoreGiveFromISR (xSemaphore_usart2, &xHigherPriorityTaskWoken ); //семафорим задаче
      }
}

Ну и сама задача:
Код
   for(;; )
   {
      xSemaphoreTake(xSemaphore_usart2, portMAX_DELAY );
      for (i=0; i<USART2_Idx; i++)
         {
            cChar = USART2_Buf[i];
            xQueueSend( usart3_TxQueue, &cChar, xNoBlock );
         }
      USART2_Idx = 0;
      USART_ITConfig( USART3, USART_IT_TXE, ENABLE );
   }

Вопрос, что не так делаю, но выдача в юсарт3 происходит не стабильно, может в принципе построение решения не правильное? Надеюсь на конструктивное советы и пожелания wink.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 10)
Genadi Zawidowsk...
сообщение Mar 19 2014, 05:17
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Поможет? Посимвольный приём. В некоторых местах форумный движок заменил латинский символ ЦЕ в скобочках на какую-то хрень.
CODE
static uint_fast8_t nmea_state = NMEAST_INITIALIZED;
static uint_fast8_t nmea_checksum;
static uint_fast8_t nmea_chsval;
static uint_fast8_t nmea_param; // номер принимаемого параметра в строке
static uint_fast8_t nmea_chars; // количество символов, помещённых в буфер

#define NMEA_PARAMS 20
#define NMEA_CHARS 12 // really need 11
static char nmea_buff [NMEA_PARAMS] [NMEA_CHARS];
static timeholder_t nmea_time;
static timeholder_t th;
static volatile uint_fast8_t secoundticks;

static unsigned char hex2int(uint_fast8_t c)
{
if (isdigit©)
return c - '0';
if (isupper©)
return c - 'A' + 10;
if (islower©)
return c - 'a' + 10;
return 0;
}

static void nmea_parsrchar(uint_fast8_t c)
{

switch (nmea_state)
{
case NMEAST_INITIALIZED:
if (c == '$')
{
nmea_checksum = '*';
nmea_state = NMEAST_OPENED;
nmea_param = 0; // номер принимаемого параметра в строке
nmea_chars = 0; // количество символов, помещённых в буфер
}
break;

case NMEAST_OPENED:
nmea_checksum ^= c;
if (c == ',')
{
// закрываем буфер параметра, переходим к следующему параметру
nmea_buff [nmea_param][nmea_chars] = '\0';
nmea_param += 1;
nmea_chars = 0;
}
else if (c == '*')
{
// закрываем буфер параметра, переходим к следующему параметру
nmea_buff [nmea_param][nmea_chars] = '\0';
nmea_param += 1;
// переходим к приёму контрольной суммы
nmea_state = NMEAST_CHSHI;
}
else if (nmea_param < NMEA_PARAMS && nmea_chars < (NMEA_CHARS - 1))
{
nmea_buff [nmea_param][nmea_chars] = c;
nmea_chars += 1;
//stat_l1 = stat_l1 > nmea_chars ? stat_l1 : nmea_chars;
}
else
nmea_state = NMEAST_INITIALIZED; // при ошибках формата строки
break;

case NMEAST_CHSHI:
nmea_chsval = hex2int© * 16;
nmea_state = NMEAST_CHSLO;
break;

case NMEAST_CHSLO:
nmea_state = NMEAST_INITIALIZED;
if (nmea_checksum == (nmea_chsval + hex2int©))
{
if (nmea_param > 2 &&
strcmp(nmea_buff [0], "GPRMC") == 0 &&
strcmp(nmea_buff [2], "A") == 0 &&
1)
{
// разбор времени
const char * s = nmea_buff [1]; // начало буфера, где лежит строка времени.формата 044709.00 или 044709.000
nmea_time.hours = (s [0] - '0') * 10 + (s [1] - '0');
nmea_time.minutes = (s [2] - '0') * 10 + (s [3] - '0');
nmea_time.secounds = (s [4] - '0') * 10 + (s [5] - '0');
nmea_time.ms = 0; //strtoul(s + 7, NULL, 10);
time_next(& nmea_time); // какое время надо будет поставить для установки в следующий PPS
}
}
break;
}
}


Сообщение отредактировал Genadi Zawidowski - Mar 19 2014, 05:19
Go to the top of the page
 
+Quote Post
Volldemar
сообщение Mar 19 2014, 05:42
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342



Да, спасибо, надеюсь поможет, но это уже следующий этап, парсинг предложений, пока нужно наладить пересылку через массив, а потом разбор и модификация этого массива.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Mar 19 2014, 06:15
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



А вы только получив строку - начинающуюся с доллара и с правильной контрольной суммой - передавайте её. Запоминать компоненты не требуется... Как дополнительный бонус - неправильные строки не передадутся через мост.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Mar 19 2014, 12:04
Сообщение #5


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Volldemar @ Mar 19 2014, 09:09) *
...Настраиваю аппаратный таймер (ТИМ2) на длительность....построение решения не правильное? Надеюсь на конструктивное советы и пожелания wink.gif


ВЫ как-то маловато таймеров задействовали. Надо было на каждый символ завести sm.gif

А если по теме.
ПДП отменили ужо? Если Вам не парсить нифига - то там три участника тока USART, USART, DMA
мозги отдыхают. не Ваши имеются ввиду а мк...
Go to the top of the page
 
+Quote Post
Volldemar
сообщение Mar 19 2014, 12:21
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342



Цитата(kolobok0 @ Mar 19 2014, 14:04) *
ВЫ как-то маловато таймеров задействовали. Надо было на каждый символ завести sm.gif

А если по теме.
ПДП отменили ужо? Если Вам не парсить нифига - то там три участника тока USART, USART, DMA
мозги отдыхают. не Ваши имеются ввиду а мк...

Чуть выше писал следующее:
Цитата
Да, спасибо, надеюсь поможет, но это уже следующий этап, парсинг предложений, пока нужно наладить пересылку через массив, а потом разбор и модификация этого массива.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 19 2014, 16:15
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Volldemar @ Mar 19 2014, 18:21) *
Чуть выше писал следующее:

Вам советуют здравые вещи, а вы игнорите. Зачем тогда совета спрашиваете?
Как уже пытались вам сказать выше, у вас два пути:
1. Тупо получить на UART3 копию принимаемого с UART2: просто в ISR UART2 пишите каждый принятый байт в UART3, и параллельно -
кладите в буфер для последующей обработки в фоне (буфер должен быть кольцевой!). Никаких таймеров конечно не нужно. Пинговать
фоновую задачу - по событию таймаута принимаемых данных в RBR UART2 (не знаю есть-ли оно в STM? если нет - по любому принятому
символу).
2. Более правильный и прямой: передавать сообщения на UART3 только после протокольной обработки (фоновой задачей). В этом
случае (опционально) можно отсекать все невалидные сообщения как предлагал Genadi Zawidowski.

Вообще не айс использовать высокочастотные прерывания (~11.5кГц) для такой ерунды. Учитесь использовать буферизацию в железе
(FIFO UART, или DMA для МК типа STM без такого FIFO).

Цитата(Volldemar @ Mar 19 2014, 11:09) *
Вопрос, что не так делаю, но выдача в юсарт3 происходит не стабильно, может в принципе построение решения не правильное? Надеюсь на конструктивное советы и пожелания wink.gif

И делаете не так и в принципе построение неверное sm.gif
1. Почему Вы решили, что посылки входящие на UART2 идут без пауз между байтами?
2. Построение и работа с кольцевым буфером неправильная (для случая взаимодействия ISR с фоновой задачей), соответственно - и с семафором ОС тоже.
3. Зачем-то смешана обработка протокола в ISR и в фоновой задаче (вся протокольная обработка желательно должна делаться в одном месте).
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 19 2014, 16:20
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



я правда не очень понимаю зачем таймер.

Я бы завел циклический входной буффер, все входящее добавлял бы в него по поступлению, а как есть время все что там есть выдавливал бы дальше, зачем отслеживать конец сообщения? А если на уартах есть FIFO, то даже буфера бы не делал бы.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 19 2014, 16:21
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(kolobok0 @ Mar 19 2014, 18:04) *
ВЫ как-то маловато таймеров задействовали. Надо было на каждый символ завести sm.gif

Здесь в ветке нужен робот-парсер, который будет все посты с использованием таймеров перемещать в "Чайник"
Имхо: неуёмное использование таймеров где ни попадя - яркий признак чайника. cool.gif
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 19 2014, 16:26
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Код
(вся протокольная обработка желательно должна делаться в одном месте)

и хорошим тоном будет если вне обработчика прерывания.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 19 2014, 17:33
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Golikov A. @ Mar 19 2014, 22:26) *
и хорошим тоном будет если вне обработчика прерывания.

Если понимаешь что делаешь (с учётом: минимального интервала между 2-мя прерываниями; соответствующим приоритетом данного
прерывания; максимальной длительностью запретов прерываний во всём ПО и макс. длительностью работы более приритетных ISR и т.п.),
то почему-бы и нет? Тем более, что парсер кадров протокола обмена внутри ISR может значительно снизить требования по требуемому
объёму ОЗУ под буфер, что часто весьма критично.
По-крайней мере я частенько делаю парсеры простых протоколов обмена в ISR. Что очень помогает уменьшить требования по ОЗУ для
кадр-ориентированных протоколов с чем-нить типа байт-стаффинга.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 16:53
Рейтинг@Mail.ru


Страница сгенерированна за 0.01458 секунд с 7
ELECTRONIX ©2004-2016