细数STM32F103的那些坑——串口篇
作者:互联网
1、串口时钟
- GPIO外设时钟都挂载在APB1总线上
- 串口1的时钟挂在APB2上,而串口2、串口3则是挂在APB1上
所以,在初始化串口1时,我们可以使用以下代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
却不可以使用以下代码初始化串口2、串口3:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART2|RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART2|RCC_APB2Periph_GPIOB, ENABLE);
若要正确初始化串口相关时钟并且兼顾代码风格的统一性,推荐使用:
//串口1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
//串口2:
RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART2, ENABLE); //使能USART2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
//串口3:
RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART3, ENABLE); //使能USART3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟
2、串口中断
在进入串口中断后,需要对中断的类型进行判断,这里有两个容易混用的函数:
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint32_t USART_IT)
该函数不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断。所以在串口中断函数中,如果要获取中断标志位,通常使用该函数。
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint32_t USART_FLAG)
该函数只判断标志位。在没有使能相应的中断时,通常使用该函数来判断标志位是否置1。
在串口中断中,使用的应该是函数USART_GetITStatus(),而USART_GetFlagStatus()通常用在串口轮询的场合。
参考:https://www.cnblogs.com/leo0621/p/8709944.html
串口中断函数常用代码如下:
void USART1_IRQHandler(void)
{
uint8_t data;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收寄存器非空中断
{
data = USART_ReceiveData(USART1); //读取字符
//添加你的代码
}
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //发送寄存器空中断
{
//添加你的代码
//如果所有数据都已发送完毕,则关闭发送中断
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
}
更加丧心病狂一点的写法:(参考资料:https://blog.csdn.net/xiahailong90/article/details/94595005)
void USART1_IRQHandler(void)
{
uint8_t data;
if (USART_GetFlagStatus(USART1, USART_FLAG_PE) != RESET)
{
USART_ReceiveData(USART1);
USART_ClearFlag(USART1, USART_FLAG_PE);
}
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
{
USART_ReceiveData(USART1);
USART_ClearFlag(USART1, USART_FLAG_ORE);
}
if (USART_GetFlagStatus(USART1, USART_FLAG_FE) != RESET)
{
USART_ReceiveData(USART1);
USART_ClearFlag(USART1, USART_FLAG_FE);
}
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收寄存器非空中断
{
USART_ClearFlag(USART1, USART_FLAG_RXNE);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
data = USART_ReceiveData(USART1); //读取字符
//添加你的代码
}
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //发送寄存器空中断
{
USART_ClearFlag(USART1, USART_FLAG_TXE);
USART_ClearITPendingBit(USART1, USART_IT_TXE);
//添加你的代码
//如果所有数据都已发送完毕,则关闭发送中断
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
}
素手执锐血衊白衣
发布了17 篇原创文章 · 获赞 10 · 访问量 2万+
私信
关注
标签:STM32F103,细数,ENABLE,USART,串口,APB2Periph,USART1,RCC 来源: https://blog.csdn.net/qq_17459305/article/details/104126735