按照这个说法,看了一下 USART_Init() 函数计算的 BRR 寄存器值,发现明显的不对,先给出 USART_Init() 函数中 BRR 寄存器计算部分的代码: uint32_t tmpreg = 0x00, apbclock = 0x00; uint32_t integerdivider = 0x00; uint32_t fractionaldivider = 0x00; /* Configure the USART Baud Rate */ RCC_GetClocksFreq(&RCC_ClocksStatus); if ((USARTx == USART1) || (USARTx == USART6)) { apbclock = RCC_ClocksStatus.PCLK2_Frequency; } else { apbclock = RCC_ClocksStatus.PCLK1_Frequency; } /* Determine the integer part */ if ((USARTx->CR1 & USART_CR1_OVER8) != 0) { /* Integer part computing in case Oversampling mode is 8 Samples */ integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate))); } else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */ { /* Integer part computing in case Oversampling mode is 16 Samples */ integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate))); } tmpreg = (integerdivider / 100) << 4; /* Determine the fractional part */ fractionaldivider = integerdivider - (100 * (tmpreg >> 4)); /* Implement the fractional part in the register */ if ((USARTx->CR1 & USART_CR1_OVER8) != 0) { tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07); } else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */ { tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); } /* Write to USART BRR register */ USARTx->BRR = (uint16_t)tmpreg; 可以看出,这里用于计算的 Fck 是直接从寄存器中读出来的,读出的值是正确的。接下来计算整数部分,这里就出错了。进一步跟踪“integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));”这段代码,看汇编程序,发现当 apbclock 为 180,000,000 的时候计算结果是错的,原因在于 25*180000000=4500000000,已经超过了 2^32=4294967296 所能表示的最大数,因此计算结果溢出。 因此,将计算整数部分的代码修改如下: /* Determine the integer part */ if ((USARTx->CR1 & USART_CR1_OVER8) != 0) { /* Integer part computing in case Oversampling mode is 8 Samples */ // integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate))); integerdivider = ((25 * (apbclock / 2)) / (USART_InitStruct->USART_BaudRate)); } else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */ { /* Integer part computing in case Oversampling mode is 16 Samples */ // integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate))); integerdivider = ((25 * (apbclock / 4)) / (USART_InitStruct->USART_BaudRate)); } 经测试验证,该计算结果正确,波特率正确,USART 能够正常通信。我在我的博客里再次质问下 ST 吧,这样的边界问题,你们不做测试么? |