LiVit

STM32F030 USART1 прием пакетов неизвестной длины

3 posts in this topic

LiVit    12

Привет коллеги! Данная публикация - для тех, кто еще не все плюшки UARTA попробовал ))

USART1 (и только он) микроконтроллеров серии STM32F030 предоставляет возможность принимать пакеты данных с неизвестной заранее длиной пакета.
Для этого можно использовать овертаймер.
Работает это так:
Если в течение заданного времени не будет принят старт-бит очередного байта, генерируется прерывание.
Время ожидания задается не физически (в секундах), а в количестве бит, которые могли бы быть приняты на данной скорости.
т.е., если мы зададим число 16, то прерывание возникнет, если в течение времени эквивалентному приему 16 бит, на вход USART не поступит старт-бит.

Как включить.
1 разрешим прерывание - бит RTOIE регистра CR1
2 зададим время (количество бит) в регистре RTOR
3 разрешим работу овертаймера - бит RTOEN регистра CR2
4 при возникновении прерывания от USART1, смотрим флаг RTOF в регистре ISR, - если есть флаг, значит это оно
5 сбросим флаг прерывания - бит RTOCF в регистре ICR.

Как я это использую.
Включаю прерывание при инициализации порта и задаю количество бит для счетчика.
Как только приходит первый байт сообщения - в прерывании разрешаю работу овертаймера.
Все принятые байты сохраняю в буфер.
Когда возникнет прерывание по овертайму - запрещаю овертаймер, и передаю пакет на парсинг.

Share this post


Link to post
Share on other sites
Posted (edited)

Есть еще IDLE в прерывании которго можно включить таймер это для старых версий. Я не жду первого байта просто прием по ДМА, окончание пакето по RTOR, таймаут по приему ответа (если мастер) на отдельном таймере (даже программный на тиках ОС).

Edited by MasterElectric

Share this post


Link to post
Share on other sites
LiVit    12
16 часов назад, MasterElectric сказал:

Есть еще IDLE в прерывании которго можно включить таймер это для старых версий. Я не жду первого байта просто прием по ДМА, окончание пакето по RTOR, таймаут по приему ответа (если мастер) на отдельном таймере (даже программный на тиках ОС).

Тоже хорошо!
RTOR далеко не все микроконтроллеры имеют. И у STM32F030 - только для USART1.

Но мне лень было с таймерами возиться.

Share this post


Link to post
Share on other sites

DC/DC-преобразователи MORNSUN R3. Повышенная надёжность - сниженная стоимость!

Особенностью преобразователей R3 являются улучшенные технические характеристики, повышенная надёжность и сниженная стоимость. Электрическая прочность изоляции представленных преобразователей не менее 1500 В, а температурный диапазон применения -40…105ºС.

Подробнее...

