USART3 初始化 STM32F103RB

Posted

技术标签:

【中文标题】USART3 初始化 STM32F103RB【英文标题】:USART3 Initilization STM32F103RB 【发布时间】:2021-08-18 08:28:17 【问题描述】:

我是 STM 芯片的初学者,我有一个项目,我必须在 Uvision 中使用所有三个 USART 终端。

我使用的是 STM32F103RB 芯片,我已经让前两个 USART_init 函数工作,但由于某种原因我无法让第三个工作。我真的很感激任何帮助 这是我的 USART_init 函数:

/*----------------------------------------------------------------------------
  Initialize UART pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART1_Init (void) 
  int i;

  RCC->APB2ENR |=  (   1UL <<  0);        /* enable clock Alternate Function  */
  AFIO->MAPR   &= ~(   1UL <<  2);        /* clear USART1 remap               */

  RCC->APB2ENR |=  (   1UL <<  2);        /* enable GPIOA clock               */
  GPIOA->CRH   &= ~(0xFFUL <<  4);        /* clear PA9, PA10                  */
  GPIOA->CRH   |=  (0x0BUL <<  4);        /* USART1 Tx (PA9) output push-pull */
  GPIOA->CRH   |=  (0x04UL <<  8);        /* USART1 Rx (PA10) input floating  */

  RCC->APB2ENR |=  (   1UL << 14);        /* enable USART#1 clock             */

  USART1->BRR   = 0x0271;                 /* 115200 baud @ PCLK2 72MHz        */
  USART1->CR1   = ((   1UL <<  2) |       /* enable RX                        */
                   (   1UL <<  3) |       /* enable TX                        */
                   (   0UL << 12) );      /* 1 start bit, 8 data bits         */
  USART1->CR2   = 0x0000;                 /* 1 stop bit                       */
  USART1->CR3   = 0x0000;                 /* no flow control                  */
  for (i = 0; i < 0x1000; i++) __NOP();   /* avoid unwanted output            */

  USART1->CR1  |= ((   1UL << 13) );      /* enable USART                     */


/*----------------------------------------------------------------------------
  Initialize UART2 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART2_Init (void) 

  RCC->APB2ENR |= 1;                                    // enable clock for AF
    AFIO->MAPR |= 1<<3;                                 // set USART2 remap
    RCC->APB2ENR |= 1<<5;                           // enable clock for GPIOD
    GPIOD->CRL &= ~(0xFF << 20);                // Clear PD5, PD6
    GPIOD->CRL |= (0x0B << 20);                 // USART2 Tx (PD5) output push-pull
    GPIOD->CRL |= (0x04 << 24);                 // USART2 Rx (PD6) input floating
    RCC->APB1ENR |= 1<<17;                          // enable clock for USART2
    USART2->BRR = 0x138;                                // set baudrate -115.2kB from 36MHz
    USART2->CR1 &= ~(1<<12);                        // force 8 data bits
    USART2->CR2 &= ~(3<<12);                        // force 1 stop bit
    USART2->CR3 &= ~(3<<8);                         // force no flow control
    USART2->CR1 &= ~(3<<9);                         // force no parity
    USART2->CR1 |= 3<<2;                                // RX, TX enable
    USART2->CR1 |= 1<<5;                                // Rx interrupts if required
    NVIC->ISER[1] = (1 << 6);                   // enable interrupts if required
    USART2->CR1 |= 1<<13;                           // USART enable
    


/*----------------------------------------------------------------------------
  Initialize UART3 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART3_Init (void) 

  RCC->APB2ENR |= 1;                                    // enable clock for AF
    AFIO->MAPR |= 1<<3;                                // set USART3 remap
    RCC->APB2ENR |= 1<<4;                               // enable clock for GPIOC
    
  GPIOC->CRH   &= ~(0xFFUL <<  4);        /* clear PC10, PC11                  */
    GPIOC->CRH   |=  (0x04UL <<  8);        /* USART3 Rx (PC10) input floating  */
  GPIOC->CRH   |=  (0x01UL <<  8);        /* USART3 Tx (PC11) output push-pull */
    RCC->APB1ENR |=  1<<20;                                 // enable clock for USART3
    
    USART3->BRR = 0x138;                                // set baudrate -115.2kB from 36MHz; USART3    
                                                    //should have the same baudrate as USART2
    USART3->CR1 &= ~(1<<12);                        // force 8 data bits
    USART3->CR2 &= ~(3<<12);                        // force 1 stop bit
    USART3->CR3 &= ~(3<<8);                         // force no flow control
    USART3->CR1 &= ~(3<<9);                         // force no parity
    USART3->CR1 |= 3<<2;                                // RX, TX enable
    USART3->CR1 |= 1<<5;                                // Rx interrupts if required
    NVIC->ISER[1] = (1 << 6);                   // enable interrupts if required
    USART3->CR1 |= 1<<13;                           // USART enable
    

