ST意法半导体
直播中

早知

9年用户 1201经验值
擅长:光电显示 存储技术
私信 关注
[问答]

如何使用寄存器通过中断发送USART消息?

我正在做一个大学项目,并且努力使用 USART 中断向虚拟终端发送消息。
我使用以下代码:
  • void UART_Send (uint8_t *buffer){
  •                 USART1->CR1 |= USART_CR1_TXEIE; // Enable TXE Interrupt
  •                 USART1->DR = buffer[0];                // Send data
  •                 }
  • void USART1_IRQHandler(void) {
  •                 // Check TXE flag
  •         int Tx1_Counter=0;
  •         if(USART1->SR & USART_SR_TXE) {
  •                             Tx1_Counter++;
  •                             if(Tx1_Counter <= strLength(buffer) - 1)
  •                             {
  •                                     USART1->DR = buffer[Tx1_Counter] & 0xFF;
  •                     } else
  •                             {
  •         }
  •                         // Transmission completes
  •                             Tx1_Counter = 0;
  •                             // Clear the counter
  •                             // Disable TXE interrupt
  •                             USART1->CR1 &= ~USART_CR1_TXEIE;
  •         }
  •                 }
我使用目前看起来像这样的寄存器来设置整个 init:
  • #include
  • #include "STM32f103x6.h"
  • #include "util.h"
  • void USART_Init (USART_TypeDef * USARTx) {
  •         // Default setting:
  •         // No hardware flow control, 8 data bits, no parity, 1 start bit and 1 stop bit
  •         USARTx->CR1 &= ~USART_CR1_UE;  // Disable USART
  •         // Configure word length to 8 bit
  •         USARTx->CR1 &= ~USART_CR1_M;   // M: 00 = 8 data bits, 01 = 9 data bits, 10 = 7 data bits
  •         USARTx->CR1 |= (01 << USART_CR1_M_Pos);
  •         // Configure oversampling mode: Oversampling by 16
  •         // CORTEX M4 samo - USARTx->CR1 &= ~USART_CR1_OVER8;  // 0 = oversampling by 16, 1 = oversampling by 8
  •         // Configure stop bits to 1 stop bit
  •         //   00: 1 Stop bit;      01: 0.5 Stop bit
  •         //   10: 2 Stop bits;     11: 1.5 Stop bit
  •         USARTx->CR2 &= ~USART_CR2_STOP;
  •         // Podesavanje Baudrate - Strana 798 i 799, 27.3.4 Fractional baud rate generation, Tabela 192. na strani 799
  •         // CSet Baudrate to 9600 using APB frequency
  •         // Tx/Rx baud = f_CK / (16*USARTDIV),
  •         // BRR = 0x1D4C za USARTDIV=468,75 za 72MHz, odnosno BRR = 0xEA6, USARTDIV = 234,75 za 36MHZ, Limited to 16 bits
  •         // Default clock je 8MHz, USARTDIV = 8.000.000/(16*9600) = 52,083 ,
  •         // DIV_Mantissa = 52 = 0x34, DIV_Fraction=0,083 u hex broju = 0,083*16=1,328->DIV_Fraction=0x1
  •         // -> BRR = 0x341
  •         USARTx->BRR  = 0x341;
  •         USARTx->CR1  |= (USART_CR1_RE | USART_CR1_TE);          // Transmitter and Receiver enable
  •         USARTx->CR1  |= USART_CR1_UE; // USART enable
  • }
  • void UART1_GPIO_Init(void) {
  •         // Enable the peripheral clock of GPIO Port A
  •         RCC->APB2ENR |=   RCC_APB2ENR_IOPAEN;
  •         // ********************** USART 1 ***************************
  •         // U Reference Manualu STM32F103R6 treba videti na koje pinove GPIO porta se mapira USART1 i u kojem rezimu treba setovati te pinove GPIO porta
  •         // jer se ukljucuje alternativna funkcija
  •         // PA9 = USART1_TX, PA10 = USART1_RX (strana 181)
  •         // Rezim rada GPIO Porta - strana 166 i 167
  •         // USARTx_TX - Ako radi u Full duplex rezimu podesiti: Alternate function push-pull (The USART_TX pin can also be configured as alternate function open drain.)
  •         // USARTx_TX - Ako radi u Half duplex synchronous rezimu podesiti: Alternate function push-pull
  •         // USARTx_RX - Ako radi u Full duplex rezimu, podesiti port kao: Input floating / Input pull-up
  •         // USARTx_RX - Ako radi u Half duplex synchronous rezimu, onda se ne koristi pin: Not used. Can be used as a general IO
  •         // Prvo podesavamo pin PA9 na koji se povezuje USART1_TX, tako da pin treba da radi u izlaznom rezimu sa alternativnom funkcijom
  •         GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9); // Obrisati  CNF9[1:0] i MODE9[1:0] - za konfiguraciju 9 pina, porta A
  •         // Alternativno moze da se koristi GPIOA_CRH &= ~(0xF << 4);
  •         // Ili GPIOA_CRH &= ~0xF0;
  •         // Prvo se podesava rezim rada pina 9 porta A - ulazni, ili jedan od tri izlazna.
  •         // Vrednosti za MODE[1:0]: 00: Input mode (reset state), 01: Output mode, max speed 10 MHz.
  •         // 10: Output mode, max speed 2 MHz, 11: Output mode, max speed 50 MHz.
  •         GPIOA->CRH |= (GPIO_CRH_MODE9_1 | GPIO_CRH_MODE9_0);// Setujemo vrednost 11 za Mode9[1:0] = Output mode, max speed 50 MHz.
  •         // isto moze i GPIO->CRH |= 0b11 << 4; ili GPIO->CRH |= 0x30;
  •         // Sada se podesava kako da pin radi u izlaznom rezimu.
  •         // Vrednosti za GPIOx_CNF[1:0]: Ako polje MODE[1:0] nije = 00, odnosno pin je setovan u nekom od izlaznih rezima, onda:
  •         // 00: General purpose output push-pull, 01: General purpose output Open-drain
  •         // 10: Alternate function output Push-pull, 11: Alternate function output Open-drain
  •         GPIOA->CRH |= GPIO_CRH_CNF9_1;        // Setuje se vrednost 10 za Mode9[1:0] -> Alternate function push-pull
  •         // Moze i GPIO->CRH |= 0x80;
  •         // Zatim podesavamo pin PA10 na koji se povezuje USART1_RX, tako da pin treba da radi u ulaznom rezimu sa alternativnom funkcijom
  •         GPIOA->CRH &= ~(GPIO_CRH_MODE10 | GPIO_CRH_CNF10); // Obrisati  CNF9[1:0] i MODE9[1:0] - za konfiguraciju 10 pina, porta A
  •         // Prvo podesavamo rezim rada pina 10, porta A
  •         // Vrednosti za MODE[1:0]: 00: Input mode (reset state), 01: Output mode, max speed 10 MHz. 10: Output mode, max speed 2 MHz, 11: Output mode, max speed 50 MHz.
  •         // Mi hocemo da postavimo vrednost 00: Input mode, ali posto smo prethodno obrisali te bitove, ne diramo nista
  •         // Vrednosti za GPIOx_CNF[1:0]: Ako je polje MODE[1:0] = 00, odnosno pin je u input rezimu, onda:
  •         // 00: Analog mode, 01: Floating input (reset state), 10: Input with pull-up / pull-down, 11: Reserved
  •         GPIOA->CRH |= GPIO_CRH_CNF10_0; // USART radi u full-duplex rezimu, pa setujemo kao Floating input = 01, videti gore ili strana 167
  • }
  • void UART1_Init(void) {
  •         // Enable the clock of USART 1
  •         RCC->APB2ENR |= RCC_APB2ENR_USART1EN;  // Enable USART 1 clock
  •         UART1_GPIO_Init();
  •         USART_Init(USART1);
  •         //NVIC_SetPriority(USART1_IRQn, 0);                        // Set Priority to 1
  •         //NVIC_EnableIRQ(USART1_IRQn);                                // Enable interrupt of USART1 peripheral
  • }
抱歉,如果塞尔维亚语注释使代码难以阅读。
整个项目在 proteus 8.12 和 Eclipse 中完成。我正在使用 STM32F103R6。
主要问题是如何调用中断以及如何在中断处理程序中传递缓冲区。






回帖(1)

陈小鸥

2022-12-13 14:20:02
现在 ISR:


  • void USART1_IRQHandler(void)
  • {
  •     if(USART1->CR1 & USART1->SR & USART_SR_TXE) {
  •         uint8_t c = *sendbuf++;
  •         if (*sendbuf == 0)
  •             USART1->CR1 &= ~USART_CR1_TXEIE;
  •             USART1->DR = c;
  •     }
  • }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分