Chinaunix首页 | 论坛 | 博客
  • 博客访问: 609323
  • 博文数量: 107
  • 博客积分: 713
  • 博客等级: 上士
  • 技术积分: 1050
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-05 00:14
个人简介

呵呵

文章分类

全部博文(107)

文章存档

2015年(2)

2014年(17)

2013年(29)

2012年(52)

2011年(7)

分类: 嵌入式

2014-10-12 21:11:42

STM32芯片命名规则:
。。。。
所以stm32  CB为48引脚,128k闪存。

stm32寄存器:
。。。。

1、stm32初始化流程

void RCC_Configuration(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit(); //时钟控制寄存器全部恢复默认值

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON); //外部高速时钟源开启(8M晶振)

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部时钟HSE就绪

  if(HSEStartUpStatus == SUCCESS) //如果时钟启动成功
  {
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); //定义AHB设备时钟为系统时钟1分频,AHB,系统时钟不分频

    /* PCLK2 = HCLK */
   RCC_PCLK2Config(RCC_HCLK_Div1); //定义AHB2设备时钟为HCLK时钟1分频


    /* PCLK1 = HCLK/2 */
   RCC_PCLK1Config(RCC_HCLK_Div2); //定义AHB1设备时钟为HCLK时钟2分频


    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2); //设定内部FLASH的的延时周期为2周期
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能FLASH预存取缓冲区


    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //配置PLL时钟为外部高速时钟的9倍频,8MHz * 9 = 72 MHz

    /* Enable PLL */
    RCC_PLLCmd(ENABLE); //使能PLL时钟

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟设置完成准备就绪
    {
    }
    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //使用PLL时钟作为系统时钟源

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08) //返回系统所用时钟源确认为外部高速晶振,8M晶振。
    {
    }
  }
}

void RCC_DeInit(void)
{
  /* Set HSION bit,打开内部8M的HSI时钟 */
  RCC->CR |= (uint32_t)0x00000001;    //RCC结构体为RCC_TypeDef

  /* Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] and MCO[2:0] bits */
  /*SW=00,SWS=00,设置HSI为系统时钟
   *HPRE=0000,AHB,即SYSCLK不分频
   *PPRE1=000,AHB1(PCLK1)不分频
   *PPRE2=000,AHB2 (PCLK2)不分频
   *ADCPRE=00,PCLK2 两分频后作为ADC时钟
   *MCO=000,没有时钟输出*/
  RCC->CFGR &= (uint32_t)0xF8FF0000;
 
  /* Reset HSEON, CSSON and PLLON bits */
/*HSEON=0,关闭HSE振荡器
CSSON=0,关闭时钟检测器
PLLON=0,PLL关闭*/
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
/*HSEBYP=0,外部4-16M振荡器没旁路*/
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE bits */
/*PLLSRC=0,HSI经过2分频后作为PLL输入时钟
     PLLXTPRE=0.HSE不分频
    PLLMUL=0000,PLL 2倍频输出
USBPRE=0,PLL 1.5倍分频后作为USB时钟*/
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

  /* Disable all interrupts */
//关闭所有时钟中断
  RCC->CIR = 0x00000000;
}

#define RCC                                    ((RCC_TypeDef *) RCC_BASE)
#define RCC_BASE                         (AHBPERIPH_BASE + 0x1000)    //RCC_BASE =  0x40021000
#define AHBPERIPH_BASE            (PERIPH_BASE + 0x20000)        //AHBPERIPH_BASE = 0x40020000
#define PERIPH_BASE                  ((uint32_t)0x40000000)                //PERIPH_BASE = 0x40000000
//所以RCC_BASE = 0x40021000,由上面寄存器表可知这个是复位和时钟控制器RCC

typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;
} RCC_TypeDef;
这个结构体根据寄存器定义,如下图所示
总结:RCC_DeInit();  所做的工作就是在系统初始的时候关闭HSE时钟,打开HSI作为时钟,并关闭时钟中断



