历史上的今天
返回首页

历史上的今天

今天是:2024年10月17日(星期四)

正在发生

2018年10月17日 | STM32时钟RCC详解(四)

2018-10-17 来源:eefocus

RCC实例详解

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)//如果定义了这些系统时钟将设为24M,如果没有定义则为72M

 #define SYSCLK_FREQ_24MHz  24000000
#else

 



#define SYSCLK_FREQ_72MHz  72000000      //系统时钟默认值的定义 ,如果没有定义外部高速时钟则用内部高速时钟,为8000000


#endif

 
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)//内外部SRAM选择

#endif

 

#define VECT_TAB_OFFSET  0x0



#ifdef SYSCLK_FREQ_HSE
  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;       
#elif defined SYSCLK_FREQ_24MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;       
#elif defined SYSCLK_FREQ_36MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;       
#elif defined SYSCLK_FREQ_48MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;       
#elif defined SYSCLK_FREQ_56MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;       
#elif defined SYSCLK_FREQ_72MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;       
#else 
  uint32_t SystemCoreClock         = HSI_VALUE;       
#endif

__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};//AHB配方表



static void SetSysClock(void); //设置系统时钟的函数声明
//以下为根据不同的系统时钟的定义来声明用到的相应的函数,为后面的函数调用做好准备
#ifdef SYSCLK_FREQ_HSE
  static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
  static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
  static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
  static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
  static void SetSysClockTo56(void);  
#elif defined SYSCLK_FREQ_72MHz
  static void SetSysClockTo72(void);
#endif

#ifdef DATA_IN_ExtSRAM //外部SRAM选择后的初始化函数声明
  static void SystemInit_ExtMemCtl(void); 
#endif

 

 


void SystemInit (void)//系统初始化函数,设置系统的时钟及时钟中断(在startup_stm32f10x_md.s中调用)(复位RCC时钟配置为默认状态,直到设置时钟函数)
{
 
 
  RCC->CR |= (uint32_t)0x00000001; //内部高速时钟使能,内部8MHz时钟开启

 
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;//MCO微控制器没有时钟输出(对外部引脚),ADC预分频PCLK2 2分频后作为ADC时钟,APB预分频HCLK不分频,AHB预分频SYSCLK不分频,HSI作为系统时钟
                                    //HSI作为系统时钟输出(已输出),SYSCLK=PCLK=PCLK1=PCLK2=8M,ADCCLK=1/2(PCLK2)=4M
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;//同上;RCC->CFGR的27位为保留位始终为0 ,HSI作为系统时钟输出(未输出原因为未编译)
#endif    
  
 
  RCC->CR &= (uint32_t)0xFEF6FFFF;//时钟监测器关闭,HSE振荡器关闭

 
  RCC->CR &= (uint32_t)0xFFFBFFFF;//外部4-25MHz振荡器没有旁路

 
  RCC->CFGR &= (uint32_t)0xFF80FFFF; //PLL时钟1.5倍分频作为USB时钟,PLL 2倍频输出,HSE不分频,HSI时钟2分频后作为PLL输入时钟
                                     //PLLCLK=HSICLK=8M(还未输出),HSECLK=HSEOSC,USBCLK=PLLCLK/1.5 ,除PLL外其他分频系数都为0
#ifdef STM32F10X_CL
 
  RCC->CR &= (uint32_t)0xEBFFFFFF;//CR中的26和28位置0

 
  RCC->CIR = 0x00FF0000;//清除中断标志,关闭一些中断

 
  RCC->CFGR2 = 0x00000000; //没有此寄存器
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
 
  RCC->CIR = 0x009F0000;//清除中断标志,关闭一些中断

 
  RCC->CFGR2 = 0x00000000; //没有此寄存器     
#else
 
  RCC->CIR = 0x009F0000; //清除中断标志,关闭一些中断
#endif
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl();//如果宏定义了外部SRAM则对其初始化控制
  #endif
#endif

 
 
  SetSysClock();//设置系统时钟

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif 
}


