库函数及寄存器对应
上图为串口的框图,主要有数据寄存器(DR)、状态寄存器(SR)、波特比率寄存器(BRR)。
数据寄存器(DR)包含接收数据寄存器(RDR)和发送数据寄存器(TDR)等。
串口接收数据流程为:RX接口接收到数据,通过编解码模块传输给“接收移位寄存器”,再传递给“接收数据寄存器(RDR)”,再传输给内核。
串口发送数据流程为:内核将数据写入“发送数据寄存器(TDR)”,再将数据存入“发送移位寄存器”,再将数据通过编解码模块输出到TX接口。
图中的发送器时钟和接收器时钟是通过波特比率寄存器(BRR)的设置来控制的
F103芯片的串口1的时钟来源是PCLK2,串口2-4的时钟开源是PCLK1,由BRR寄存器左侧的“/USARTDIV”设置,参数为1或者2,二者时钟频率默认均为72MHz。
状态寄存器(SR)用于存储串口状态,发送器控制单元和接收器控制单元可以对其状态标志位进行更改,其状态标志位可供中断控制单元获取。
控制寄存器(内部参数用于控制串口)
串口使能函数
#define CR1_UE_Set ((uint16_t)0x2000)
#define CR1_UE_Reset ((uint16_t)0xDFFF)
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters (验证参数)*/
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
/* Enable the selected USART by setting the UE bit in the CR1 register */
/*通过在CR1寄存器中设位13来启用所选的串口*/
if (NewState != DISABLE)
{
USARTx->CR1 |= CR1_UE_Set;
}
/* Disable the selected USART by clearing the UE bit in the CR1 register */
/*通过在CR1寄存器中设位13来禁用所选的串口*/
else
{
USARTx->CR1 &= CR1_UE_Reset;
}
}
状态寄存器(存储串口状态)
获取状态标志位函数
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
#define USART_FLAG_CTS ((uint16_t)0x0200)
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
FlagStatus bitstatus = RESET; //声明枚举变量(状态标记)并初始化为0
/* Check the parameters (验证参数输入是否正确)*/
assert_param(IS_USART_ALL_PERIPH(USARTx)); //验证是否是正确的串口名
assert_param(IS_USART_FLAG(USART_FLAG)); //验证标志
/* The CTS flag is not available for UART4 and UART5 */
/* CTS标志不适用于UART4和UART5。(见上图位9)*/
if (USART_FLAG == USART_FLAG_CTS) //验证串口是否是串口1、2、3
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
//串口号对应的SR寄存器的值与USART_FLAG进行与运算判断对应位的值是否为1来获取串口的状态,
if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET) //若上述计算结果如果不等于0
{
bitstatus = SET; //状态标记设置为1
}
else
{
bitstatus = RESET; //否则为设置0
}
return bitstatus; //返回状态位
}
数据寄存器(存储串口传输数据)
串口发送函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) //发送数据到串口,DR寄存器
{
/* Check the parameters (验证参数) */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
/* Transmit Data (发送数据)*/ //串口号对应的DR寄存器存入Data数据的9位
USARTx->DR = (Data & (uint16_t)0x01FF);
}
串口接收函数
uint16_t USART_ReceiveData(USART_TypeDef* USARTx) //接受数据,从DR读取接受到的数据
{
/* Check the parameters (验证参数) */
assert_param(IS_USART_ALL_PERIPH(USARTx));
/* Receive Data(接受数据) */ //返回寄存器DR寄存器的前9位数据
return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}
波特比率寄存器(设置串口通讯的波特率)
串口初始化函数中的波特率部分
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
{
uint32_t usartxbase = 0 , apbclock = 0x00;
RCC_ClocksTypeDef RCC_ClocksStatus;
usartxbase = (uint32_t)USARTx; //将串口的地址强制转换成32位整数
RCC_GetClocksFreq(&RCC_ClocksStatus); //获取时钟频率
//如果串口地址为串口1的地址则设置时钟源为PCLK2,否则为PCLK1
if (usartxbase == USART1_BASE)
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
……
//将apbclock经过一系列运算(原理见上图)得到tmpreg,并存入BRR寄存器
USARTx->BRR = (uint16_t)tmpreg;
}
文中函数和部分内容摘自正点原子stm32资料与官方库函数