Модераторы: PILOT, ManiaK, Mazzi

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Приём строки по USART [STM32] Keil5 
V
    Опции темы
supercelt
Дата 5.1.2017, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Привет!. Помогите пожалуйста. Для вас это наверное расплюнуть, а у меня непонятки. Пишу код в Keil под stm32. Есть модуль, от которого по usart приходит строка вот такого вида:
Код

r\n\
+CMGR: "993848",145
r\n\
r\n\
OK


Цель: выделить всё что между кавычек. Я так поразмыслил это можно делать 2 способами. 

Первый:
Это кусок кода в файле mod.c где и крутится всё что касается модуля.

Код

char buffer[];
uint8_t i;

void USART1_IRQHandler(void){ //Прерывание USART1
        if(USART1->SR & USART_SR_RXNE){ //Если прерывание вызвано по приёму USART1
                USART1->SR &= ~USART_SR_RXNE; //Сбрасываем флаг приёма USART1
                flag_receive = 1;
        }
}

void Get(){
buffer[i++] = USART1->DR;
}


Здесь стандартно по прерыванию приёма я сбрасываю флаг, устанавливаю флаг, что я готов записать принятый байт и быстро ухожу. В самом прерывании я не стал записывать в переменную содержание регистра DR ибо сами знаете делать что-то в прерывании не комильфо.
значит флаг flag_receive установился и далее в цикле while файла main.c:
if(flag_receive){
Get();
flag_receive = 0;
}
Далее вызываем Get и всё складируется в buffer. Далее с помощью регулярки выдернуть всё что между кавычек.

Вариант 2

Код

char buffer;
char str[];