void SystemCoreClockUpdate (void)
{
  uint32_t tmp = 0, pllmull = 0, pllsource = 0;

#ifdef  STM32F10X_CL
  uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  uint32_t prediv1factor = 0;
#endif
    
 
  tmp = RCC->CFGR & RCC_CFGR_SWS;
  
  switch (tmp)
  {
    case 0x00: 
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04: 
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08: 

     
      pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
      pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
      
#ifndef STM32F10X_CL      
      pllmull = ( pllmull >> 18) + 2;
      
      if (pllsource == 0x00)
      {
       
        SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {
 #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
       prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
      
       SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 
 #else
       
        if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
        {
          SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
        }
        else
        {
          SystemCoreClock = HSE_VALUE * pllmull;
        }
 #endif
      }
#else
      pllmull = pllmull >> 18;
      
      if (pllmull != 0x0D)
      {
         pllmull += 2;
      }
      else
      {
        pllmull = 13 / 2; 
      }
            
      if (pllsource == 0x00)
      {
       
        SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {
        
       
        prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
        prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
        
        if (prediv1source == 0)
        { 
         
          SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;          
        }
        else
        {
          
         
          prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1;
          pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2; 
          SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         
        }
      }
#endif  
      break;

    default:
      SystemCoreClock = HSI_VALUE;
      break;
  }
  
 
 
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
 
  SystemCoreClock >>= tmp;  
}


static void SetSysClock(void)//根据不同的宏定义,设置不同的系统时钟
{  
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72(); 
#endif
 
  
}

 
#ifdef DATA_IN_ExtSRAM
 
void SystemInit_ExtMemCtl(void) 
{

 
  RCC->AHBENR = 0x00000114;
  
    
  RCC->APB2ENR = 0x000001E0;
  


  


  
  GPIOD->CRL = 0x44BB44BB;  
  GPIOD->CRH = 0xBBBBBBBB;

  GPIOE->CRL = 0xB44444BB;  
  GPIOE->CRH = 0xBBBBBBBB;

  GPIOF->CRL = 0x44BBBBBB;  
  GPIOF->CRH = 0xBBBB4444;

  GPIOG->CRL = 0x44BBBBBB;  
  GPIOG->CRH = 0x44444B44;
   
  

  
  FSMC_Bank1->BTCR[4] = 0x00001011;
  FSMC_Bank1->BTCR[5] = 0x00000200;
}
#endif

#ifdef SYSCLK_FREQ_HSE

static void SetSysClockToHSE(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
      
      
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
 
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  } 

  if (HSEStatus == (uint32_t)0x01)
  {

#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
   
    FLASH->ACR |= FLASH_ACR_PRFTBE;

   
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);

#ifndef STM32F10X_CL
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#else
    if (HSE_VALUE <= 24000000)
 {
      FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
 }
 else
 {
      FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
 }
#endif
#endif
 
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
    
   
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;   

   
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04)
    {
    }
  }
  else
  {
  }  
}
#elif defined SYSCLK_FREQ_24MHz

static void SetSysClockTo72(void)//系统时钟设置为72M:SYSCLK=72M,HCLK=72M,PCLK1=36M(最高36M),PCLK2=72M,ADCCLK=36M,
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;//启动计数,HSE状态
  
      
      
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);//HSE使能
 
 
  do //循环,直到HSE使能成功或者超时
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;//HSE使能成功
  }
  else
  {
    HSEStatus = (uint32_t)0x00;//HSE使能不成功
  } 

  if (HSEStatus == (uint32_t)0x01)//HSE使能成功
  {
   
    FLASH->ACR |= FLASH_ACR_PRFTBE;//flash缓存使能

   
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);//
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;//   

 
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//RCC_CFGR_HPRE_DIV1=0,CFGR中的值不变
      
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//RCC_CFGR_PPRE2_DIV1=0,CFGR中的值不变
    
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//低速APB预分频把HCLK 2分频,APB1CLK=HCLK/2

