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

Старт складской программы по Wi-Fi/ Bluetooth-чипам от Espressif

На склад КОМПЭЛ поступили чипы, модули и отладочные платы от компании Espressif Systems на базе ESP8266 и ESP32. Стоимость всех изделий данной линейки – в 2-3 раза ниже ближайших аналогов, чипы занимают минимальное место на плате, энергоэффективны и универсальны в применении

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

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, необходимо разблокировать саму флэшь.
  • Сообщения

    •  Приветствую всех , дабы не плодить новые темы решил спросить тут.
       Подскажите как переделать схему на UC3842/3845 под биполярный транзистор,( остались транзисторы от телеков: Кт838а , 2sc5802, J6810a  , а вот мосфетов в прямой доступности нет)
       Достаточно ли будет "выходного тока" микросхемы 1А для управления транзистором? или нужен будет какой-то согласующий каскад?
       как рассчитать номинал резистора между базой транзистора и 6 ногой микросхемы.
       Планируется собрать зарядник : 75вт (15в 5А), трансформатор ТПИ-4-3 , 30кгц. 
    • Ну как там твоя программа симуляции, сдурела или еще нет?
    • А нам присылают счет только на одного человека - на собственника.  ----------------------------------------------- Для того, что Декларация прав человека распространялась на тебя, мало быть человеком, надо еще чтобы власть признавала тебя человеком. 
    • Ну так Холтоноид
    • Заказал индикатор SSD1306 и энкодер для очередного переносного приёмника в этот раз с предыдущей страницы, но оказывается там нет индикации напряжения на аккумуляторе. Наверно придётся вернуться к версии на уже надоевшем индикаторе от 5110.
    • Спасибо огромное! более подробно почитал сервис мануал: Only DC detection is enabled 2 seconds after power-on. If there is a fault in the power amplifier........ If this status continues for more than 3 seconds, the power is turned off (for Standby mode) and flashes the standby LED.  Do not accept the key input afterward.

      However, power on is possible when the following key was pressed to be able to key input in the protection line and service.
      1. Test mode (remote control code : A55F)
      2. When the STEREO/DIRECT key and SIGNAL SELECT key are both held pressed for 2 seconds. (Be effective when turned the power off by DC detection regarding 2.)   а теперь по русски: если на выход попала постоянка, то процессор запоминает это, и при повторной попытке включения, не включает ресивер. это можно обойти, если одновременно зажать кнопки STEREO/DIRECT и SIGNAL SELECT на 2 секунды.   ну и вывод - что то пробито в усилителе, буду думать дальше что и как попытаться починить)