最近有客户在使用极海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例程库。
|
写的不错