最近有客户在使用极海APM32F072CBT6时,遇到串口波特率不能配置到3M以上的问题,因为在数据手册中有明确指示072的串口波特率最高可以配置到6M。客户使用极海当前SDK例程库(V1.7)串口波特率最多只能配置到3M,这是怎么回事呢?APM32F072的串口波特率无法配置到更高的速率吗?
答案当然是否定的。经过我们内测试验,发现这个问题是由于当前SDK例程库(V1.7)的底层软件配置有缺失,当前的例程库在配置USART_Config这个函数底层的时候,其配置方式只能讲串口波特率配置到3M,如下所示:
- void USART_Config(USART_T* uart, USART_Config_T* configStruct)
- {
- uint32_t temp, fCLK, intDiv, fractionalDiv;
- /** Disable USART */
- uart->CTRL1_B.UEN = 0x00;
- /** WLS, PCEN, TXEN, RXEN */
- temp = uart->CTRL1;
- temp &= 0xE9F3;
- temp |= (uint32_t)configStruct->mode | \
- (uint32_t)configStruct->parity | \
- (uint32_t)configStruct->wordLength;
- uart->CTRL1 = temp;
- /** STOP bits */
- temp = uart->CTRL2;
- temp &= 0xCFFF;
- temp |= configStruct->stopBits;
- uart->CTRL2 = temp;
- /** Hardware Flow Control */
- temp = uart->CTRL3;
- temp &= 0xFCFF;
- temp |= (uint32_t)configStruct->hardwareFlowCtrl;
- uart->CTRL3 = temp;
- if (uart == USART1)
- {
- fCLK = RCM_ReadUSART1CLKFreq();
- }
- else if (uart == USART2)
- {
- fCLK = RCM_ReadUSART2CLKFreq();
- }
- else
- {
- fCLK = RCM_ReadPCLKFreq();
- }
- intDiv = ((25 * fCLK) / (4 * (configStruct->baudRate)));
- temp = (intDiv / 100) << 4;
- fractionalDiv = intDiv - (100 * (temp >> 4));
- temp |= ((((fractionalDiv * 16) + 50) / 100)) & ((uint8_t)0x0F);
- uart->BR = temp;
- }
通过查阅《APM32F072x8xB用户手册 V1.6》,第22.4.4.5章节,有说明串口采样率可配置为波特率的8倍和16倍,如下图所示,以上配置是默认使用16倍采样率来配置的,如果系统时钟为48M,那么串口波特率最高就只能配置到48M/16=3M,是无法配置到更高波特率的。
那么要想配置到更高波特率,需要对此配置软件做哪些修改呢?
显然这里我们需要使用8倍的采样率,才能配置更高的波特率,因为48M/8=6M。那么USART_Config的底层驱动软件需要更改为:
- void USART_Config(USART_T* uart, USART_Config_T* configStruct)
- {
- uint32_t temp, fCLK, intDiv, fractionalDiv;
- uint32_t divider = 0, tmpreg = 0;
-
- /** Disable USART */
- uart->CTRL1_B.UEN = 0x00;
- /** WLS, PCEN, TXEN, RXEN */
- temp = uart->CTRL1;
- temp &= 0xE9F3;
- temp |= (uint32_t)configStruct->mode | \
- (uint32_t)configStruct->parity | \
- (uint32_t)configStruct->wordLength;
- uart->CTRL1 = temp;
- /** STOP bits */
- temp = uart->CTRL2;
- temp &= 0xCFFF;
- temp |= configStruct->stopBits;
- uart->CTRL2 = temp;
- /** Hardware Flow Control */
- temp = uart->CTRL3;
- temp &= 0xFCFF;
- temp |= (uint32_t)configStruct->hardwareFlowCtrl;
- uart->CTRL3 = temp;
- if (uart == USART1)
- {
- fCLK=RCM_ReadUSART1CLKFreq();
- }
- else if (uart == USART2)
- {
- fCLK=RCM_ReadUSART2CLKFreq();
- }
- else
- {
- fCLK=RCM_ReadPCLKFreq();
- }
-
- /* Determine the integer part */
- //if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
- if (uart->CTRL1_B.OSMCFG != RESET)/*!<Ovensampling by 8*/
- {
- /* (divider * 10) computing in case Oversampling mode is 8 Samples */
- divider = (uint32_t)((2 * fCLK) / (configStruct->baudRate));
- tmpreg = (uint32_t)((2 * fCLK) % (configStruct->baudRate));
- }
- else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
- {
- /* (divider * 10) computing in case Oversampling mode is 16 Samples */
- divider = (uint32_t)((fCLK) / (configStruct->baudRate));
- tmpreg = (uint32_t)((fCLK) % (configStruct->baudRate));
- }
- /* round the divider : if fractional part i greater than 0.5 increment divider */
- if (tmpreg >= (configStruct->baudRate) / 2)
- {
- divider++;
- }
- /* Implement the divider in case Oversampling mode is 8 Samples */
- //if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
- if (uart->CTRL1_B.OSMCFG != RESET)
- {
- /* get the LSB of divider and shift it to the right by 1 bit */
- tmpreg = (divider & (uint16_t)0x000F) >> 1;
- /* update the divider value */
- divider = (divider & (uint16_t)0xFFF0) | tmpreg;
- }
- uart->BR = (uint16_t)divider;
- }
这里我们就把8配采样率的配置加进来了,但是当我们运行的时候我们却发现了另外一个问题,那就是串口波特率配置为4M和6M都是没问题的,配置为5M的时候无法正常通讯。这又是怎么一回事呢?原来手册中也给了我们提醒,当使用8倍采样率的时候,可配置更高的通讯速度,但是时钟容忍度较小。因为48可以被4和6整除,但是不能被5整除,这就会造成在串口通讯过程中,串口波特率的时钟周期存在有较大误差,当我们把系统时钟更改为5M*8=40M时,5M的波特率通讯也随之正常。
以上就是如何配置APM32F072的软件底层来实现高速串口波特率通讯的方法,不过极海在下一版SDK中会将此配置方式更新进去,届时请各位工程师留意下载最新的SDK例程库。
|