crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Прием данных из последовательного порта, Некая смесь Си для AVR и QT
x-8973
  опции профиля:
сообщение 15.6.2014, 17:50
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 25
Регистрация: 22.2.2013
Пользователь №: 3720

Спасибо сказали: 0 раз(а)




Репутация:   0  


Вечер добрый всем здешним обитателям!
Проблема моя затрагивает программирование для микроконтроллеров, но на решение данный факт, я надеюсь, никак не влияет. Итак:
Есть последовательный порт на микроконтроллере. Имеется прерывание, которое генерируется при приеме портом байта данных. Есть возможность получить этот байт. Нужно принять пакет данных, который состоит из нескольких байт (длина пакета может быть разной).
Пакет представляет из себя заголовок (признак начала 0xAEAE, идентификатор пакета, длина пакета) длиной 4 байта, и собственно данные.
Примерный алгоритм я себе представляю так:
-принимать данные, пока длина буфера в массиве char не станет равна 4.
-поискать в буфере признак начала пакета
-если признак найден, выбросить байты, что слева от него, иначе очистить буфер и выйти из прерывания
-если длина пакета принята, то прочитать ее и принимать данные, пока не наберется нужное количество байт, иначе принимать данные, пока не будет принята длина пакета
-если принято нужное количество байт, то передать буфер на обработку.

Для ПК я этот алгоритм реализовал с использованием классов QT, в частности, QByteArray. А вот для МК ничего придумать не могу. Натыкаюсь на то, что массив char есть именно массив. А QByteArray - класс, имеющий методы для поиска, "обрезки" и прочих насущных дел.
Может быть, кто поможет мне в этом деле? Код QT прилагаю.

void Widget::SlotDataRead()
{
    int bytes = port->bytesAvailable();
    dataBuffer.append(port->read(bytes));
    quint16 startSeq = 0xAEAE;
    int startPos = dataBuffer.indexOf(QByteArray((char*)&startSeq));
    if (startPos > -1)
    {
        dataBuffer = dataBuffer.remove(0, startPos);
        if (startPos+3 <= dataBuffer.count())
        {
            dataPacketLength = dataBuffer.at(startPos+3);
            if (dataBuffer.count() >= dataPacketLength)
            {
                receivedDataProc(dataBuffer.left(dataPacketLength));
                dataBuffer = dataBuffer.remove(dataPacketLength);
            }
        }
    }
    else
        dataBuffer.clear();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.6.2014, 23:44
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Ну я бы делал через кольцевой буфер например.
Надо просто реализовать все необходимые операции:
append, indexOf, remove, left, at, count, clear
Что то вроде:
char data[MAX_SIZE];
struct buf {
   int head;
   int tail;
}

void init( struct buf * b ) {
  b->head = b->tail = 0;
}

void append( struct buf * b, char d  ) {
  data[b->tail] = d;
  b->tail = (b->tail + 1) % MAX_SIZE;
}
...

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
x-8973
  опции профиля:
сообщение 16.6.2014, 4:13
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 25
Регистрация: 22.2.2013
Пользователь №: 3720

Спасибо сказали: 0 раз(а)




Репутация:   0  


Правильно говорят, что утро вечера мудренее) За ночь я все придумал)
От порта приходит по одному байту, а это значит, что мне не нужны всякие методы типа left, indexOf и прочие. Я всегда могу проверить, что за байт пришел, простым условием, и просто выбросить его, если он не тот, что нужен. lanz, спасибо за помощь, и простите за беспокойство)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 16.6.2014, 13:56
Сообщение #4


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

Группа: Модератор
Сообщений: 1609
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


на будущее: в обработчике прерывания обычно ничего не делается, кроме минимума для сохранения данных и выставления флагов. отдельно делается основной цикл (как правило, на таймере), который обрабатывает флаги, выставленные обработчиками прерываний. в обработчиках что-либо делать некрасиво, а иногда и физически невозможно: поток может быть неравномерный, а мощная обработка может занять слишком много времени.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JohnZ
  опции профиля:
сообщение 1.8.2014, 20:02
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


Цитата(x-8973 @ 16.6.2014, 4:13) *
Правильно говорят, что утро вечера мудренее) За ночь я все придумал)
От порта приходит по одному байту, а это значит, что мне не нужны всякие методы типа left, indexOf и прочие. Я всегда могу проверить, что за байт пришел, простым условием, и просто выбросить его, если он не тот, что нужен.


Не совсем так. Iron Bug сказал правильно, только хочу добавить, - в цикле проверяй флажок кол-ва принятых байт,
и когда их >= 4, можно начинать проверять что пришло в прерывании, инициализировать длинну принимаемого пакета,
и если длинна совпала, значит принят весь пакет.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


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




RSS Текстовая версия Сейчас: 27.5.2022, 2:15