| Форум РадиоКот https://radiokot.ru/forum/ |
|
| stm32g431 UART на прерываниях, отказ SysTick_Handler https://radiokot.ru/forum/viewtopic.php?f=59&t=199523 |
Страница 1 из 2 |
| Автор: | Cliff [ Пн окт 27, 2025 15:04:24 ] |
| Заголовок сообщения: | stm32g431 UART на прерываниях, отказ SysTick_Handler |
Осваиваю UART на регистрах. Уткнулся в непонятную проблему. Если включить прерывания для UART, то перестаёт работать прерывание SysTick_Handler. Инициализация тактирования системы: СпойлерКод: // Range 1 Boost SET_BIT(PWR->CR5, PWR_CR5_R1MODE); // HSE SET_BIT(RCC->CR, RCC_CR_HSEON); while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) asm(""); // disable PLL CLEAR_BIT(RCC->CR, RCC_CR_PLLON); // config PLL MODIFY_REG( RCC->PLLCFGR, (RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLQ | RCC_PLLCFGR_PLLR | RCC_PLLCFGR_PLLPDIV), ( RCC_PLLCFGR_PLLSRC_HSE | // PLL source ((( 1 ) - 1U) << RCC_PLLCFGR_PLLM_Pos) | // PLLM = 1 .. 16 (( 36 ) << RCC_PLLCFGR_PLLN_Pos) | // PLLN (((( 6 ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos) | // PLLQ = 2, 4, 6, 8 (((( 2 ) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos) | // PLLR = 2, 4, 6, 8 (( 2 ) << RCC_PLLCFGR_PLLPDIV_Pos) // PLLP = 2 .. 31 ) ); // enable PLL SET_BIT(RCC->CR, RCC_CR_PLLON); // Enable PLL System Clock output: PLLCLK selection from main PLL SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLREN); /* Wait till PLL is ready */ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) asm(""); //volatile uint32_t // pcr5 = PWR->CR5, // cr = RCC->CR, // pll = RCC->PLLCFGR; /* Increasing the number of wait states because of higher CPU frequency */ if (READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) < FLASH_ACR_LATENCY_4WS) /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, FLASH_ACR_LATENCY_4WS); //volatile uint32_t pllf = RCC_GetSysClockFreqFromPLLSource(); /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */ MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV2); // SYSCLKSource MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL); while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != (RCC_CFGR_SW_PLL << RCC_CFGR_SWS_Pos)) asm(""); /* Set the highest APB divider in order to ensure that we do not go through a non-spec phase whatever we decrease or increase HCLK. */ MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV16); MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_CFGR_PPRE2_DIV16); /* Set the new HCLK clock divider */ MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV1); /*---------- PCLK1 Configuration ----------*/ MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV1); /*---------- PCLK2 Configuration ----------*/ MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_CFGR_PPRE2_DIV1); //volatile uint32_t SystemCoreClock = // HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU); // в аргументе передаётся делитель (количество тиков для срабатывания прерывания) SysTick_Config(SYSCLOCK_FREQ / 1000U); // частота в Гц / 1000 = интервал 1мс Код: #define SYSCLOCK_FREQ 144000000UL Инициализация UART СпойлерКод: #define UARTNUM 3 /* Configure the UART clock source */ #define __uartccip(uartn) RCC_CCIPR_USART ## uartn ## SEL #define UART_CCIP(uartn) __uartccip(uartn) MODIFY_REG(RCC->CCIPR, UART_CCIP(UARTNUM), 0 /* RCC_USART3CLKSOURCE_PCLK1 */); /* Peripheral clock enable */ #define __uarten(uartn) RCC_APB1ENR1_USART ## uartn ## EN #define UART_EN(uartn) __uarten(uartn) SET_BIT(RCC->APB1ENR1, UART_EN(UARTNUM)); // GPIOB /* *USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); GPIO_SPEED (PINGRP, PINRX, LOW); GPIO_TYPE (PINGRP, PINRX, PUSHPULL); GPIO_PUPD (PINGRP, PINRX, NOPULL); GPIO_MODE (PINGRP, PINRX, ALTERNATE); GPIO_AF (PINGRP, PINRX, 0x07); GPIO_SPEED (PINGRP, PINTX, LOW); GPIO_TYPE (PINGRP, PINTX, PUSHPULL); GPIO_PUPD (PINGRP, PINTX, NOPULL); GPIO_MODE (PINGRP, PINTX, ALTERNATE); GPIO_AF (PINGRP, PINTX, 0x07); /* TX, RX enable */ UART->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_TXEIE | USART_CR1_RXNEIE; UART->CR2 = 0; UART->CR3 = 0; /* UART_PRESCALER_DIV1 */ UART->PRESC = 0; /* в нашем случае PLLclk = SysClk */ uint64_t clk = SYSCLOCK_FREQ; uint32_t baud = 115200; UART->BRR = (clk + (baud >> 1)) / baud; /* UART enable */ SET_BIT(UART->CR1, USART_CR1_UE); #define __uartirq(uartn) USART ## uartn ## _IRQn #define UART_IRQ(uartn) __uartirq(uartn) NVIC_SetPriority(UART_IRQ(UARTNUM), 0); NVIC_EnableIRQ(UART_IRQ(UARTNUM)); Отправка по UART, тут много лишнего для отладки я уже добавлял. Например, обработку RX фейковую, чтобы убедиться, что не из-за неё тормозит. Изначально вообще убирал RX (USART_CR1_RE USART_CR1_RXNEIE) СпойлерКод: static uint8_t _tx[64], *_tc = NULL; static size_t _tsz = 0; static void _tx_send() { if (_tsz <= 0) return; UART->TDR = *_tc; _tc++; _tsz--; } #define __uartit(uartn, itn) USART ## uartn ## _IRQHandler #define UART_IT(uartn, itn) __uartit(uartn, itn) void UART_IT(UARTNUM,0)(void) { if (UART->ISR & (USART_ISR_TXE | USART_ISR_TXE_TXFNF)) _tx_send(); if (UART->ISR & (USART_ISR_RXNE | USART_ISR_RXNE_RXFNE)) { volatile auto r = UART->RDR; volatile uint8_t n = 1; } if (UART->ISR & USART_ISR_IDLE) UART->ICR = USART_ICR_IDLECF; if (UART->ISR & USART_ISR_TC) UART->ICR = USART_ICR_TCCF; } сам SysTick СпойлерКод: static volatile uint32_t _tick = 0; void SysTick_Handler(void) { _tick ++; static uint16_t _tick_1s = 0; _tick_1s++; if (_tick_1s >= 1000) { _tick_1s = 0; } } Если убрать строчку Код: NVIC_EnableIRQ(UART_....) и отправлять через цикл с ожиданием USART_ISR_TXE, то SysTick_Handler работает без проблем. Даже при отладке, пока инициируется переферия, SysTick_Handler успевает несколько раз выполниться. Но как только включается прерывание по UART, всё приехали. Прерывания по UART работают постоянно, а вот SysTick_Handler нет. При срабатывании прерывания UART регистр ISR вот такой: 0x600080, вместо 8 бывает d и c если делать обработчик проще (оставлять только обработку tx). Вообще, я это обнаружил случайно, хотел из SysTick для отладки отправлять раз в секунду hello в этот uart, но хотелось бы всё-таки разобраться, что делаю не так. |
|
| Автор: | veso74 [ Пн окт 27, 2025 15:40:53 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Kакое IDE? Keil? RTOS есть? Попробуйте изменить приоритет ради теста. Напр. Код: NVIC_SetPriority(SysTick_IRQn, 1); ... NVIC_SetPriority(USART1_IRQn, 3); В отладчике через SysTick_Handler(void) проходит?? |
|
| Автор: | Cliff [ Пн окт 27, 2025 20:29:04 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
veso74, спасибо за советы, осталось осмыслить результат диагностики. Kакое IDE? Keil? RTOS есть? vscode, cmsis - решил пойти по пути джедая. rtos нет Попробуйте изменить приоритет ради теста. После смены приоритета всё заработало. Я посмотрел на содержимое SysTick_Config(...), которую применяю из cmsis: Код: #define __NVIC_PRIO_BITS 4U /*!< STM32G4XX uses 4 Bits for the Priority Levels */ ... NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ Т.е. по умолчанию, если я правильно понимаю, для SysTick_IRQn выставляется наименьший приоритет (максимальное число). Но что тогда показывают результаты теста с приоритетами? Получается, они подтверждают подозрение, которое было у меня до этого, что вызов USART3_IRQHandler() фигачит в бесконечном цикле и не даёт выполниться более низким прерываниям (таким как SysTick)? Полагаю, что видимо надо доснять флаг какого-то из прерываний. И в эту сторону я и копал, но ни к чему не пришёл. Логика моя верна? Полагаю, вариант с приоритетами - это костыль, надо видимо решить исходную проблему. Добавлено after 7 minutes 57 seconds: В отладчике через SysTick_Handler(void) проходит?? При исходных параметрах из первого своего сообщения - перестаёт туда заходить, как только включаются прерывания. Т.е. в самом начале выполнения прошивки, отладчик там останавливается. После выполнения NVIC_EnableIRQ(USART3_IRQn); перестаёт там срабатывать. После смены приоритетов, работа возобновилась. Снова туда заходит. |
|
| Автор: | linux_rulezz [ Пн окт 27, 2025 20:30:08 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Прерывание по TXE стоит отключать, если передавать нечего. А так получается, что оно бесконечно шарашит… Лучше вообще при помощи DMA передавать. Да и принимать тоже: во всех "взрослых" STM32 есть прерывание по символу. Вот и ставим прерывание по '\n', да не паримся! Сам так делаю. Протокол, естественно, текстовый. В случае же убогого уродбаса, есть прерывание IDLE, которое и помогает опознать конец фрейма. Тоже использую, благо, этот самый модбас у меня лишь при работе со всякими кривыми китайскими релюшками, которые лень перепрошивать, чтобы туда вменяемый протокол запилить. |
|
| Автор: | HardWareMan [ Пн окт 27, 2025 21:27:05 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Прерывание по TXE стоит отключать, если передавать нечего. А так получается, что оно бесконечно шарашит… Вот правильный ответ. Только следует не отключать а маскировать в самом UART. Хотя, кто-то скажет что это и есть "отключать". А вообще, бесконечный вызов какого-то прерывания я ловил даже на AVR. |
|
| Автор: | Cliff [ Пн окт 27, 2025 21:33:39 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
linux_rulezz, спасибо! Не знаю, почему мне эта мысль не приходила в голову, но это гениально! Я ещё раз перекопал HAL-библиотеку, и там, оказывается, делают точно так же - выключают прерывание TXE по окончании прередачи, а перед очередной передачей включают вновь. Сделал так же у себя, работает стабильно. /бухтёж-on Это вообще писец... я освоил USB, SPI, CAN... везде, блин, "свой путь" в логике работы. Но вот привыкнув уже к тому, что мы, включив прерывание однажды при инициализации, сбрасываем его флагом каждый раз.. И мне казалось, что отключать каждый раз само прерывание - это какая-то дичь, даже не подпускал этой мысли, есть же просто флаги... А оказывается - так МОЖНО было.... и вообще - это НОРМА. /бухтёж-off Короч... Спасибо за помощь. Видимо, свой вопрос я решил. Добавлено after 2 minutes 3 seconds: Только следует не отключать а маскировать в самом UART. Видимо, это вопрос терминологий. Я так и понял изначально:Код: SET_BIT(UART->CR1, USART_CR1_TXEIE); ... CLEAR_BIT(UART->CR1, USART_CR1_TXEIE); Надеюсь, с RX будет проще. |
|
| Автор: | veso74 [ Пн окт 27, 2025 21:40:29 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
где-то в условиях передачи попробуйте вписать начало прерывания: UART->CR1 |= USART_CR1_TXEIE; и остановить прерывание UART->CR1 &= ~USART_CR1_TXEIE; напр. Код: _tc = _tx; _tsz = len; UART->CR1 |= USART_CR1_TXEIE; и Код: void USARTx_IRQHandler(void) {
if (UART->ISR & USART_ISR_TXE) { if (_tsz > 0) { UART->TDR = *_tc++; _tsz--; } else UART->CR1 &= ~USART_CR1_TXEIE; } } } |
|
| Автор: | HardWareMan [ Пн окт 27, 2025 21:53:33 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Видимо, это вопрос терминологий. Отключается оно в NVIC (и глобально в ядре), чтобы ядро вообще не дёргалось в вектор. А в модуле оно маскируется. У некоторых модулей есть отдельные вектора на некоторые запросы. Если же вектор обслуживает несколько запросов, то вам придётся сначала сохранять в локальную переменную регистр флагов SR, затем подтверждать все флаги и после этого анализировать, что там выстрелило. |
|
| Автор: | Cliff [ Пн окт 27, 2025 22:06:31 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
veso74, угу, так и сделал. Спасибо! Ещё раз покопал RM, нигде подобной рекомендации не нашёл. И в многочисленных уроках в интернетах - тоже ничего про это. Или на F1 (уроки по теме UART в интернетах все на F103) прерывание TXE срабатывает однократно и его не надо отключать в конце передачи? |
|
| Автор: | linux_rulezz [ Пн окт 27, 2025 23:06:49 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Cliff, я подозреваю, что просто мало кому приходит в голову на прерываниях организовывать передачу, если можно подключить для этого DMA. Да, конечно, конкретный канал (если нет DMAMUX, да и с ним каналов очень мало) может быть занят чем-то более важным, а блокировать суперлуп на время передачи с черепашьей скоростью не хочется… Вот в этом случае - да, оправдано. Но в конце - когда полностью передали буфер, либо вообще прерывание запрещаем (маскируем при помощи NVIC), либо в CR1 его отключаем. А что до "уроков" в интернете - к ним стоит трижды критически подходить. Чаще всего друг у друга тырят какое-нибудь фуфло на основе калокуба. Добавлено after 6 minutes 38 seconds: О, запустил у себя в дереве Код: find . -name "*.c" -exec grep -Hn TXE {} \; и нашел-таки пример! Вот: Код: if(USART1->ISR & USART_ISR_TXE){ // TX emty - send next char // clear by writing to TDR if(txnum < txdlen){ USART1->TDR = tbuf[txnum++]; }else USART1->CR1 &= ~USART_CR1_TXEIE; // turn off interrupt } Это - в прерывании. А вот так - в функции "офлайн" пересылки данных: Код: TXstatus usart1_send(const char *str, int len){
if(!txrdy) return LINE_BUSY; if(len > UARTBUFSZ) return STR_TOO_LONG; txrdy = 0; txdlen = len; memcpy(tbuf, str, len); txnum = 0; USART1->CR1 |= USART_CR1_TXEIE; // allow IRQ return ALL_OK; } |
|
| Автор: | smacorp [ Вт окт 28, 2025 08:29:50 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
А кто-нибудь флаг ТС (Transmission complete) использует? В примерах одного из производителей МК встречал такой подход: - разрешается прерывание TXE и отправляётся всё, кроме последнего байта; - перед отправкой последнего байте запрещается прерывание TXE и тут же разрешается прерывание TCIE; - последний байт улетает, и уже тогда запрещается и прерывание TCIE. Кто-нибудь так делает? Оно, конечно, работает, но гложут сомнения - зачем использовать TCIE, когда и без него всё отправляется? |
|
| Автор: | Cliff [ Вт окт 28, 2025 08:39:23 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
smacorp, мне казалось, что TC создавался не для передачи, а вообще для других целей, связанных с общей организацией процессов в проекте. Например, дождаться передачи сообщения на другое устройство, прежде чем его отключить или что-нибудь включить. |
|
| Автор: | linux_rulezz [ Вт окт 28, 2025 09:11:42 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
smacorp, конечно: этот флаг нужен, если нет аппаратного управления ногой DE при работе с RS-485. Вот, например: Код: void uart4_isr(){ if(UART4->SR & USART_SR_IDLE){ // idle - end of frame DMA2_Channel3->CCR &= ~DMA_CCR_EN; modbus_rdy = 1; dlen = MODBUSBUFSZI - DMA2_Channel3->CNDTR; recvdata = rbuf[rbufno]; // prepare other buffer rbufno = !rbufno; (void) UART4->DR; // clear IDLE flag by reading DR _485_Rx(); // receive next }else if(UART4->SR & USART_SR_TC){ // TC - switch to Rx if(modbus_txrdy){ _485_Rx(); } UART4->SR &= ~USART_SR_TC; } } А еще в документации такое встречается (что повторяется и в коде): Код: void usart_setup(){
... while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission USART1->SR = 0; // clear flags USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx } |
|
| Автор: | jcxz [ Вт окт 28, 2025 14:28:01 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Оно, конечно, работает, но гложут сомнения - зачем использовать TCIE, когда и без него всё отправляется? TC нужен в тех случаях, когда нужно получить уведомление о завершении операции отправки символа, а не о возможности записать следующий символ в буфер передачи.Он полезен для: 1) полудуплексная передача по одной линии (RS-485 и иже с ним); 2) если нужно управление внешним драйвером на TX (например для RS-485), причём - необязательно для полудуплексных интерфейсов, для дуплексных тоже иногда нужно; 3) по UART пришла команда о перезагрузке устройства - устройство отправляет подтверждение и перегружается (только после отправки полностью подтверждения!); 4) нужно отправить наружу по UART кадр данных, после чего уснуть с отключением тактирования UART (уснуть нужно только после отправки последнего бита последнего байта, не ранее); 5) синхронизация передач по UART с приёмами/передачами по каким-то другими интерфейсами; 6) нужно отправить кадр по UART, после чего сразу переключить скорость UART (например - когда вы отправляете внешнему устройству команду установки новой baudrate, а он устанавливает её и отвечает сразу уже на новой скорости); 7) ... + ещё куча подобных случаев. |
|
| Автор: | smacorp [ Вт окт 28, 2025 15:46:11 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Задавая вопрос о TC и связанном с ним прерывании, я, конечно, и не сомневался, что они придуманы не зря. И когда используется DMA, как и в некоторых других случаях, использование TCIE понятно. Я же говорил о таком применении: Код: void USART1_IRQHandler() { if (USART1->SR & USART1_TXE) // Transmit data register empty { USART1->DR = *tx_buffer++; if (--tx_size == 0) { USART1->CR1 &= ~USART1_TXEIE; // Disable TXE interrupt USART1->CR1 |= USART1_TCIE; // Enable TC interrupt } return; } if (USART1->SR & USART1_TC) // Transmission complete flag { USART1->CR1 &= ~USART1_TCIE; // Disable TC interrupt } } И зачем так рекомендует делать производитель МК не совсем понятно. Есть ведь tx_size, по которому и так будет ясно, что все данные улетели. Впрочем, наверное это лишь учебный пример и в реальном коде так делать смысла нет? Или, всё же, есть? |
|
| Автор: | linux_rulezz [ Вт окт 28, 2025 16:11:48 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
smacorp, в этом примере забыли выставить флаг "данные переданы". А в таком виде, понятное дело, отлавливать TC нет смысла. Хотя, можно исхитриться и использовать USART1_TCIE в качестве него: если tx_size равен нулю, и флага нет, то данные улетели, и можно что-нибудь делать (отключаться, менять скорость, переключаться в режим чтения и т.д., и т.п.). |
|
| Автор: | HardWareMan [ Вт окт 28, 2025 16:18:48 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Разница флагов TC и TE очевидна: первый "Transmission Complete" (передача окончена) а второй TE "Transmitter Empty" (передатчик пуст). И задачи у них разные. ТЕ это попытка в оптимизацию для бесшовной передачи. У SPI, например, использование TE приводит к тому, что байты идут сплошным потоком и SCK не прерывается вообще. Передавать надо строго только по ТЕ кроме вышеописанных случаев (полудуплекс, выключение и прочее), когда надо убедиться что передача закончилась и байт улетел в шину весь, вместе со стопами и прочим арбитражом. |
|
| Автор: | jcxz [ Вт окт 28, 2025 16:39:21 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Я же говорил о таком применении: Такое применение - только в мусорку. Код кривой. Содержит сразу несколько багов: 1) будет передано больше байт, чем tx_size; 2) будут ложные прерывания; 3) будут "гонки"; 4) будет некорректное состояние битов CR1 после завершения передачи (останется стоять TCIE); ...Код: void USART1_IRQHandler() { if (USART1->SR & USART1_TXE) // Transmit data register empty { USART1->DR = *tx_buffer++; if (--tx_size == 0) { USART1->CR1 &= ~USART1_TXEIE; // Disable TXE interrupt USART1->CR1 |= USART1_TCIE; // Enable TC interrupt } return; } if (USART1->SR & USART1_TC) // Transmission complete flag { USART1->CR1 &= ~USART1_TCIE; // Disable TC interrupt } } И скорее всего - код вообще зациклится в бесконечной передаче. И зачем так рекомендует делать производитель МК не совсем понятно. Есть ведь tx_size, по которому и так будет ясно, что все данные улетели. Значит вы не понимаете назначение флагов статуса UART. С этого и надо было начинать.TXE - сигнал о наличии свободного места в FIFO передатчика; TC - сигнал о завершении передачи символа. Это совершенно разные сигналы и использовать каждый нужно в подходящем ему случае. Потому TC разрешается только для последнего символа (с запретом TXE). |
|
| Автор: | Cliff [ Вт окт 28, 2025 22:24:21 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
Я же говорил о таком применении: Очевидно, что тут выстроена модель: 1. Корректная побайтная передача 2. Оповещение о завершении передачи всего буфера. ну т.е. TC гарантировано сработает только при завершении выдачи в порт крайнего бита всего буфера. Видимо, это пример из конкретной задачи. Просто, применение TC тут вырезано, только факт его срабатывания остаётся. Непонятно, что смущает в данном примере. Либо ваш вопрос сложнее, чем кажется с первого взгляда. |
|
| Автор: | linux_rulezz [ Вт окт 28, 2025 22:36:27 ] |
| Заголовок сообщения: | Re: stm32g431 UART на прерываниях, отказ SysTick_Handler |
крайнего Не крайнего, а последнего! Не нужно людей в заблуждение вводить! |
|
| Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


