我目前正在使用发现板上的STM32F407VG。我正在检查外围设备,并试图通过仅操作寄存器(无HAL)来使每个外围设备正常工作。
我使用示波器(大约每位8-9 us )和Putty中的波特率(111,111波特率来显示实际字符)来测量这一点。
我是最大的时钟速度的芯片168 MHz SYSCLK,APB1预分频器"/4",APB2预分频器"/2“。我非常确定我的时钟是在它们应该的位置,以验证我设置了TIMER12,它共享APB1时钟,并将预分频器设置为8400,并且每当存在比较匹配(CCR = 5000)和溢出时都会生成一个中断。我用示波器测量了一下,我得到了一个预期的1 Hz方波,这意味着定时器12的APB1是84 MHz。
这是我的时钟初始化代码:
void SysClockConfig ( void ){
//setting up the MCO output to see the clock signal
//RCC->CFGR |= ( 6 << 24 ) | (3 << 21 ) | ( 4 << 27 );
//1. ENABLE HSE and wait for the HSE to become Ready
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
// 2. Set the POWER ENABLE CLOCK and VOLTAGE REGULATOR
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;
// 3. Configure the FLASH PREFETCH and the LATENCY Related Settings
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_5WS;
//4. Configure the PRESCALARS HCLK, PCLK1, PCLK2
// AHB PR
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
// APB1 PR
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
// APB2 PR
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
//5. Configure the MAIN PLL
RCC->PLLCFGR = (PLL_M << RCC_PLLCFGR_PLLM_Pos) | (PLL_N << RCC_PLLCFGR_PLLN_Pos) | (PLL_Q << RCC_PLLCFGR_PLLQ_Pos) | (RCC_PLLCFGR_PLLSRC_HSE);
//6. Enable the PLL and wait for it to become ready
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
//7. Set source
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}这是我的UART2配置代码:
void UART2_Config ( void )
{
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //clock UART
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //clock GPIOA
GPIOA->MODER |= ( 2 << GPIO_MODER_MODER2_Pos ) | ( 2 << GPIO_MODER_MODER3_Pos ); //set PA2 and PA3 alternate function
GPIOA->OSPEEDR |= ( 3 << GPIO_OSPEEDR_OSPEED2_Pos ) | ( 3 << GPIO_OSPEEDR_OSPEED3_Pos ); //clock GPIO pin at fastest speed
GPIOA->AFR[0] |= ( 7 << GPIO_AFRL_AFSEL2_Pos ) | ( 7 << GPIO_AFRL_AFSEL3_Pos ); //set PA2 and PA3 to alt func UART2
USART2->CR1 = 0;
USART2->CR1 |= USART_CR1_UE; //UART Enable
//USART2->BRR = (0x16 << USART_BRR_DIV_Mantissa_Pos) | (0xc << USART_BRR_DIV_Fraction_Pos); //Set Baud rate
USART2->BRR = 4300;
//USART2->CR1 |= USART_CR1_RE; //Receiver enable
USART2->CR1 |= USART_CR1_TE; //Transmitter enable
//Baud rate is off by a factor of 12ish
}最后,我的main和while循环包含用于发送字符的函数:
void UART2_SendChar ( uint8_t c )
{
USART2->DR = c;
while ( !(USART_SR_TC));
}
int main ( void )
{
SysClockConfig();
GPIO_Config();
TIM10_Config();
TIM12_Config();
UART2_Config();
//NVIC_SetPriority (TIM1_UP_TIM10_IRQn, 1);
//NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
NVIC_SetPriority (TIM8_BRK_TIM12_IRQn, 1);
NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
while ( 1 )
{
//GPIOD->BSRR |= (1<<12);
//delay(2000000);
//GPIOD->BSRR |= (1<<28);
delay(4000000);
UART2_SendChar('a');
}
}我在参考手册中找不到任何东西来解释这种行为。这告诉我我做错了什么,但我似乎找不到它。
发布于 2021-07-04 15:30:57
我最近回答了一个类似的问题here,所以让我复制这个问题:
BRR是Q12.4格式的定点数,选择OVER8方式时需要进行一次额外的运算。
OP的问题是关于STM32F4的,但如果查看STM32F030参考手册,他/她可以找到相同的逻辑,但由不同的公式表示。国际海事组织,其中一个(F030)更清晰,更容易理解。
要将uint16_t (Q16.0)转换为Q12.4,需要将其乘以16。
基本上,对于OVER16来说,BRR简单地变成了PeripheralClock / BaudRate。
对于OVER8,您首先需要将临时变量计算为temp = 2 * PeripheralClock / BaudRate。将其写入BRR时,需要将其低4位右移一次。
请参见示例代码:
void setBaudRate(uint32_t baud, bool over8)
{
const uint32_t pClock = 42000000ull; // Hard-code or call a function to obtain it
uint32_t usartDiv = (over8) ? (2 * pClock / baud) : (pClock / baud);
uint32_t reg = USART1->BRR;
reg &= ~0xffff; // Clear the lower 16 bits
if (over8) {
reg |= (usartDiv & 0xfff0) | ((usartDiv & 0xf) >> 1);
}
else { // over16
reg |= usartDiv;
}
USART1->BRR = reg;
}因此,对于您的情况,BRR的正确值是4375。
https://stackoverflow.com/questions/68240003
复制相似问题