xamen:STM32H7 USART 时钟初始化

使用芯片 STM32H750XB,板子使用的是 安富莱的 stm32-V7 开发板。

时钟配置

整体功能把握

USART 的时钟源可以来自于 usart_ker_ck 和 usart_pclk:


usart_ker_ck 和 usart_pclk 的来源由下图可知:


以 USART1 为例,我们需要控制 USART16SEL 来选择第一级输入的时钟源。然后再由 USART1EN 和 USART1LPEN 来控制第二级的输出。

实际上,控制第二级的最多可有五个变量:PERxEN、PERxLPEN、PERxAMEN、CPU_state 和 D3_state。


PERxEN、PERxLPEN 和 PERxAMEN 是控制位用于控制时钟输出,CPU_state 是 CPU 的状态位,D3_state 是域的状态位,它们组合起来一起控制某个外设的时钟是否有效。

还是以 USART1 为例,我们分析《STM32H750XB参考手册》中的内容:

  • RCC_APB2ENR寄存器中有一个控制 USART1 的 PERxEN 位,被命名为USART1EN

  • RCC_APB2LPENR寄存器中有一个控制 USART1 的 PERxLPEN 位,被命名为USART1LPEN


    这里我们就能看出 RCC_APB2LPENR 和 RCC_APB2ENR 的区别了,前者控制着 CPU 在睡眠模式下,后者控制这个 USART1 外设是否使能。

  • PERxAMEN这个控制变量对于 USART1 这个外设来说是没有的,其属于低功耗的外设使用,是位于 D3 域的外设才有。其功能和 RCC_APB2ENR、RCC_APB2LPENR 差不多,当 D3 处于 CStop 模式时,控制该外设是否正常工作。

  • 了解了上面三个控制位,CPU_state 和 D3_state 的作用就很明显了。

第一级的时钟来源与配置可以参考

使用 CubeMX 配置 RCC 时钟_Bin Watson的博客-CSDN博客

实战配置

有了上面的了解我们大致知道怎么配置一个 USART 外设的时钟了:

  • (配置第一级输入的时钟源)我们需要根据使用的时钟配置 USARTxSEL,以 USART1 为例就是配置 USAT16SEL,选择使用的时钟;
  • (配置第二级输入控制)设置 PERxLPEN 和 PERxAMEN 两个控制位,控制 USART 在何种情况下会休眠;
  • 设置 PERxEN 启动 USART;
  • static void InitHardUart(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;/* 下面这个配置可以注释掉,预留下来是为了方便以后选择其它时钟使用 默认情况下,USART1和USART6选择的PCLK2,时钟100MHz。 USART2,USART3,UART4,UART5,UART6,UART7和UART8选择的时钟是PLCK1,时钟100MHz。 */RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART16;/* 第一级配置 */RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2; /* 第二级配置 */HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit); #if UART1_FIFO_EN == 1/* 串口1 *//* 使能 GPIO TX/RX 时钟 */USART1_TX_GPIO_CLK_ENABLE();USART1_RX_GPIO_CLK_ENABLE();/* 使能 USARTx 时钟 */USART1_CLK_ENABLE();/* 启动 USART1 */ ...}

    如上,我们设置 USAT16SEL 让其使用 D2PCLK2 作为输入时钟。没有设置 PERxLPEN 则说明使用默认的跟随 CPU 休眠。

    第 21 行 USART1_CLK_ENABLE() 设置了 PERxEN 位:

    #define USART1_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()#define __HAL_RCC_USART1_CLK_ENABLE() do { \ __IO uint32_t tmpreg; \ SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\ /* Delay after an RCC peripheral clock enabling */ \ tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\ UNUSED(tmpreg); \ } while(0)

    USART 发送与接收的实现可以参考 使用RS485芯片进行串口通讯 这篇文章,大体上是实现是相同的,不同的点在于不通过 RS485 进行收发的话,我们只需要直接控制 USART 的收发,而不需要使用回调来控制 RS485 的工作模式。

    相关推荐

    相关文章