#ifdef STM32F10X_CL
   
   
   
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
   
    RCC->CR |= RCC_CR_PLL2ON;
   
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
     
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else    
   
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |  //PLL输入时钟源HSI时钟2分频后作为PLL输入时钟,HSE分频器作为PLL输入HSE不分频 
                                        RCC_CFGR_PLLMULL)); //PLL倍频系数PLL 2倍频输出(为了清零其他位)
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//PLL输入时钟源HSE时钟作为PLL输入时钟,PLL倍频系数PLL 9倍频输出 
#endif

   
    RCC->CR |= RCC_CR_PLLON; //PLL使能

   
    while((RCC->CR & RCC_CR_PLLRDY) == 0)//等待PLL使能成功
    {
    }
    
   
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));//HSI作为系统时钟(为了清零其他位)
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //PLL输出作为系统时钟  

   
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)//等待直到PLL成功用作系统时钟源
    {
    }
  }
  else
  {
  }
}
#endif


推荐阅读

史海拾趣

乔光电子(FTR)公司的发展小趣事

Futaba Electric Co., Ltd. 的五个发展故事

故事一:从真空管到VFD的转型

Futaba Electric Co., Ltd.(原名双叶电子)成立于1948年,最初以生产收音机收讯真空管起家。然而,随着技术的飞速发展和市场需求的变迁,公司在1970年做出了关键的战略调整,决定放弃真空管业务,转而专注于萤光表示管(VFD)的研发与生产。这一决定极具前瞻性,因为VFD以其高清晰度、广视角和出色亮度等独特优势,迅速赢得了市场的青睐。Futaba凭借在VFD领域的持续创新和卓越品质,逐渐确立了其在全球市场的领先地位,市场份额超过60%,成为行业内的佼佼者。

故事二:无线电控制技术的突破

进入1960年代,Futaba在电子领域不断拓宽其技术边界。1962年,公司推出了无线电控制设备和冲压金属模用部件,旨在提升工业生产的品质和效率。这一创新不仅解决了工业控制领域中长期存在的供应商品质和交货期问题,还引领了模具制造行业的标准提升。Futaba的无线电控制技术逐渐在模具制造、工业自动化等领域得到广泛应用,为公司后续在无线遥控领域的深入发展奠定了坚实基础。

故事三:无线遥控技术的领导者

随着技术的不断积累和市场的日益扩大,Futaba在无线遥控领域取得了显著成就。特别是在1990年,公司成功研发出高频无线展频通讯技术,该技术以其高可靠性和抗干扰性,在卫星通讯、工业用机器人和工业控制设备等领域展现出巨大潜力。Futaba的无线遥控产品如遥控飞机、车、船等,在休闲娱乐市场也广受欢迎,进一步巩固了公司在无线遥控技术领域的领先地位。

故事四:VFD在汽车行业的广泛应用

Futaba的VFD产品凭借其卓越的性能和稳定的品质,赢得了众多汽车制造商的信赖。自1983年Futaba的VFD产品被福特汽车公司采用以来,其在美国三大汽车厂的市场占有率迅速攀升至100%。这一成就不仅证明了Futaba产品在汽车行业的广泛应用和市场认可度,也为其在高端消费性电子设备市场的进一步拓展提供了有力支持。

故事五:中国市场的深入布局

为了更好地服务于中国市场,Futaba成立了双叶电子科技开发(北京)有限公司,专营日本双叶(Futaba)的全线产品。这家公司在北京设立,不仅负责Futaba真空荧光显示管及模组、RC遥控器等产品的生产和销售,还积极开拓中国市场,参与行业交流和合作。双叶电子科技开发(北京)有限公司的成立,标志着Futaba在全球化战略中对中国市场的高度重视和深入布局。通过不断提升产品质量和服务水平,Futaba在中国市场也取得了显著成绩,为公司的持续发展注入了新的动力。

ADDtek公司的发展小趣事

对不起,我无法提供有关ADDtek公司发展的故事。

川土(Chipanalog)公司的发展小趣事

2016年,上海川土微电子有限公司(简称“川土微电子”)正式成立,标志着Chipanalog川土微电子的诞生。作为一家专注于模拟芯片产品研发与销售的高科技公司,川土微电子从成立之初就明确了其核心使命——为中国电子信息制造企业提供高品质进口替代模拟芯片。在创始人及团队的共同努力下,公司迅速确定了发展方向,并开始着手研发首款模拟芯片产品。

BEKA Associates Ltd公司的发展小趣事