void RCC_HSEConfig(uint32_t RCC_HSE)
{
  /* Check the parameters */
/*不做实质上的操作*/
  assert_param(IS_RCC_HSE(RCC_HSE));

  /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/
  /* Reset HSEON bit */
/*#define CR_HSEON_Reset ((uint32_t)0xFFFEFFFF)
#define CR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF)
   设置HSE之前需要复位HSEON,HSEBYP,这两位写0*/
  RCC->CR &= CR_HSEON_Reset;
  /* Reset HSEBYP bit */
  RCC->CR &= CR_HSEBYP_Reset;

  /* Configure HSE (RCC_HSE_OFF is already covered by the code section above) */
  switch(RCC_HSE)
  {
    /*RCC_HSE= RCC_HSE_ON,所以执行这条
    #define CR_HSEON_Set ((uint32_t)0x00010000),开启HSE振荡器*/
    case RCC_HSE_ON:
      /* Set HSEON bit */
      RCC->CR |= CR_HSEON_Set;
      break;
     
    case RCC_HSE_Bypass:
      /* Set HSEBYP and HSEON bits */
      RCC->CR |= CR_HSEBYP_Set | CR_HSEON_Set;
      break;
     
    default:
      break;
  }
}
总结:打开HSE时钟


ErrorStatus RCC_WaitForHSEStartUp(void)
{
  __IO uint32_t StartUpCounter = 0;
  ErrorStatus status = ERROR;
  FlagStatus HSEStatus = RESET;
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);         //#define RCC_FLAG_HSERDY ((uint8_t)0x31)
    StartUpCounter++;
  } while((HSEStatus == RESET) && (StartUpCounter != HSEStartUp_TimeOut));
  if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET)
  {
    status = SUCCESS;
  }
  else
  {
    status = ERROR;
  }
  return (status);
}

FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)
{
  uint32_t tmp = 0;
  uint32_t statusreg = 0;
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_RCC_FLAG(RCC_FLAG));
  /* Get the RCC register index */
  tmp = RCC_FLAG >> 5;        //RCC_FLAG = 0x31,tmp = 1
  if (tmp == 1) /* The flag to check is in CR register */
  {
    statusreg = RCC->CR;       // 读取RCC->CR寄存器
  }
  else if (tmp == 2) /* The flag to check is in BDCR register */
  {
    statusreg = RCC->BDCR;
  }
  else /* The flag to check is in CSR register */
  {
    statusreg = RCC->CSR;
  }
  /* Get the flag position */
  tmp = RCC_FLAG & FLAG_Mask;    //tmp = 0x31 & 1f = 0x11
  if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)    //检测RCC->HSERDY,如果HSE准备好了,则bitstatus = SET,(RESET = 0, SET = !RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  /* Return the flag status */
  return bitstatus;
}
总结:等待HSE时钟准备完毕,HSE准备完毕则返回SUCCES

void RCC_HCLKConfig(uint32_t RCC_SYSCLK)        //RCC_SYSCLK = RCC_SYSCLK_Div1    #define RCC_SYSCLK_Div1 ((uint32_t)0x00000000)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_RCC_HCLK(RCC_SYSCLK));
  tmpreg = RCC->CFGR;
  /* Clear HPRE[3:0] bits,RCC->CFGR->HPRE清零,表示SYSCLK不分频 */
  tmpreg &= CFGR_HPRE_Reset_Mask;    //#define CFGR_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F)
  /* Set HPRE[3:0] bits according to RCC_SYSCLK value ,*/
  tmpreg |= RCC_SYSCLK;    //RCC_SYSCLK = RCC_SYSCLK_Div1    #define RCC_SYSCLK_Div1 ((uint32_t)0x00000000)
  /* Store the new value */
  RCC->CFGR = tmpreg;
}

void RCC_PCLK2Config(uint32_t RCC_HCLK)               //#define RCC_HCLK_Div1 ((uint32_t)0x00000000),    RCC_HCLK = RCC_HCLK_Div1
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_RCC_PCLK(RCC_HCLK));
  tmpreg = RCC->CFGR;
  /* Clear PPRE2[2:0] bits */
  tmpreg &= CFGR_PPRE2_Reset_Mask;    //#define CFGR_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF)
  /* Set PPRE2[2:0] bits according to RCC_HCLK value */
  tmpreg |= RCC_HCLK << 3;
  /* Store the new value */
  RCC->CFGR = tmpreg;
}

