supercelt Опубликовано 5 января, 2017 Поделиться Опубликовано 5 января, 2017 Привет!. Помогите пожалуйста. Для вас это наверное расплюнуть, а у меня непонятки. Пишу код в 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 вариант? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
mail_robot Опубликовано 6 января, 2017 Поделиться Опубликовано 6 января, 2017 (изменено) 15 часов назад, supercelt сказал: В самом прерывании я не стал записывать в переменную содержание регистра DR ибо сами знаете делать что-то в прерывании не комильфо это прерывание будет работать в масштабе времени примерно так - один день ты ждешь байт из USART и примерно минуту его рассматриваешь. Сохранение одного единственного регистра в буфер добавит еще пару секундочек к той минуте. Критично? Запихивай все в буфер строки прямо из прерывания. Чтобы начать разбор строки надо дождаться особых символов. Например '\n'. Иначе откуда знать что пора? Но есть один нюанс - если этот символ никогда не придет (ошибки приема или еще чтото) то буфер переполнится. Надо думать и об этом. Сама строка дербанится уже просто библиотечными функциями string.h У меня на HAL есть готовый код приема строки и разбора до командного процессора. Но тут видимо не тот случай Изменено 6 января, 2017 пользователем mail_robot 1 Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
supercelt Опубликовано 15 января, 2017 Автор Поделиться Опубликовано 15 января, 2017 В продолжении вопроса. Выделить из кавычек это я поторопился. Надо сначала ещё кучу всего сделать. Там условия такие, что строка может придти когда угодно, какая угодно. Я не знаю ее размер. Таким образом я решил что по мере поступления символов, а прерывании по 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; } //--------------------------------------------------------------- 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Особенности хранения литиевых аккумуляторов и батареекПотеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
bobbjenkins Опубликовано 17 января, 2017 Поделиться Опубликовано 17 января, 2017 (изменено) Код ваш не читал но вот что посоветую. \n\r это разделитель строк, соответственно если вы не ждете такой ситуации: "начало стро\n\r ки"\n\r То можете спокойно использовать символ новой строки как признак того что пора заполненный буфер обработать и очистить. Ну естественно, буффер будет обрабатываться несколько раз, для каждой новой строки - тут вылавливайте именно ту строку которая содержит ваши кавычки. Далее, по поводу заранее неизвестн длины строки. Придумайте лимит, скажем 1000 символов. Если пришедшая строка больше - то просто или игнорим остальные символы до следующей комбинации "новая строка", или просто обрабатываем /очищаем буффер, как только он заполнился, и пишем оставшиеся символы в буфер сначала, как будто встретили символ новой строки. Тут уж как хотите. никакой таймер тут не нужен. выделить подстроку из строки можно Или с помощью strtok() или вручную как то так: void extract_between_quotes(char* s, char* dest) { int in_quotes = 0; *dest = 0; while(*s != 0) { if(in_quotes) { if(*s == '"') return; dest[0]=*s; dest[1]=0; dest++; } else if(*s == '"') in_quotes=1; s++; } } Учтите ситуации когда кавычка или одна в строке или ее вовсе нет или их три и больше. Примеров в сети навалом успехов! Изменено 17 января, 2017 пользователем bobbjenkins 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Секреты депассивации литиевых батареек FANSO EVE EnergyСамыми лучшими параметрами по энергоемкости, сроку хранения, температурному диапазону и номинальному напряжению обладают батарейки литий-тионилхлоридной электрохимической системы. Но при длительном хранении происходит процесс пассивации. Разберем в чем плюсы и минусы, как можно ее избежать или уменьшить последствия и как проводить депассивацию батареек на примере продукции и рекомендаций компании FANSO EVE Energy. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
Andras Опубликовано 24 января, 2017 Поделиться Опубликовано 24 января, 2017 TO mail_robot: Цитата У меня на HAL есть готовый код приема строки и разбора до командного процессора. Но тут видимо не тот случай Не могли бы вы поделиться этим кодом? В принципе я уже состряпал терминал, хотелось бы поглядеть на ваш код. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
mail_robot Опубликовано 24 января, 2017 Поделиться Опубликовано 24 января, 2017 (изменено) вот, упрощенная версия. Библиотеки мысленно подкиньте Src.zip Изменено 25 января, 2017 пользователем mail_robot 0 Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.