Быть может, стоило бы прочесть Reference Manual, раздел USART? Потому что там очень доходчиво, даже с диаграммами, расписано всё. Можете через гугл-переводчик, если проблемы с английским
Читал, но я много чего там не понимаю. Не в смысле языка, а а смысле работы всего этого хозяйства. Например, мне не понятно, выставляется ли бит RXNE при срабатывании прерывания по Idle. Со временем, думаю, пойму.
Но ведь это несложно и проверить на деле. Нет, не выставляется, ведь ничего не было принято, поскольку старт-бит и стоп-бит не были обнаружены, и запуска сдвигового регистра приема не было. Во время приема флаг RXNE выставляется в конце приема байта, а флаг IDLE будет выставлен после того, как линия RX будет оставаться свободной в течение времени, равного длительности кадра (обычно 10 бит). Флаг ORE (overrun) будет выставляться тогда, когда был принят новый байт, а предыдущий не был прочитан.
Код:
oid USART2_IRQHandler(void) { /* Линия свободна (idle frame) */ if((USART2->ISR & USART_ISR_IDLE)&&(USART2->CR1 & USART_CR1_IDLEIE)) { Start_RTOTimer(); USART2->ICR = USART_ICR_IDLECF; }
/* Предыдущий принятый символ не был прочитан */ if(USART2->ISR & USART_ISR_ORE) { ToRXBuff(USART2->RDR); USART2->ICR = USART_ICR_ORECF; }
/* Символ был принят */ if((USART2->ISR & USART_ISR_RXNE)&&(USART2->CR1 & USART_CR1_RXNEIE)) { Stop_RTOTimer(); ToRXBuff(USART2->RDR); }
/* Готов к передаче символа */ if((USART2->ISR & USART_ISR_TXE)&&(USART2->CR1 & USART_CR1_TXEIE)) { uint8_t ch; if(FromTXBuff(&ch)) USART2->TDR = ch; else USART2->CR1 &= ~USART_CR1_TXEIE; }
/* Передача символа была завершена и передающий буфер пуст */ if((USART2->ISR & USART_ISR_TC)&&(USART2->CR1 & USART_CR1_TCIE)) {
причем, запуск RTO-таймера можно делать или в IDLE, или в RXNE. В последнем случае таймер не останавливается, а перезапускается с начала. Так же, я настоятельно рекомендую использовать проверку не только флага источника прерывания, но и бита разрешения этого источника. Особенно это необходимо при передаче по TXE-флагу. Этот флаг устанавливается независимо от того, включен передатчик (TE) или выключен. И попадая в прерывание по другому источнику, будет лишняя загрузка передающего регистра. Именно с помощью запрета прерывания TXEIE прекращается передача (в варианте передачи по прерываниям). Флаг TC устанавливается по завершению передачи символа, если в передающем буфере нет загруженных байтов (TXE = 1).
Ну и не надо писать if((USART1->SR & USART_SR_RXNE) >> USART_SR_RXNE_Pos) == 1), поскольку это излишние действия. Нужно отталкиваться от того, что по правилам языка Си, выражение в if() будет истинно при любом ненулевом значении. А запись USART1->SR & USART_SR_RXNE представляет собой логическую побитовую операцию AND с содержимым регистра и значением битовой маски. То есть, например 0110 AND 0100 = 0100, это есть ненулевое значение и условие if будет истинно и выполнится. Если же 0010 AND 0100 = 0000, то условие if будет ложно и не выполнится.
& - означает побитовую операцию AND двух чисел. && - означает логическое AND выражений: "если (ВЫРАЖЕНИЕ_1 = истина) И (ВЫРАЖЕНИЕ_2 = истина)"
Заголовок сообщения: Re: STM32 новичку в ARM что к чему
Добавлено: Пт май 27, 2022 07:19:06
Открыл глаза
Зарегистрирован: Ср сен 24, 2014 12:30:09 Сообщений: 62
Рейтинг сообщения:0
НовыйДень писал(а):
Но ведь это несложно и проверить на деле. Нет, не выставляется, ведь ничего не было принято, поскольку старт-бит и стоп-бит не были обнаружены, и запуска сдвигового регистра приема не было. Во время приема флаг RXNE выставляется в конце приема байта, а флаг IDLE будет выставлен после того, как линия RX будет оставаться свободной в течение времени, равного длительности кадра (обычно 10 бит). Флаг ORE (overrun) будет выставляться тогда, когда был принят новый байт, а предыдущий не был прочитан.
"
Спасибо, ну прямо очень подробно! Сохранил себе в текстовый документ. Попробую!
Последний раз редактировалось Lum1noFor Пт май 27, 2022 09:20:08, всего редактировалось 2 раз(а).
У меня UART работает через DMA: где-то только передача, где-то - и передача, и прием. И я ни разу в жизни ни IDLE, ни RTO не использовал. ЧЯДНТ?
Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA? Возможны всего два варианта: по паузе между байтами или по коду символа.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Возможны всего два варианта: по паузе между байтами или по коду символа.
Не только. Есть еще весьма широко распространенный вариант с ФИКСИРОВАННОЙ ДЛИНОЙ пакета. Скажем, лично я использую во всех своих проектах именно такой вариант. Он происходит из простого факта применения в коммуникациях проекта, в том числе, кастомного HID USB с пакетом в 64 байта. Вот эти пакеты у меня везде и гуляют через DMA<->RS485/RS422.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA?
Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки. А DMA тем временем во второй буфер поступающие данные копит. Там, где нет такого прерывания, я обычно прием без DMA делаю. Потому как пользователь не обязан отправлять блоки строго по одной строке: может и несколько строк отправить, а у меня логическая единица - одна строчка. Вот, чтобы не париться с промежуточным буфером, который будет на токены принятое разделять, я и заканчиваю прием строго на '\n', меняю буферы и выставляю флаг готовности.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Возможны всего два варианта: по паузе между байтами или по коду символа.
Не только. Есть еще весьма широко распространенный вариант с ФИКСИРОВАННОЙ ДЛИНОЙ пакета. Скажем, лично я использую во всех своих проектах именно такой вариант. Он происходит из простого факта применения в коммуникациях проекта, в том числе, кастомного HID USB с пакетом в 64 байта. Вот эти пакеты у меня везде и гуляют через DMA<->RS485/RS422.
Ага, а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как? Опять звать на помощь таймер для измерения длительности паузы при приёме? Или тупо ждать следующего пакета, чтоб не заводить таймер? В итоге всё равно не получается третий вариант, однако.
Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA?
Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки. А DMA тем временем во второй буфер поступающие данные копит. Там, где нет такого прерывания, я обычно прием без DMA делаю. Потому как пользователь не обязан отправлять блоки строго по одной строке: может и несколько строк отправить, а у меня логическая единица - одна строчка. Вот, чтобы не париться с промежуточным буфером, который будет на токены принятое разделять, я и заканчиваю прием строго на '\n', меняю буферы и выставляю флаг готовности.
Так ведь я тебя и спрашивал, по паузе или коду символа? То есть по коду символа, как и ожидалось. Ибо по-другому никак.
а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как?
Ну сняли и сняли. Пропадет последний незавершенный и первый пакет после включения. Первый после включения завершит сессию DMA и перезапустит ожидание адресного байта.
а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как?
Ну сняли и сняли. Пропадет последний незавершенный и первый пакет после включения. Первый после включения завершит сессию DMA и перезапустит ожидание адресного байта.
Хм, то есть факт потери связи зафиксирован не будет.
tonyk, почему же по-другому - никак? Можно и по таймауту. Только придется городить промежуточную буферизацию (кольцевой буфер) с построчной выдачей. Я вот баловался с передачей по USB, используя кольцевой буфер — чтобы максимально увеличить скорость выдачи данных и избавиться от блокирующих операций.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Хм, то есть факт потери связи зафиксирован не будет.
Почему не будет? Будет. Это делает хост (сиречь программа в винде). А девайсу болт положить на связь. Его функционирование никак с наличием обмена не связано. Через обмен идет управление и мониторинг. Все это не обязательно.
Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки.
а контроль переполнения буфера как реализован? а то ведь это классическая дыра...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
использовать уже имеющийся во всех STM32 IDLE или, что лучше, RTO.
А кто сказал, что байты должны идти "ноздря в ноздрю"? Может, между ними по 2-4 свободных фрейма? И окончанием передачи считать, скажем, паузу дольше 100мс после последнего байта… Я таймауты вообще на терминале тестировал, у меня был выставлен таймаут в 3 секунды (уж за три-то секунды я успею следующий символ набрать =D)
Что до переполнения буфера: а как он переполнится, когда прием идет посредством DMA? По заполнению буфера идет прерывание, и коль не было '\n' в процессе, считаем строку бажной и сбрасываем нафиг с выставлением флага ошибки (т.е. следующий пакет тоже нужно будет выбросить).
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Одного универсального способа нет, всегда пишется под конкретную задачу. Где-то пакеты все одинаковой длины, где-то разной длины, но начинаются/заканчиваются определенными символами, где-то инфа в нетекстовом виде и нет определенного завершающего символа, где-то разрозненные символы с произвольными промежутками, где-то минимальные промежутки между пакетами регламентированы, а где-то есть контроль четности. Где-то очень высокая скорость порта и нужен DMA на прием/отправку, а где-то скорость низкая по отношению к частоте МК, да еще и занят нужный канал DMA. Вобщем, ты владеешь несколькими методами работы и выбираешь в конкретном случае наиболее подходящий. Так и везде, в принципе то. Поэтому спорить, что дескать только DMA форева или стопудово только прерывания - не имеет смысла.
Уважаемые знатоки, подскажите в решении проблемы. Использовал STM32F051 совместно с отладчиком BlackMagik. Сначала всё работало как часы, прошивало, отлаживало. Но в один момент чип перестал видиться отладчиком. Достал ST-Link. С ним теперь возможна только запись прошивки из-под ресета через родную прогу, без отладки. Пин BOOT0 сидит на земле, то есть используется запуск из прошивки флеш, пины SWD в проекте вообще не заняты и нигде не переназначаются. Куда копать для восстановления нормальной работы SWD?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 28
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения