STM32 RCC位域初始化时钟

简介

  1. 使用位域初始化RCC寄存器。
  2. 学习使用CobeMX生成代码。
  3. 使用RM0008.pdf创建自己的RCC寄存器。
  4. 初始化STM32时钟代替CobeMX生成的函数并运行查看RCC是否被正常初始化。

项目地址

地址
博客地址

实现

生成代码

  • 使用CobeMX初始化代码

uVision编写

  1. 创建自己的RCC.h

    • 参考文献可以看到RCC所有的寄存器,按照文献相应创建结构体,并设置位域。

      #ifndef __LkkRccInit_H_
      #define __LkkRccInit_H_
      #include "stm32f1xx_hal.h"
      
      typedef struct {
          uint32_t HSION : 1;
          uint32_t HSIRDY : 1;
          uint32_t RES0 : 1;
          uint32_t HSITRIM : 5;
          uint32_t HSICAL : 8;
          uint32_t HSEON : 1;
          uint32_t HSERDY : 1;
          uint32_t HSEBYP : 1;
          uint32_t CSSON : 1;
          uint32_t RES1 : 4;
          uint32_t PLLON : 1;
          uint32_t PLLRDY : 1;
          uint32_t RES2 : 6;
      }Rcc_CR;
      typedef struct {
          uint32_t SW : 2;
          uint32_t SWS : 2;
          uint32_t HPRE : 4;
          uint32_t PPRE1 : 3;
          uint32_t PPRE2 : 3;
          uint32_t ADCPRE : 2;
          uint32_t PLLSRC : 1;
          uint32_t PLLXTPRE : 1;
          uint32_t PLLMUL : 4;
          uint32_t USBPRE : 1;
          uint32_t RES0 : 1;
          uint32_t MCO : 3;
          uint32_t RES1 : 5;
      }Rcc_CFGR;
      typedef struct {
          uint32_t LSIRDYF : 1;
          uint32_t LSERDYF : 1;
          uint32_t HSIRDYF : 1;
          uint32_t HSERDYF : 1;
          uint32_t PLLRDYF : 1;
          uint32_t RES0 : 2;
          uint32_t CSSF : 1;
          uint32_t LSIRDYIE : 1;
          uint32_t LSERDYIE : 1;
          uint32_t HSIRDYIE : 1;
          uint32_t HSERDYIE : 1;
          uint32_t PLLRDYIE : 1;
          uint32_t RES1 : 3;
          uint32_t LSIRDYC : 1;
          uint32_t LSERDYC : 1;
          uint32_t HSIRDYC : 1;
          uint32_t HSERDYC : 1;
          uint32_t PLLRDYC : 1;
          uint32_t RES2 : 2;
          uint32_t CSSC : 1;
          uint32_t RES3 : 8;
      }Rcc_CIR;
      typedef struct {
          uint32_t AFIORST : 1;
          uint32_t RES0 : 1;
          uint32_t IOPARST : 1;
          uint32_t IOPBRST : 1;
          uint32_t IOPCRST : 1;
          uint32_t IOPDRST : 1;
          uint32_t IOPERST : 1;
          uint32_t IOPFRST : 1;
          uint32_t IOPGRST : 1;
          uint32_t ADC1RST : 1;
          uint32_t ADC2RST : 1;
          uint32_t TIM1RST : 1;
          uint32_t SPI1RST : 1;
          uint32_t TIM8RST : 1;
          uint32_t USART1RST : 1;
          uint32_t ADC3RST : 1;
          uint32_t RES1 : 3;
          uint32_t TIM9RST : 1;
          uint32_t TIM10RST : 1;
          uint32_t TIM11RST : 1;
          uint32_t RES2 : 10;
      }Rcc_APB2RSTR;
      typedef struct {
          uint32_t TIM2RST : 1;
          uint32_t TIM3RST : 1;
          uint32_t TIM4RST : 1;
          uint32_t TM5RST : 1;
          uint32_t TM6RST : 1;
          uint32_t TM7RST : 1;
          uint32_t TIM12RST : 1;
          uint32_t TIM13RST : 1;
          uint32_t TIM14RST : 1;
          uint32_t RES0 : 2;
          uint32_t WWDGRST : 1;
          uint32_t RES1 : 2;
          uint32_t SPI2RST : 1;
          uint32_t SPI3RST : 1;
          uint32_t RES2 : 1;
          uint32_t USART2RST : 1;
          uint32_t USART3RST : 1;
          uint32_t UART4RST : 1;
          uint32_t UART5RST : 1;
          uint32_t I2C1RST : 1;
          uint32_t I2C2RST : 1;
          uint32_t USBRST : 1;
          uint32_t RES3 : 1;
          uint32_t CANRST : 1;
          uint32_t RES4 : 1;
          uint32_t BKPRST : 1;
          uint32_t PWRRST : 1;
          uint32_t DACRST : 1;
          uint32_t RES5 : 2;
      }Rcc_APB1RSTR;
      typedef struct {
          uint32_t DMA1EN : 1;
          uint32_t DMA2EN : 1;
          uint32_t SRAMEN : 1;
          uint32_t RES0 : 1;
          uint32_t FLITFEN : 1;
          uint32_t RES1 : 1;
          uint32_t CRCEN : 1;
          uint32_t RES2 : 1;
          uint32_t FSMCEN : 1;
          uint32_t RES3 : 1;
          uint32_t SDIOEN : 1;
          uint32_t RES4 : 21;
      }Rcc_AHBENR;
      typedef struct {
          uint32_t AFIOEN : 1;
          uint32_t RES0 : 1;
          uint32_t IOPAEN : 1;
          uint32_t IOPBEN : 1;
          uint32_t IOPCEN : 1;
          uint32_t IOPDEN : 1;
          uint32_t IOPEEN : 1;
          uint32_t IOPFEN : 1;
          uint32_t IOPGEN : 1;
          uint32_t ADC1EN : 1;
          uint32_t ADC2EN : 1;
          uint32_t TIM1EN : 1;
          uint32_t SPI1EN : 1;
          uint32_t TIM8EN : 1;
          uint32_t USART1EN : 1;
          uint32_t ADC3EN : 1;
          uint32_t RES1 : 3;
          uint32_t TIM9EN : 1;
          uint32_t TIM10EN : 1;
          uint32_t TIM11EN : 1;
          uint32_t RES2 : 10;
      }Rcc_APB2ENR;
      typedef struct {
          uint32_t TIM2EN : 1;
          uint32_t TIM3EN : 1;
          uint32_t TIM4EN : 1;
          uint32_t TIM5EN : 1;
          uint32_t TIM6EN : 1;
          uint32_t TIM7EN : 1;
          uint32_t TIM12EN : 1;
          uint32_t TIM13EN : 1;
          uint32_t TIM14EN : 1;
          uint32_t RES0 : 2;
          uint32_t WWDGEN : 1;
          uint32_t RES1 : 2;
          uint32_t SPI2EN : 1;
          uint32_t SPI3EN : 1;
          uint32_t RES2 : 1;
          uint32_t USART2EN : 1;
          uint32_t USART3EN : 1;
          uint32_t UART4EN : 1;
          uint32_t UART5EN : 1;
          uint32_t I2C1EN : 1;
          uint32_t I2C2EN : 1;
          uint32_t USBEN : 1;
          uint32_t RES3 : 1;
          uint32_t CANEN : 1;
          uint32_t RES4 : 1;
          uint32_t BKPEN : 1;
          uint32_t PWREN : 1;
          uint32_t DACEN : 1;
          uint32_t RES5 : 2;
      }Rcc_APB1ENR;
      typedef struct {
          uint32_t LSEON : 1;
          uint32_t LSERDY : 1;
          uint32_t LSEBYP : 1;
          uint32_t RES0 : 5;
          uint32_t RTCSEL : 2;
          uint32_t RES1 : 5;
          uint32_t RTCEN : 1;
          uint32_t BDRST : 1;
          uint32_t RES2 : 15;
      }Rcc_BDCR;
      typedef struct{
      	uint32_t LSION:1;
      	uint32_t LSIRDY:1;
      	uint32_t RES0:22;
      	uint32_t RMVF:1;
      	uint32_t RES1:1;
      	uint32_t PINRSTF:1;
      	uint32_t PORRSTF:1;
      	uint32_t SFTRSTF:1;
      	uint32_t IWDGRSTF:1;
      	uint32_t WWDGRSTF:1;
      	uint32_t LPWRRSTF:1;
      }Rcc_CSR;
      typedef struct {
          Rcc_CR rcc_CR;
          Rcc_CFGR rcc_CFGR;
          Rcc_CIR rcc_CIR;
          Rcc_APB2RSTR rcc_APB2RSTR;
          Rcc_APB1RSTR rcc_APB1RSTR;
          Rcc_AHBENR rcc_AHBENR;
          Rcc_APB2ENR rcc_APB2ENR;
          Rcc_APB1ENR rcc_APB1ENR;
          Rcc_BDCR rcc_BDCR;
      	Rcc_CSR rcc_CSR;
      }Lkk_Rcc;
      
      
      typedef struct {
          uint32_t LPDS : 1;
          uint32_t PDDS : 1;
          uint32_t CWUF : 1;
          uint32_t CSBF : 1;
          uint32_t PVDE : 1;
          uint32_t PLS : 3;
          uint32_t DBP : 1;
          uint32_t RES0 : 23;
      }Pwr_CR;
      typedef struct {
          uint32_t WUF : 1;
          uint32_t SBF : 1;
          uint32_t PVDO : 1;
          uint32_t RES0 : 5;
          uint32_t EWUP : 1;
          uint32_t RES1 : 23;
      }Pwr_CSR;
      
      typedef struct {
          Pwr_CR pwr_CR;
          Pwr_CSR pwr_CSR;
      }Lkk_Pwr;
      
      typedef struct {
          uint32_t LATENCY : 3;
          uint32_t HLFCYA : 1;
          uint32_t PRFTBE : 1;
          uint32_t PRFTBS : 1;
          uint32_t RES0 : 26;
      }Lkk_FLASH_ACR;
      
      typedef struct {
          Lkk_FLASH_ACR lkk_flash_ACR;
      }Lkk_FLASH;
      #endif /* __My_RCC_H_ */
      
  2. 编写RCC.c初始化RCC

    • RCC分配地址
    Lkk_Rcc *lkk_Rcc = (Lkk_Rcc *) 0x40021000UL; 
    Lkk_FLASH *lkk_FlASH = (Lkk_FLASH *) 0x40022000UL;
    Lkk_Pwr *lkk_PWR = (Lkk_Pwr*)0x40007000UL;
    

    这里也初始化了FLASHPWR,因为通过调试发现RCC初始化时也会涉及到他俩。

    地址可以参考我上传的RM0008.pdf的第50页(Memory Map)。

    • 开启时钟,我选择的是HSI,与CobeMX的时钟树相对应
    /**
    	Rcc_CR init
    **/
    lkk_Rcc->rcc_CR.HSION = 0x1; //open HSI
    lkk_Rcc->rcc_CR.HSIRDY = 0x1;//ready HSI
    lkk_Rcc->rcc_CR.HSITRIM = 0x10;//HSI adjustment
    lkk_Rcc->rcc_CR.HSICAL = 0x0;//HSI correcting
    
    • 关闭HSE

      //close HSE
      lkk_Rcc->rcc_CR.HSEON = 0x0;
      lkk_Rcc->rcc_CR.HSERDY = 0x0;
      lkk_Rcc->rcc_CR.HSEBYP = 0x0;
      lkk_Rcc->rcc_CR.CSSON = 0x0;
      
    • 关闭PLL初始化PLLMUL

      /**
      	PLL frequency doubling coefficient
      	The PLL frequency doubling coefficient is determined by software settings. 
      	It can only be written when PLL is off
      **/
      lkk_Rcc->rcc_CR.PLLON = 0x0; 
      lkk_Rcc->rcc_CFGR.PLLMUL = 0x0E;
      	
      
    • 初始化RCC_CFGR

      /**
      	Rcc_CFGR init
      **/
      lkk_Rcc->rcc_CFGR.SW = 0x02; //System clock switching
      lkk_Rcc->rcc_CFGR.SWS = 0x02;	
      lkk_Rcc->rcc_CFGR.HPRE = 0x0;	//AHB Prescaler
      lkk_Rcc->rcc_CFGR.PPRE1 = 0x04;	//APB1 Prescaler
      lkk_Rcc->rcc_CFGR.PPRE2 = 0x0;	//APB2 Prescaler
      lkk_Rcc->rcc_CFGR.ADCPRE = 0x0;	//ADC Prescaler
      lkk_Rcc->rcc_CFGR.PLLSRC = 0x0;	//PLL input clock source
      lkk_Rcc->rcc_CFGR.MCO = 0x0;	//MCO microcontroller clock output : None
      
    • 初始化RCC_AHBENR

      //Rcc_AHBENR init
      lkk_Rcc->rcc_AHBENR.SRAMEN = 0x1;	//SRAM clock enable
      
    • 初始化FLASH

      /**
      	FLASH
      **/
      
      lkk_FlASH->lkk_flash_ACR.LATENCY = 0x02;
      lkk_FlASH->lkk_flash_ACR.PRFTBE = 0x0;
      lkk_Rcc->rcc_AHBENR.FLITFEN = 0x1;	//Flash memory interface circuit clock enable
      
    • 初始化RCC_APB2ENR

      //Rcc_APB2ENR init
      lkk_Rcc->rcc_APB2ENR.AFIOEN = 0x1; //Auxiliary function IO clock enable
      lkk_Rcc->rcc_APB2ENR.IOPAEN = 0x1;	//IO port a clock enable
      lkk_Rcc->rcc_APB2ENR.IOPCEN = 0x1;	//IO port c clock enable
      lkk_Rcc->rcc_APB2ENR.IOPDEN = 0x1;	//IO port d clock enable
      
    • 初始化RCC_APB1ENR

      lkk_Rcc->rcc_APB1ENR.PWREN = 0x1;
      
    • 初始化RCC_BDCR

      //Rcc_BDCR init
      lkk_Rcc->rcc_BDCR.RTCSEL = 0x0;
      
    • 初始化RCC_CSR

      //Rcc_CSR init
      lkk_Rcc->rcc_CSR.PINRSTF = 0x1;
      lkk_Rcc->rcc_CSR.PORRSTF = 0x1;
      lkk_Rcc->rcc_CR.PLLON = 0x1;
      //初始化了RLLMUL后再打开!!!
      //原理见RM0008.pdf的第102页
      
    • 初始化PWR

      //PWR	
      lkk_PWR->pwr_CR.PLS = 0x00;
      
    • 完整初始化函数

      #include "LkkRccInit.h"
      void Lkk_Clock_Config(void){
      	Lkk_Rcc *lkk_Rcc = (Lkk_Rcc *) 0x40021000UL; 
      	Lkk_FLASH *lkk_FlASH = (Lkk_FLASH *) 0x40022000UL;
      	Lkk_Pwr *lkk_PWR = (Lkk_Pwr*)0x40007000UL;
      	/**
      		Rcc_CR init
      	**/
          lkk_Rcc->rcc_CR.HSION = 0x1; //open HSI
      	lkk_Rcc->rcc_CR.HSIRDY = 0x1;//ready HSI
      	
      	lkk_Rcc->rcc_CR.HSITRIM = 0x10;//HSI adjustment
      	lkk_Rcc->rcc_CR.HSICAL = 0x0;//HSI correcting
      	
      	//close HSE
      	lkk_Rcc->rcc_CR.HSEON = 0x0;
      	lkk_Rcc->rcc_CR.HSERDY = 0x0;
      	lkk_Rcc->rcc_CR.HSEBYP = 0x0;
      	lkk_Rcc->rcc_CR.CSSON = 0x0;
      	
      	/**
      		PLL frequency doubling coefficient
      		The PLL frequency doubling coefficient is determined by software settings. 
      		It can only be written when PLL is off
      	**/
      	lkk_Rcc->rcc_CR.PLLON = 0x0; 
      	lkk_Rcc->rcc_CFGR.PLLMUL = 0x0E;
      	
      	/**
      		Rcc_CFGR init
      	**/
      	
      	lkk_Rcc->rcc_CFGR.SW = 0x02; //System clock switching
      	lkk_Rcc->rcc_CFGR.SWS = 0x02;
      	
      	lkk_Rcc->rcc_CFGR.HPRE = 0x0;	//AHB Prescaler
      	lkk_Rcc->rcc_CFGR.PPRE1 = 0x04;	//APB1 Prescaler
      	lkk_Rcc->rcc_CFGR.PPRE2 = 0x0;	//APB2 Prescaler
      	lkk_Rcc->rcc_CFGR.ADCPRE = 0x0;	//ADC Prescaler
      	lkk_Rcc->rcc_CFGR.PLLSRC = 0x0;	//PLL input clock source
      	
      	lkk_Rcc->rcc_CFGR.MCO = 0x0;	//MCO microcontroller clock output : None
      	
      	//Rcc_AHBENR init
      	lkk_Rcc->rcc_AHBENR.SRAMEN = 0x1;	//SRAM clock enable
      	
      	/**
      		FLASH
      	**/
      
      	lkk_FlASH->lkk_flash_ACR.LATENCY = 0x02;
      	lkk_FlASH->lkk_flash_ACR.PRFTBE = 0x0;
      	
      	lkk_Rcc->rcc_AHBENR.FLITFEN = 0x1;	//Flash memory interface circuit clock enable
      	
      	//Rcc_APB2ENR init
      	lkk_Rcc->rcc_APB2ENR.AFIOEN = 0x1; //Auxiliary function IO clock enable
      	lkk_Rcc->rcc_APB2ENR.IOPAEN = 0x1;	//IO port a clock enable
      	lkk_Rcc->rcc_APB2ENR.IOPCEN = 0x1;	//IO port c clock enable
      	lkk_Rcc->rcc_APB2ENR.IOPDEN = 0x1;	//IO port d clock enable
      	
      	//Rcc_APB1ENR init
      	lkk_Rcc->rcc_APB1ENR.PWREN = 0x1;
      	
      	//Rcc_BDCR init
      	lkk_Rcc->rcc_BDCR.RTCSEL = 0x0;
      	
      	//Rcc_CSR init
      	lkk_Rcc->rcc_CSR.PINRSTF = 0x1;
      	lkk_Rcc->rcc_CSR.PORRSTF = 0x1;
      	
      	lkk_Rcc->rcc_CR.PLLON = 0x1;
      
      	//PWR
      	lkk_PWR->pwr_CR.PLS = 0x00;
      }
      
  3. main.c添加自定的RCC头文件,引入初始化函数代替

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under BSD 3-Clause license,
      * the "License"; You may not use this file except in compliance with the
      * License. You may obtain a copy of the License at:
      *                        opensource.org/licenses/BSD-3-Clause
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "LkkRccInit.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    /* USER CODE BEGIN PFP */
    void Lkk_Clock_Config(void);
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
      Lkk_Clock_Config();
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      /* USER CODE BEGIN 2 */
      
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    

软仿真查看

  • 选择RCC,单步跟踪查看
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高明爱圣子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值