您当前的位置:五五电子网电子知识电子学习基础知识电脑-单片机-自动控制STM32单片机基础学习:从勉强看懂一行程序到IO口研究 正文
STM32单片机基础学习:从勉强看懂一行程序到IO口研究

STM32单片机基础学习:从勉强看懂一行程序到IO口研究

点击数:7210 次   录入时间:03-04 11:37:43   整理:http://www.55dianzi.com   电脑-单片机-自动控制

     刚好勉勉强强看懂一行程序

  继续学习中,先把开发板自带一个例子做了些精简,以免看得吓人。。。。
  
  就是这个,让PORTD上接的4个LED分别点亮。
  开始研究代码
  int main(void)
  {
  Init_All_Periph();
  。。.。。.
  看到这一行,开始跟踪,于是又看到了下面的内容
  void Init_All_Periph(void)
  {
  RCC_Configuration();
  。。.。。.
  继续跟踪
  void RCC_Configuration(void)
  {
  SystEMInit();
  。。.。。.
  这行代码在system_stm32f10x.c中找到了。
  void SystemInit (void)
  {
  /* Reset the RCC cLOCk configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC-》CR |= (uint32_t)0x00000001;
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  #ifndef STM32F10X_CL
  RCC-》CFGR &= (uint32_t)0xF8FF0000;
  #else
  RCC-》CFGR &= (uint32_t)0xF0FF0000;
  #endif /* STM32F10X_CL */
  /* Reset HSEON, CSSON and PLLON bits */
  RCC-》CR &= (uint32_t)0xFEF6FFFF;
  /* Reset HSEBYP bit */
  RCC-》CR &= (uint32_t)0xFFFBFFFF;
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC-》CFGR &= (uint32_t)0xFF80FFFF;
  #ifndef STM32F10X_CL
  /* DISAble all interrupts and clear pending bits */
  RCC-》CIR = 0x009F0000;
  #else
  /* Reset PLL2ON and PLL3ON bits */
  RCC-》CR &= (uint32_t)0xEBFFFFFF;
  /* Disable all interrupts and clear pending bits */
  RCC-》CIR = 0x00FF0000;
  /* Reset CFGR2 register */
  RCC-》CFGR2 = 0x00000000;
  #endif /* STM32F10X_CL */
  /* Configure the System clock Frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();
  }
  这一长串的又是什么,如何来用呢?看来,偷懒是不成的了,只能回过头去研究STM32的时钟构成了。
  相当的复杂。

     系统的时钟可以有3个来源:内部时钟HSI,外部时钟HSE,或者PLL(锁相环模块)的输出。它们由RCC_CFGR寄存器中的SW来选择。
  SW(1:0):系统时钟切换
  由软件置’1’或清’0’来选择系统时钟源。 在从停止或待机模式中返回时或直接或间接作为系统时钟的HSE出现故障时,由硬件强制选择HSI作为系统时钟(如果时钟安全系统已经启动)
  00:HSI作为系统时钟;
  01:HSE作为系统时钟;
  10:PLL输出作为系统时钟;
  11:不可用。
  ////////////////////////////////////////////////////////////////////
  PLL的输出直接送到USB模块,经过适当的分频后得到48M的频率供USB模块使用。
  系统时钟的一路被直接送到I2S模块;另一路经过AHB分频后送出,送往各个系统,其中直接送往SDI,FMSC,AHB总线;8分频后作为系统定时器时钟;经过APB1分频分别控制PLK1、定时器TIM2~TIM7;经过APB2分频分别控制PLK2、定时器TIM1~TIM8、再经分频控制ADC;
  由此可知,STM32F10x芯片的时钟比之于51、AVR、PIC等8位机要复杂复多,因此,我们立足于对着芯片手册来解读程序,力求知道这些程序代码如何使用,为何这么样使用,如果自己要改,可以修改哪些部分,以便自己使用时可以得心应手。
  单步执行,看一看哪些代码被执行了。
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC-》CR |= (uint32_t)0x00000001;
  120S52109-1.jpg
  这是RCC_CR寄存器,由图可见,HSION是其bit 0位。
  HSION:内部高速时钟使能
  由软件置’1’或清零。
  当从待机和停止模式返回或用作系统时钟的外部4-25MHz时钟发生故障时,该位由硬件置’1’来启动内部8MHz的RC振荡器。当内部8MHz时钟被直接或间接地用作或被选择将要作为系统时钟时,该位不能被清零。
  0:内部8MHz时钟关闭;
  1:内部8MHz时钟开启。
  ///////////////////////////////////////////////////////////////////////
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  #ifndef STM32F10X_CL
  RCC-》CFGR &= (uint32_t)0xF8FF0000;
  点击看大图
  这是RCC_CFGR寄存器
  该行程序清零了MC0[2:0]这三位,和ADCPRE[1:0],ppre2[2:0],PPRE1[2:0],HPRE[3:0],SWS[1:0]和SW[1:0]这16位。
  /*
  MCO: 微控制器时钟输出,由软件置’1’或清零。
  0xx:没有时钟输出;
  100:系统时钟(SYSCLK)输出;
  101:内部8MHz的RC振荡器时钟输出;
  110:外部4-25MHz振荡器时钟输出;
  111:PLL时钟2分频后输出。
  */
  /* Reset HSEON, CSSON and PLLON bits */
  RCC-》CR &= (uint32_t)0xFEF6FFFF;
  清零了PLLON,HSEBYP,HSERDY这3位。
  /* Reset HSEBYP bit */
  RCC-》CR &= (uint32_t)0xFFFBFFFF;
  清零了HSEBYP位 ///???为什么不一次写??
  HSEBYP:外部高速时钟旁路,在调试模式下由软件置’1’或清零来旁路外部晶体振荡器。只有在外部4-25MHz振荡器关闭的情况下,才能写入该位。
  0:外部4-25MHz振荡器没有旁路;
  1:外部4-25MHz外部晶体振荡器被旁路。
  所以要先清HSEON位,再清该位。
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC-》CFGR &= (uint32_t)0xFF80FFFF;
  清零了:USBPRE,PLLMUL,PLLXTPR,PLLSRC共7位
  /* Disable all interrupts and clear pending bits */
  RCC-》CIR = 0x009F0000;
  ////这个暂不解读
  SetSysClock();
 跟踪进入该函数,可见一连串的条件编译:

 
  单步运行,执行的是:
  #elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
  为何执行该行呢,找到SYSCLK_PREQ_**的相关定义,如下图所示。
  
  这样就得到了我们所要的一个结论:如果要更改系统工作频率,只需要在这里更改就可以了。
  可以继续跟踪进入这个函数来观察如何将工作频率设定为72MHz的。
  static void SetSysClockTo72(void)
  {
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
  /* Enable HSE */
  RCC-》CR |= ((uint32_t)RCC_CR_HSEON);
  //开启HSE
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
  HSEStatus = RCC-》CR & RCC_CR_HSERDY;
  StartUpCounter++;
  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
  //等待HSE确实可用,这有个标志,即RCC_CR寄存器中的HSERDY位(bit 17),这个等待不会无限长,有个超时策略,即每循环一次计数器加1,如果计数的次数超过HSEStartUp_TimeOut,就退出循环,而这个HSEStartUp_TimeOut在stm32f10x.h中定义,
  #define HSEStartUp_TimeOut ((uint16_t)0x0500) /*!《 Time out for HSE start up */
  ///////////////////////////////////////////////////////////////////////////////////////////////
  if ((RCC-》CR & RCC_CR_HSERDY) != RESET)
  {
  HSEStatus = (uint32_t)0x01;
  }
  else
  {
  HSEStatus = (uint32_t)0x00;
  }
  ///再次判断HSERDY标志位,并据此给HSEStatus变量赋值。
  if (HSEStatus == (uint32_t)0x01)
  {

[1] [2] [3] [4]  下一页


本文关键字:单片机  程序  电脑-单片机-自动控制电子学习 - 基础知识 - 电脑-单片机-自动控制