【问题讨论】:

你应该摆脱所有那些“神奇的数字”,参见How to access a hardware register from firmware?的例子。就目前而言,没有打开 MCU 手册就无法阅读此代码。 【参考方案1】:

你的 USART3 初始化的第一行是错误的 :-)

RCC-&gt;APB2ENR |= 1; // enable clock for AF

必须是(没有时钟,USART 不起作用)

RCC-&gt;APB1ENR |= (1&lt;&lt;18); // enable clock for USART

作为附加提示,不要将所有这些幻数用于位。 这更具可读性(并且所需的定义已经在 CMSIS 中完成:

RCC-&gt;APB1ENR |= RCC_APB1ENR_USART3EN; // enable clock for USART

【讨论】:

【参考方案2】:

经过一番研究,我发现问题不仅仅是时钟没有启用。下面是使用STM32F103RB芯片初始化UART3的完整代码

/*----------------------------------------------------------------------------
  Initialize UART3 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART3_Init (void) 

    RCC->APB2ENR |= 1;                                  // enable clock for AF
    AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP;  // set USART3 to partical remap to use PC10 and PC11
    RCC->APB2ENR |= 1<<4;                               // enable clock for GPIOC
    
    // since our pins are above 8, we use H instead of L
    // since we are using 10 & 11 we will be using bits 8-15 in the CRH register
    /* USART3 Tx (PC10) output push-pull */             
    GPIOC->CRH   &= ~(0xFFUL <<  8);        
  GPIOC->CRH   |=  (0x0BUL <<  8);       
    /* USART3 Rx (PC11) input floating  */
    GPIOC->CRH   |=  (0x04UL <<  12);     
    
    RCC->APB1ENR |=  RCC_APB1ENR_USART3EN; /* enable clock for USART3         */
    USART3->BRR = 0x138;                  /* set baudrate -115.2kB from 36MHz */
    
    USART3->CR1   = ((   1UL <<  2) |     /* enable RX                        */
                   (   1UL <<  3) |       /* enable TX                        */
                   (   0UL << 12) );      /* 1 start bit, 8 data bits         */
    
  USART3->CR2   = 0x0000;                 /* 1 stop bit                       */
  USART3->CR3   = 0x0000;                 /* no flow control                  */
    
    USART3->CR1 |= 1<<13;                 /* USART3 enable                    */
    
    //Configure and enable USART3 interrupt
    NVIC->ICPR[USART3_IRQn/32] = 1UL << (USART3_IRQn%32);   // clear any previous pending interrupt flag
    NVIC->IP[USART3_IRQn] = 0x80;                           // set priority to 0x80
    NVIC->ISER[USART3_IRQn/32] = 1UL << (USART3_IRQn%32);   // set interrupt enable bit
    USART3->CR1 |= USART_CR1_RXNEIE;                        // enable USART3 receiver not empty interrupt

我用来证明这个工作的中断看起来像这样

// UART3 Interupt Handler
void USART3_IRQHandler (void) 

    uint8_t inKey3 = (int8_t) (USART3->DR & 0x1FF);
    SendCharTo3(inKey3);
    if(inKey3 == 0x0D) 
        SendCharTo3('\n');
    


/*----------------------------------------------------------------------------
  SendChar
  Write character to Serial Port. for UART 3
 *----------------------------------------------------------------------------*/
int SendCharTo3 (uint8_t ch)  

  while (!(USART3->SR & USART_SR_TXE));
  USART3->DR = ((uint16_t)ch & 0x1FF);

  return (ch);

【讨论】:

以上是关于USART3 初始化 STM32F103RB的主要内容,如果未能解决你的问题,请参考以下文章

STM32F103RB BxCAN通信[关闭]

STM32F103RB - 如何知道使用哪个引脚发送触发信号

STM32F103在RX中断时无法通过UART接收数据

STM32F103 PWM输出实验(HAL库)

[STM32F103]PWM输入捕获配置

STM32F103停机模式测试