Your content will need to be approved by a moderator

Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoticons maximum are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By LiVit
      Приветствую, коллеги!
      Ситуация такая: есть серия устройств на STM32F030R8, на некоторых время от времени начинает греться микроконтроллер. 
      Вся логика работает, всё вроде в порядке, кроме потребления в 250мА. И перегретого корпуса микроконтроллера.
      В прошивке изначально отсутствовала инициализация неиспользуемых ног, кроме того, проц сначала старается завести внешний кварц, и только потом переходит на внутренний генератор.
      Нога BOOT0 притянута к земле напрямую, без резистора.
      На проце который уже начал перегреваться, я сделал инициализацию всех ног на вход, с подтяжкой ног к земле. Сразу завожу внутренний тактовый генератор.
      К сожалению, ему уже ничего не помогает, - даже будучи стертым, он жрет 200 мА. Как я понимаю, тут мои полномочия всё.
      Хотелось бы услышать от коллег, что именно могло вызвать такую странную неисправность проца? Может кто сталкивался? В Errata ничего подобного не нашел.
    • By User_1
      Всем привет!
      Почему-то этот код работает: 
      void Send_to_UART(char* string) { char data = 0; while(*string) { while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE))); data = *string; USART1->TDR = data; string++; } while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE))); USART_SendData(USART1, 0x0D); while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE))); USART_SendData(USART1, 0x0A); while(!(USART_GetFlagStatus(USART1, USART_FLAG_TC))); } char hello[13] = {'H','e','l','l','o',' ','W','o','r','l','d','!'}; int main (void) { Init_Clock(); Init_USART1(); Send_to_UART(hello); while(1); } А если написать вот так:
      int main (void) { Init_Clock(); Init_USART1(); Send_to_UART("Hello World!"); while(1); } то не просто не работает - микроконтролер зависает даже до входа в main().
      В Си ведь, насколько я понимаю, строка - это тот же массив символов
      Объясните, пожалуйста, что я делаю не так?
      Камень stm32f030, среда CooCox CoIDE
    • Guest Максим
      By Guest Максим
      Всем светлым и умным головам привет!

      Никак не могу найти информацию о данном прерывании TIM1_BRK_UP_TRG_COM.
      Вопрос 1: Что это за стек или система прерываний? 
      Вопрос 2: Когда будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler, если также есть обработчик прерывания TIM1_CC_IRQHandler?
      Вопрос 3: период переполнения таймера равен 100 мкс. Сколько раз будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler до обработчика прерывания TIM1_CC_IRQHandler? По логике вещей, предполагаю, что 100 раз?
      Заранее благодарен!

      Всем радости))
    • By User_1
      Доброго времени суток!
      Вкратце: нужно после того, как я записал байт данных в SPI1->DR, отменить передачу этого байта и вместо него отправить 0х00
      Подробно: Смысл вот в чём: некий контроллер, с которым я пытаюсь наладить общение по SPI, запрашивает произвольный участок массива байт и считывает их сплошным потоком. Ну примерно как считывается микросхема EEPROM: задаёшь начальный адрес, а потом просто шлёшь сплошные 0xFF, а она сама инкрементирует адрес и прямо непрерывным потоком байт выдаёт содержимое памяти. Только тут в роли этой микросхемы мой stm32f030 и мне нужно следующий байт отправлять в SPI1->DR сразу после отправки предыдущего. Но когда поток заканчивается (а он каждый раз разной длины и длина эта заранее неизвестна), один байт остаётся не переданным и отправится первым при следующем запросе. А мне нужно, чтобы первым байтом всегда отправлялся 0х00
      Пином (ну то есть битом) NSS управляю программно, его выставление в единичку и снова в ноль, очевидно, не помогает вообще никак. Пока решил проблему так: деинициализирую модуль SPI и выключаю его тактирование, затем включаю тактирование и снова инициализирую. Работает, скорости хватает. Но должно же быть менее костыльное решение?)
      Может кто сталкивался с такой проблемой?
      Курение даташита, reference manual и результатов поиска в гугле, не особо помогло.
    • By LiVit
      Добрейшего всем времени суток!
      Случилось недавно моему заказчику захотеть защитить прошивку от считывания (да, я знаю, люди эту защиту сковыривают на раз, но это уже не моя беда). А так как делать это вручную, при прошивке каждого проца, довольно геморройно, было решено добавить в код "самозащиту".
      Почитав мануал на проц, погуглив, почитав комментарии в stm32F0xx_flash.h, я написал следующий код:
          #include "stm32F0xx_flash.h"     if (RESET == FLASH_OB_GetRDP())        //checking protection status     {         FLASH_OB_Unlock();    //unblock the Option Byte         if (FLASH_COMPLETE == FLASH_OB_RDPConfig(OB_RDP_Level_1))     FLASH_OB_Launch();         FLASH_OB_Lock();     } Казалось бы, всё сделано так, как рекомендовано. Тем не менее, этот код не работает.
      Гугль показал, что данная тема волнует не только меня, но и других камрадов. 
      В общем, правильное решение выглядит так:
          #include "stm32F0xx_flash.h"         if (RESET == FLASH_OB_GetRDP())        //checking protection status     {         FLASH_Unlock();    //unblock the FLASH (!!)         FLASH_OB_Unlock();    //unblock the Option Byte         if (FLASH_COMPLETE == FLASH_OB_RDPConfig(OB_RDP_Level_1))     FLASH_OB_Launch();         FLASH_OB_Lock();         FLASH_Lock();     } Обратите внимание, - перед тем, как разблокировать Option Byte, необходимо разблокировать саму флэшь.
  • Сообщения

    • Вот как написано в МРБ-607 Юный радиолюбитель В.Г.Борисов 1966-4 изд :
    • Наш, на порядок, активнее.  По крайней мере эфир забит под завязку. Навальный, как тот Явлинский ( кто его ещё помнит ?) становится,  всплывает только к определённой дате. Оппозиционирование же, на мой скромный взгляд, постояное "донимание" властей, с чем у навального - швах. Скорее договорённость прослеживается. Я тут слегка побужу, потом 15 суток, затем жалоба в еспч, компенсация и на Канары.  Так и живёт. И имеет право. Очень сомнительно. Двоих рядом поставить: Зеленский - актёр, харизма присутствует . Наш - ну незнаю... Нескладный какой то. Не лидер нифига, как по мне.
    • @Sasha00 В названии транзистора обычно указывается порог открытия. Например IRF540 и IRL540. Там, где "L", у того низкий уровень открытия. У остальных высокий порог. А если нужно точнее, до тысячных вольт, то нужно понимать, что от партии к партии и температуры порог открытия может отличаться на 100%. Так что, порог открытия у IRL = 2 вольта +-50%. У обычных 4В +-50%.
    • А то... Потому и написал на стенке что-то типа "Ребята давайте срать дружно!" или "Пердите потише - в соседних кабинах уши закладывает!"
    • Пособие не читал, но способ реально работает.  Если без экстремизму.