void Get(){
    uint8_t f;
    buffer = USART1->DR;
    if(f){
        str[i++] = buffer;
    }
    if(buffer == """){
        if(f){
            f = 0;
        } else {
            f = 1;
        }
    }
}


То есть вытягиваем нужную строку непосредственно в процессе приёма байтов посимвольно. 
В коде могут быть ошибки, так как хотел показать идею.
А теперь главные вопросы
Если сначала набивать массив строкой, а потом разбирать регуляркой, как написать эту самую регулярку, что бы между кавычек вытащить?
И второй вопрос, что будет работать быстрее и эффективнее 1 или 2 вариант?
PM   Вверх
Romikgy
Дата 6.1.2017, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7325
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 3
Всего: 146



Цитата(supercelt @  5.1.2017,  15:12 Найти цитируемый пост)
 ибо сами знаете делать что-то в прерывании не комильфо.

кто такую чушь сказал? особенно у стм32??? 
все и складывают в прерывании в отдельный буфер


Цитата(supercelt @  5.1.2017,  15:12 Найти цитируемый пост)
И второй вопрос, что будет работать быстрее и эффективнее 1 или 2 вариант? 

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


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Курсант
Дата 10.1.2017, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Регвыр на МК применять, ИМХО, слишком круто, хотя для кругозора можно повозиться.
Не соглашусь с тем, что нужно заполнять буфер. Можно использовать конечный автомат для управления распознаванием символов.
Состояний у конечного автомата будет 11:
1. Ожидание \r (начальное состояние). После прихода \r переходим в состояние 2.
2. Ожидание \n (после прихода \n переходим в состояние 2, иначе в состояние 1)
3. Ожидание + (в случае прихода \r переходим в состояние 2, иначе в состояние 1)
4. Ожидание C (после C переходим в состояние 5, после \r - в состояние 2, иначе в состояние 1)
5. Ожидание M
6. Ожидание G
7. Ожидание R
8. Ожидание :
9. Ожидание <пробела>
10. Ожидание "
11. Ввод значения (можно проверять символы на принадлежность к цифрам и сразу преобразовывать в int). После прихода " возвращаем полученное значение функции-абоненту и переходим в состояние 1. Если приходит не цифра, и не ", сбрасываем накопленное значение и переходим в состояние 1.)

PM ICQ Skype   Вверх
baldman88
Дата 10.1.2017, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Все не так просто. В данном случае выгоднее сделать циклический буфер и уже парсить данные, полученные из него.
PM MAIL   Вверх
Курсант
Дата 10.1.2017, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Цитата(baldman88 @ 10.1.2017,  23:23)
Все не так просто. В данном случае выгоднее сделать циклический буфер и уже парсить данные, полученные из него.

Много подводных камней. Во-первых, нужно своевременно опустошать буфер (или считывать его), хотя это не проблема. Проблема в том, что парсить данные нужно по мере готовности, т.е. после прихода закрывающей кавычки. Слишком много условностей. Конечный автомат, ИМХО, простое и надёжное решение, приспособленное к формату входных данных. Я не скажу, что это более простое решение. С точки зрения кода оно менее очевидное. Но оно быстрее и надёжнее.
По сути, Вы делаете функцию парсинга, принимающую один единственный символ:

Код

char result[20];

typedef enum {
WAIT_FOR_NEW,
WAIT_FOR_RET,
WAIT_FOR_PLUS,
WAIT_FOR_C,
WAIT_FOR_R,
WAIT_FOR_G,
WAIT_FOR_M,
WAIT_FOR_20,
WAIT_FOR_KAV,
WAIT_FOR_NUMBERS
} ParseCharStates;

void ParseChar ( char In ) {// Функция посимвольного парсинга строки. Может вызываться из прерывания при приходе символа, либо при заполнении буфера (тогда функция вызывается до опустошения буфера)
    static int mode = WAIT_FOR_NEW;
    static int CharIndex = 0;
    switch (mode) {
    case WAIT_FOR_NEW:
        if ( In == "\n") mode = WAIT_FOR_RET;
    case WAIT_FOR_RET:
        if ( In == "\r") mode = WAIT_FOR_PLUS;
    else if ( In == "\n") mode = WAIT_FOR_RET;
        else mode = WAIT_FOR_NEW;
    case WAIT_FOR_PLUS:
        if ( In == "+" ) mode = WAIT_FOR_C;
    else if ( In == "\n") mode = WAIT_FOR_RET;
        else mode = WAIT_FOR_NEW;
    ...
    case WAIT_FOR_KAV:
        if ( In == "\"" ) mode = WAIT_FOR_NUM;
    else if ( In == "\n") mode = WAIT_FOR_RET;
        else mode = WAIT_FOR_NEW;
    case WAIT_FOR_NUM:
        if ( In == "\"" ) {
            mode = WAIT_FOR_NEW;
            result[CharIndex]="\0";
            CharIndex = 0;
            RecognitionIsOver (); // Функция - обработчик распознанного значения. Уведомляет функцию-абонент о том, что значение распознано. Функция абонент вызывается периодически и проверяет флаг 
//распознанного сообщения
        }
        else {
            result[CharIndex] = In;
            CharIndex++;
        }
    }
}


Это сообщение отредактировал(а) Курсант - 11.1.2017, 00:36
PM ICQ Skype   Вверх
baldman88
Дата 11.1.2017, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Цитата(Курсант @ 10.1.2017,  23:35)
Проблема в том, что парсить данные нужно по мере готовности, т.е. после прихода закрывающей кавычки.

Я, наверное, параноик (видимо, работая с военными это нормальное состояние), но гарантии, что придет именно кавычка, нет. Тогда может возникнуть ситуация, что в качестве закрывающей будет воспринята открывающая из следующего сообщения (вероятность крайне низка, но такое может случиться!). Нужно предусмотреть сброс автомата в начальное состояние. Именно поэтому целесообразнее иметь буфер (и проверять его после прихода нового символа). И вот здесь использование конечного автомата очень даже оправдано (получили символ, прошлись по буферу -- если все в порядке, то выделили нужное значение, и при новом вызове автомат всегда находится в начальном состоянии).
Пы.Сы.: ТС, скорее всего, неправильно поставил слеши -- они должны идти перед r и n. Да и первая строка, по идее, должна идти уже после пятой.
PM MAIL   Вверх
Курсант
Дата 11.1.2017, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Цитата(baldman88 @ 11.1.2017,  12:26)
Цитата(Курсант @ 10.1.2017,  23:35)
Проблема в том, что парсить данные нужно по мере готовности, т.е. после прихода закрывающей кавычки.

Я, наверное, параноик (видимо, работая с военными это нормальное состояние), но гарантии, что придет именно кавычка, нет. Тогда может возникнуть ситуация, что в качестве закрывающей будет воспринята открывающая из следующего сообщения (вероятность крайне низка, но такое может случиться!). Нужно предусмотреть сброс автомата в начальное состояние. Именно поэтому целесообразнее иметь буфер (и проверять его после прихода нового символа). И вот здесь использование конечного автомата очень даже оправдано (получили символ, прошлись по буферу -- если все в порядке, то выделили нужное значение, и при новом вызове автомат всегда находится в начальном состоянии).
Пы.Сы.: ТС, скорее всего, неправильно поставил слеши -- они должны идти перед r и n. Да и первая строка, по идее, должна идти уже после пятой.

Как только в режиме чтения строки придёт любой символ из \r или \n, автомат сбросится и буфер обнулится. Ну, должен обнулиться, по крайней мере, возможно я забыл его обунлить, т.к. код иллюстративный, а не точный.
Я, кстати, как раз хотел эту саму закрывающую кавычку Вам в качестве аргумента предложить. Т.е. Вам придётся парсить всю строку при каждом пришедшем символе.
Более того, у нас один коллега реализовывал обмен по COM-порту как раз с помощью буфера и парсинга строк. Работает, вроде, но бывает что команды игнорирует, приходится повторно отправлять с компа.
PM ICQ Skype   Вверх
supercelt
Дата 15.1.2017, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



В продолжении вопроса. Выделить из кавычек это я поторопился. Надо сначала ещё кучу всего сделать. Там условия такие, что строка может придти когда угодно, какая угодно. Я не знаю ее размер. Таким образом я решил что по мере поступления символов, а прерывании по usart1 я буду просто набивать буфер. А потом, когда он набьётся - разбирать строку. И вот проблема. Раз я не знаю размер строки, то когда она полностью придёт неизвестно. Проверять по символу \r\n не вариант, так как эти символы приходят вначале сообщения и в середине. Короче я думал думал и вот что придумал. Алгоритм такой:

После того, как сработало первое прерывание по приёму usart1, я запускаю таймер. Настраиваю его на прерывание по переполнению. Далее приходит второй символ, таймер сбрасываю, он не успевает переполнится. И так далее. И вот пришёл последний символ. прерывание сработало последний раз и сбросило таймер. Он продолжает тикать. А раз символов то больше нет, он благополучно вваливается в прерывание по переполнению. В обработчике вектора вырубаю таймер и выставляю флаг что я принял всё-таки строку. Алгоритм простой, но как всегда всё работает почему-то не так как надо. Если из кода, который ниже убрать включение прерывание на таймер, то работает, но таймер соответственно не останавливается. А если включить прерывание, что так и должно быть - ничего не работает. Похоже даже на зависание. И самое интересное. Что бы я не делал, в режиме отладки, на кусок кода обработчика прерывания таймера нельзя поставить точку останова. Везде можно а именно на этот кусок нельзя.

Код

#include "gsm.h"
#include "lcd.h"
/////////////////////////////////////////////Buffer сделать c префиксом сетап. Может набить туда ещё команд? сделать вывод со 2 юсарта на комп, дублиовать экран на комп
char Buffer_CSCA[] = "AT+CSCA?\r\n";
char Buffer_Setup[] = "ATE0\r\n";//ATV0, ATE0, ATS4=000
char Buffer_Receive[100];
uint8_t flag_receive, buf, flag_setup, i, f, ex;
uint16_t co;
unsigned short buff[100];

void TIM12_IRQHandler(void){
        if(TIM12->SR & TIM_SR_UIF){ 
                TIM12->SR &= ~TIM_SR_UIF;
        }
        flag_receive = 1;
        TIM12->CNT = 0;
        TIM12->CR1 &= ~TIM_CR1_CEN;
}

void DMA1_Channel4_IRQHandler(void){ //Прерывание DMA
        if(DMA1->ISR & DMA_ISR_TCIF4){ //Если прерывание вызвано завершением передачи...
                DMA1->IFCR = DMA_IFCR_CTCIF4; //Сброс флага завершения передачи
                DMA1_Channel4->CCR &= ~DMA_CCR4_EN; //Вырубаем DMA
        }
}

void USART1_IRQHandler(void){ //Прерывание USART1
        if(USART1->SR & USART_SR_RXNE){ //Если прерывание вызвано по приёму USART1
                USART1->SR &= ~USART_SR_RXNE; //Сбрасываем флаг приёма USART1
                buff[i] = TIM12->CNT;
                Buffer_Receive[i++] = USART1->DR;
                LCD_Send_Data(USART1->DR);
                                if(!f){
                                        TIM12->CR1 |= TIM_CR1_CEN;
                                        f = 1;
                                } else {
                                        TIM12->CNT = 0;
                                }
        }
}


void GSM_INI(void){
        RCC->APB2ENR |= RCC_APB2ENR_USART1EN;                           //USART1 clock
        RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;        //PortA & Alt clock
        GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
        GPIOA->CRH |= GPIO_CRH_CNF9_1;                                                                    //Alternate function output Push-pull
        GPIOA->CRH |= GPIO_CRH_MODE9_1;                                                                //Speed 2 MHz
    
        /*RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //Test usart2
        GPIOA->CRL &= ~GPIO_CRL_CNF2_0; //Test usart2
        GPIOA->CRL |= GPIO_CRL_CNF2_1; //Test usart2
        GPIOA->CRL |= GPIO_CRL_MODE2_1; //Test usart2*/
    
//==USART1=======================================================================================    
        USART1->BRR = 0x9C4; //9600 бод скорость обмена
        USART1->CR1 |= USART_CR1_RXNEIE; //Разрешаем локальные прерывания по приёму USART
        USART1->CR1 |= USART_CR1_RE | USART_CR1_TE; //Включаем передатчик и приёмник
        USART1->CR1 |= USART_CR1_UE; //Включаем USART
      NVIC_EnableIRQ(USART1_IRQn); //Разрешаем глобальные прерывания для USART1
//==============================================================================================
    
//==USART2=[TEST]===============================================================================
        /*USART2->BRR = 0x9C4;
        USART2->CR1 |= USART_CR1_TE;
        USART2->CR1 |= USART_CR1_UE;*/
//==============================================================================================    

//==DMA=========================================================================================
        RCC->AHBENR |= RCC_AHBENR_DMA1EN;
        DMA1_Channel4->CPAR = (uint32_t)&(USART1->DR); //С какой периферией работаем
        DMA1_Channel4->CMAR = (uint32_t)Buffer_Setup; //Указатель на нулевой элемент буфера откуда отправляем данные
        DMA1_Channel4->CCR |= DMA_CCR4_DIR | DMA_CCR4_MINC; //Читаем ИЗ памяти в периферию | при считывании увеличиваем на 1 адрес буфера Buffer, что бы при следующем считывани перейти на след ячейку памяти.
        DMA1_Channel4->CCR &= ~DMA_CCR4_PINC; //Увеличение на 1 адрема периферии выкл. Если вкл, то счётчик увеличится при след. чтении и тогда работа будет уже не с юсарт а с другой периферией
        DMA1_Channel4->CCR |= DMA_CCR4_TCIE;
        DMA1_Channel4->CNDTR = sizeof(Buffer_Setup); //Размер буфера данных
        DMA1_Channel4->CCR &= ~(DMA_CCR4_MSIZE | DMA_CCR4_PSIZE | DMA_CCR4_CIRC); //Память - 8 бит | Периферия - 8 бит | Не циклическая передача.
        DMA1_Channel4->CCR |= DMA_CCR4_PL_0; //Приоритет - средний (Medium)
        USART1->CR3 |= USART_CR3_DMAT; // Разрешаем USART использовать DMA
        NVIC_EnableIRQ(DMA1_Channel4_IRQn); //Разрешаем глобально прерывания по DMA1 канал 4
        DMA1_Channel4->CCR |= DMA_IT_TC; //Разрешаем локальнве прерывания по завершению передачи DMA1 канал 4
        DMA1_Channel4->CCR |= DMA_CCR4_EN; //Включаем DMA что бы передать настройки модулю GSM командой из Buffer
//==============================================================================================    

//==TIMER12=for=receive bytes from USART========================================================
        RCC->APB1ENR |= RCC_APB1ENR_TIM12EN;
        TIM12->CR1 |= TIM_CR1_ARPE;
        TIM12->ARR = 0xFFFF;
        TIM12->PSC = 0xEF;
        TIM12->CNT = 0;
        NVIC_EnableIRQ(TIM12_IRQn);
        TIM12->DIER |= TIM_DIER_UIE;
        TIM12->EGR = TIM_EGR_UG;      //******Вызываем Update Event что бы таймер не уходил в прерывание сразу после старта
        __NOP();                                            //
        __NOP();                                            //
        TIM12->SR &= ~(TIM_SR_UIF);    //****************************
        //TIM16->CR1 |= TIM_CR1_CEN;
//==============================================================================================
//
//В инициализации сделать поочерёдную отправку команд настроек и получение ответов с выводом сообщений на экран. Т.е. Постали - получили -вывели. След ком. послали получили вывели.
//поменять 16 таймер на другой, не совмещенный по векторам ни с каким другим

}

void GSM_COMM_SEND_SMS_SERVICE(){
        DMA1_Channel4->CMAR = (uint32_t)Buffer_CSCA;
        DMA1_Channel4->CNDTR = sizeof(Buffer_CSCA);
        DMA1_Channel4->CCR |= DMA_CCR4_EN;
}

void GSM_COMM_GET_SMS_SERVICE(){
        buf = USART1->DR;
        LCD_Send_Data(buf);
        
        //while(!(USART2->SR & USART_SR_TC)); //Ждем пока бит TC в регистре SR станет 1
        //USART2->DR = buf;
}
//---------------------------------------------------------------


PM   Вверх
Курсант
Дата 15.1.2017, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Вы не знаете чем набьётся буфер. ИМХО, если Вы не знаете максимальный размер того, что приходит между кавычек, Вы не можете гарантированно распознать строку - это раз. В буфер может набиться и две команды, и три, и две с половиной, что тогда? Две выполните, третью выкинете? А потом в следующем прерывании получите закрывающую кавычку от третьей команды и распознаете её как открывающую кавычку, и "съедите" кракозяблы.

Говорите точно, что за строки. Если они как-то описываются, то можно говорить об алгоритме. Если данные на входе не поддаются никакому описанию, то и обработке они не поддаются... Разве только через самообучающуюся нейросеть smile
PM ICQ Skype   Вверх
supercelt
Дата 16.1.2017, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Цитата(Курсант @ 15.1.2017,  23:28)
Вы не знаете чем набьётся буфер. ИМХО, если Вы не знаете максимальный размер того, что приходит между кавычек, Вы не можете гарантированно распознать строку - это раз. В буфер может набиться и две команды, и три, и две с половиной, что тогда? Две выполните, третью выкинете? А потом в следующем прерывании получите закрывающую кавычку от третьей команды и распознаете её как открывающую кавычку, и "съедите" кракозяблы.

Говорите точно, что за строки. Если они как-то описываются, то можно говорить об алгоритме. Если данные на входе не поддаются никакому описанию, то и обработке они не поддаются... Разве только через самообучающуюся нейросеть smile

Понимаете, разбор строки это как оказалось уже 2 шаг. Я застрял на первом. Неважно что пришло, и сколько размером набился буфер. Мне надо просто отследить когда в usart перестали поступать данные с момента начала. Прикрути  таймер, но эта штука не особо то и работает.
PM   Вверх
baldman88
Дата 16.1.2017, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Цитата(supercelt @ 16.1.2017,  21:13)
Цитата(Курсант @ 15.1.2017,  23:28)
Вы не знаете чем набьётся буфер. ИМХО, если Вы не знаете максимальный размер того, что приходит между кавычек, Вы не можете гарантированно распознать строку - это раз. В буфер может набиться и две команды, и три, и две с половиной, что тогда? Две выполните, третью выкинете? А потом в следующем прерывании получите закрывающую кавычку от третьей команды и распознаете её как открывающую кавычку, и "съедите" кракозяблы.

Говорите точно, что за строки. Если они как-то описываются, то можно говорить об алгоритме. Если данные на входе не поддаются никакому описанию, то и обработке они не поддаются... Разве только через самообучающуюся нейросеть smile

Понимаете, разбор строки это как оказалось уже 2 шаг. Я застрял на первом. Неважно что пришло, и сколько размером набился буфер. Мне надо просто отследить когда в usart перестали поступать данные с момента начала. Прикрути  таймер, но эта штука не особо то и работает.

Вам шашечки или ехать? Для начала попробуйте конкретизировать задачу. Что, конкретно, не получилось с таймером? И как он может помочь в изначальном вопросе?
PM MAIL   Вверх
supercelt
Дата 19.1.2017, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Что с таймером. Вобщем в отладчике ставлю точки остановки на прерывании у таймера и юсарта. Запускаю. И самый первый раз останавливаемся на метке таймера. При том что таймер выключен. По сути получается якобы алгоритм отработал, выключил таймер TIM12->CR1 &= ~TIM_CR1_CEN; Но по задумке, повторю ещё раз: -Срабатывает первое прерывание по принятому байту юсарта
-Набиваем буфер
-Если это первое прерывание, то запускаем таймер, если не первое, то обнуляем таймер.
-Далее принимаются байты, счётчик сбрасывается, таймер не успевает переполняться.
-Затем данные кончились, таймер никто не обнулил, он продолжает считать и досчитывает до топа и переполняется. 
-Вваливаемся в вектор по переполнению. Выключаем таймер, ставим флаг что набили буфер. 

А в отладчике. Первое куда мы приходим это вектор таймера. А должно быть - юсарт. 
И ещё одна странность. По отладчику видно, что приём одного байта занимает примерно 80 тиков таймера. Для наглядности я ставил ARR = 0xFFFF. Завязывал на полную. НО если я поставлю например 20000 тиков, то кол-во тиков между прерываниями приёма юсарта будет уже не 80, а допустим 2000. По идее ARR же  никак не должно влиять на количество тиков между прерываниями, ведь до конца все-равно не досчитываем. 
PM   Вверх
baldman88
Дата 19.1.2017, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Я бы не стал на 100% доверять эмулятору. Особенно если уже до этого были проблемы и неточности с его работой.
Насколько я понял, то сообщения от устройства у Вас приходят не очень часто, и Вы хотите использовать таймер именно для определения того, что сообщение уже пришло? Не самый удачный алгоритм. Скорее -- совсем неудачный (если заранее известен формат сообщений от устройства).
PM MAIL   Вверх
supercelt
Дата 20.1.2017, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



А если неизвестен? то кроме таймера есть ещё шустрые варианты?
PM   Вверх
Курсант
Дата 21.1.2017, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Ещё вариант - запустить счётчик реального времени. И при получении байта запоминать метку времени. Кроме того, периодически эту метку времени просматривать. Если интервал от этой метки времени до текущего момент времени превысил максимальную паузу между символами - отправляем накопленную строку на парсинг.
PM ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)"
PILOT ManiaK
UniBomb Mazzi

На данный раздел помимо Правил форума распространяются текже следующие правила:


  • Прежде чем создать тему воспользуйтесь поиском или посмотрите в faq. Возможно на форуме уже есть ответ на ваш или близкий к вашему вопрос.
  • В заголовке темы в квадратных скобках обозначьте используемое семейство микроконтроллера: [avr],[pic],[arm].
  • При создании темы с вопросом указывайте участок кода с ошибкой, версию компилятора, схемы подключения, fuse биты и прочие данные, которые помогут найти правильный ответ. Для форматирования текста программ используйте кнопку код.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Для флуда, просьб выполнить задание, поиска партнёров или исполнителей существуют свои разделы.
  • Если вы заметили несовместимое с правилами сообщение, то можете уведомить об этом модератора раздела нажав кнопку Репорт у соответствующего сообщения.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема »


 




[ Время генерации скрипта: 0.1667 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.