BCD Semi(Diodes)在电子行业中以其卓越的技术实力和持续的产品创新而闻名。近年来,公司成功研发出一系列高性能的模拟半导体产品,这些产品在市场上取得了显著的成功。通过不断优化生产工艺和设计理念,BCD Semi成功提升了产品的性能和可靠性,赢得了客户的广泛认可。同时,公司还积极开拓新的应用领域,将产品应用于汽车、通信、工业控制等多个领域,进一步扩大了市场份额。

Erocore Enterprise Co Ltd公司的发展小趣事

随着全球化趋势的加速,Erocore开始实施国际化战略。公司积极拓展海外市场,通过建立海外生产基地、设立销售办事处等方式,实现产品的全球布局。同时,Erocore也加强了与国际知名企业的合作与交流,引进先进的技术和管理经验,提升公司的整体竞争力。

富瀚(Fullhan)公司的发展小趣事
使用负载设备逐渐增加电动机的负载,直至达到或超过保护器设定的过载保护阈值。

问答坊 | AI 解惑

求职/招聘者请进

电机英才网http://motor.jdjob88.com 是国内唯一专注电机类企业招聘和个人求职的专业性人才网站。电机英才网提供众多人才信息和企业招聘信息,欢迎注册企业招聘会员和个人求职会员,希望您能在电机英才网找到合适的工作或聘请到合适的人员,并祝您 ...…

查看全部问答>

智能机器车论文

              题目名称:智能机器车                           淮安信息职业技术学院  & ...…

查看全部问答>

机器人 转一个国外的机器人项目

http://66.249.89.132/translate_c?hl=zh-CN&sl=en&u=http://www.robotroom.com/Jet.html&prev=/search%3Fq%3DC51%2Bcompiler%26hl%3Dzh-CN%26client%3Daff-cs-360se%26hs%3Dbtg%26sa%3DN%26start%3D50%26newwindow%3D1&usg=ALkJrhhLTO9Bj7aM9-ySHE ...…

查看全部问答>

求硬件资料,写操作系统用,汇编级的,

举个例吧,像下面这样的就可以,简单明白,通俗易懂 7.1.2 可编程间隔定时器PIT 每个PC机中都有一个PIT,以通过IRQ0产生周期性的时钟中断信号。当前使用最普遍的是Intel 8254 PIT芯片,它的I/O端口地址是0x40~0x43。 Intel 8254 PIT有3个计时通 ...…

查看全部问答>

CEF中国电子展金融危机时如何应对?

在CEF中国电子展的展出的电子元器件、电阻电容、电感、变压器、磁性元件、谐振器、振荡器、滤波器、电声器件、连接器、开关、继电器、微特电机、电线电缆、二极管、三极管、电力器件、晶闸管、敏感元件、传感器、电保护器件、LED光电与显示器件、激 ...…

查看全部问答>

拜托各位大虾,迷茫中!!女孩到底适合不适合做嵌入式??????

  学习嵌入式学了一些了,都还没入门。有朋友劝我放弃,觉得女孩做这个没有什么前途。真的迷茫啊,如果不做这个那又做什么呢?女孩到底做什么合适啊!我的很多朋友都在做基础测试,我觉得我现在做好像晚了点,况且还很无聊。我对自己能否 ...…

查看全部问答>

[转贴]DM9000 linux2.6 驱动解析

DM9000 linux2.6 驱动解析,网络上面找的,感觉还不错转帖给需要朋友。 /* *   dm9000.c: Version 1.2 03/18/2003 * *         A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. * & ...…

查看全部问答>

关于8962开发板enet_io例程问题

在enet_io例程中可以通过网页控制开发板的上的外设,我用makefsfile软件成功将网页文件转变为一个.h文件,但是不知道如何在程序中调用这个头文件里的网页内容,希望经验的大侠可以指点指点哈。…

查看全部问答>

热释电传感器

大家好!最近做了个热释电人体感应的电路,为什么上电第一次感应输出反应时间比较慢,以后再感应就没问题基本上和计算的时间差不多!还请高手帮忙解决一下!…

查看全部问答>

msp430 作为游戏把柄玩俄罗斯方块 俄罗斯方块visual basic做的 源码

之前做课程设计vb做的俄罗斯方块电脑运行俄罗斯方块下位机msp430的四个按键操作上下左右 [ 本帖最后由 chouchick 于 2012-6-1 23:09 编辑 ]…

查看全部问答>