void RCC_PCLK1Config(uint32_t RCC_HCLK)        //RCC_HCLK = #define RCC_HCLK_Div2 ((uint32_t)0x00000400)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_RCC_PCLK(RCC_HCLK));
  tmpreg = RCC->CFGR;
  /* Clear PPRE1[2:0] bits ,PPRE1清零*/ 
  tmpreg &= CFGR_PPRE1_Reset_Mask;    //#define CFGR_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF)
  /* Set PPRE1[2:0] bits according to RCC_HCLK value */
  tmpreg |= RCC_HCLK;   //2分频
  /* Store the new value */
  RCC->CFGR = tmpreg;
}

void FLASH_SetLatency(uint32_t FLASH_Latency)    //#define FLASH_Latency_2 ((uint32_t)0x00000002) 
{
  uint32_t tmpreg = 0;
 
  /* Check the parameters */
  assert_param(IS_FLASH_LATENCY(FLASH_Latency));
 
  /* Read the ACR register */
  tmpreg = FLASH->ACR;
 
  /* Sets the Latency value */
  tmpreg &= ACR_LATENCY_Mask;    //#define ACR_LATENCY_Mask ((uint32_t)0x00000038)
  tmpreg |= FLASH_Latency;        //2个等待状态
 
  /* Write the ACR register */
  FLASH->ACR = tmpreg;
}

void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer)    // //#define FLASH_PrefetchBuffer_Enable ((uint32_t)0x00000010)
{
  /* Check the parameters */
  assert_param(IS_FLASH_PREFETCHBUFFER_STATE(FLASH_PrefetchBuffer));
 
  /* Enable or disable the Prefetch Buffer */
  FLASH->ACR &= ACR_PRFTBE_Mask;
  FLASH->ACR |= FLASH_PrefetchBuffer;
}

void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)    //#define RCC_PLLSource_HSE_Div1 ((uint32_t)0x00010000),    #define RCC_PLLMul_9 ((uint32_t)0x001C0000)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));
  assert_param(IS_RCC_PLL_MUL(RCC_PLLMul));
  tmpreg = RCC->CFGR;
  /* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits ,清零LLSRC, PLLXTPRE and PLLMUL[3:0]*/ 
  tmpreg &= CFGR_PLL_Mask;        //#define CFGR_PLL_Mask ((uint32_t)0xFFC0FFFF)
  /* Set the PLL configuration bits ,HSE作为PLL时钟输入,PLL 9倍输出,即,如果HSE = 8M,则PLL = 72M*/
  tmpreg |= RCC_PLLSource | RCC_PLLMul; // RCC_PLLSource =  ((uint32_t)0x00010000),RCC_PLLMul = ((uint32_t)0x001C0000)
  /* Store the new value */
  RCC->CFGR = tmpreg;
}

void RCC_PLLCmd(FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  *(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState;      //?????
}

     #define CR_PLLON_BB     (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4)),
    #define PERIPH_BB_BASE            ((uint32_t)0x42000000),
    #define CR_OFFSET                     (RCC_OFFSET + 0x00)
    #define RCC_OFFSET                    (RCC_BASE - PERIPH_BASE)
    #define RCC_BASE                      (AHBPERIPH_BASE + 0x1000)
    #define AHBPERIPH_BASE            (PERIPH_BASE + 0x20000)
    #define PLLON_BitNumber 0x18
    所以 CR_PLLON_BB = 0x42000000 +0x21000*32 + 0x18 * 4 = 0x42000000 + 0x420000 + 0x60 = 0x42420060 



void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)        //#define RCC_SYSCLKSource_PLLCLK ((uint32_t)0x00000002)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));
  tmpreg = RCC->CFGR;
  /* Clear SW[1:0] bits */
  tmpreg &= CFGR_SW_Mask;
  /* Set SW[1:0] bits according to RCC_SYSCLKSource value */
  tmpreg |= RCC_SYSCLKSource;
  /* Store the new value */
  RCC->CFGR = tmpreg;
}
设置PLL输出作为系统时钟





阅读(3123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~