如何在STM32L476RG uC中正确配置USART_BRR寄存器?

问题描述 投票:1回答:1

我正在尝试在STM32L476RG Nucleo板上编写自己的USART_TX驱动程序。这里是datasheetreference manual

我正在使用Keil uVision 5,并在“管理”对话框中进行设置:

  • CMSIS>核心
  • 设备>启动
  • Xtal = 16MHz

我想创建一个字符发送器。根据第二节中的手册说明。 40 p 1332我写了这段代码:

// APB1 connects USART2
// The USART2 EN bit on APB1ENR1 is the 17th
// See alternate functions pins and label for USART2_TX! PA2 is the pin and AF7 (AFRL register) is the function to be set


#include "stm32l4xx.h"                  // Device header

#define MASK(x) ((uint32_t) (1<<(x)));

void USART2_Init(void);
void USART2_Wr(int ch);
void delayMs(int delay);

int main(void){
    USART2_Init();


    while(1){
    USART2_Wr('A');
    delayMs(100);


    }
}

void USART2_Init(void){
    RCC->APB1ENR1 |= MASK(17); // Enable USART2 on APB1
    // we know that the pin that permits the USART2_TX is the PA2, so...
    RCC->AHB2ENR |= MASK(0); // enable GPIOA

    // Now, in GPIOA 2 put the AF7, which can be set by placing AF7=0111 in AFSEL2 (pin2 selected)
    // AFR[0] refers to GPIOA_AFRL register
    // Remember: each pin asks for 4 bits to define the alternate functions. see pg. 87 
    // of the datasheet
    GPIOA->AFR[0] |= 0x700; 
    GPIOA->MODER &= ~MASK(4);// now ... we set the PA2 directly with moder as alternate function "10"

    // USART Features -----------

    //USART2->CR1 |=MASK(15); //OVER8=1
    USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?
    //USART2->BRR = 0x1A1; //This one works!!!
    USART2->CR1 |=MASK(0); //UE
    USART2->CR1 |=MASK(3); //TE

}

void USART2_Wr(int ch){
    //wait when TX buffer is empty
    while(!(USART2->ISR & 0x80)) {} //when data is transfered in the register the ISR goes 0x80.
        //then we lock the procedure in a while loop until it happens
        USART2->TDR =(ch & 0xFF); 

}

void delayMs(int delay){
int i;
    for (; delay>0; delay--){
        for (i=0; i<3195; i++);
    }
}

现在,问题:

系统正常运行,但无法正常运行。我的意思是:如果按照USART_BRR reg中0x683的配置以9600波特率使用RealTerm,它将显示错误的字符,但如果我将2400设置为实时术语为波特率,则可以使用!

要在USART_BRR reg中提取0x683,请参阅第二节。 40.5.4 USART波特率生成,它表示如果OVER8 = 0,则USARTDIV = BRR。就我而言,USARTDIV = 16MHz / 9600 = 1667d = 683h。

我认为问题出在此代码行:

USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?

因为如果我替换为

USART2->BRR = 0x1A1; //USARTDIV=16Mhz/9600?

该系统以9600波特率工作。

我的代码或对USARTDIV计算的理解有什么问题?

谢谢您的支持。

此致,GM

c embedded microcontroller stm32 bare-metal
1个回答
4
投票

USART的默认时钟源是PCLK1(图15)PCLK1SYSCLK / AHB_PRESC / AHB1_PRESC。如果0x1A1的波特率为9600,则表明PCLK1 = 4MHz。

当从内部MSI RC振荡器运行时,

4MHz恰好是处理器在启动时的默认频率(和PCLK1)。因此,最可能的解释是您尚未配置时钟树,并且没有按照您认为的从16MHz HSE运行。

要么配置您的时钟树以使用16MHz信号源,要么在MSI频率上执行计算。 MSI精度在正常温度范围内几乎可以维持足够准确的波特率,但是并不理想。


0
投票

关于Clifford的答案(谢谢!)是否有一种简单的方法可以在启动后更改SYSCLK

例如,通过编程MSIRANGE寄存器中的RCC_CR位域?

谢谢,GM

© www.soinside.com 2019 - 2024. All rights reserved.