.stm32的启动过程

  在stm32的开发中,芯片的启动代码官方通常会提供,一般不需要修改。但是对芯片的启动代码有一定了解,有助于对某些组件工作原理加深了解

  可以借助官方提供的启动代码来理解启动过程,启动代码是一个汇编文件(.s作为后缀),我们开发板的启动文件是start_stm32f40_41xxx.s

1.初始化栈

2.初始化堆

3.实现异常向量表

4.处理各个异常的代码

    其中复位异常中 ----- 初始化一些基本硬件(时钟,SRAM,FLASH...),调用主函数

 

.stm32的时钟系统

  stm32f407的推荐时钟频率 168MHz

1.提供参考时钟的硬件

  晶振 ----------- 产生低频的稳定震荡信号

  RC震荡电路 ----- 产生低频的不稳定震荡信号

以上产生的频率不足以直接供给CPU使用,实际上使用PLL(锁相环)通过一个低频信号产生一个高频信号,供给CPU使用

2019年9月9日星期一(STM32 内部时钟 中断)

 

 

    

stm32f407一共4个原始时钟源

    HSIRC -------- 高速内部RC震荡时钟(16M)

    HSEOSC -------- 高速外部晶振(4-26M)

    LSIRC -------- 低速内部RC震荡时钟(32K)

    LSEOSC ------- 低速外部晶振(32.768K)

2.stm32f407时钟树

2019年9月9日星期一(STM32 内部时钟 中断)

 

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 


   

                    

绝大多数的外设挂在AHB总线和APB总线上,这些总线上的频率和系统频率一起提供,可选(HSI HSE PLL)

其中RTC和看门狗通常使用独立的时钟源,RTC使用LSE,看门狗使用LSI

3.PLL锁相环频率配置

    PLL输出频率(168M) = f时钟输入(8M) X PLLN / (PLLM X PLLP)

    168 =                     8 X      336 /  (8    X   2)

4.修改工程中PLL配置,让主频为168M

1system_stm32f4xx.c文件中

第316行改为

     2019年9月9日星期一(STM32 内部时钟 中断)

 

 

2stm32f4xx.h

第123行改为

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

.GPIO输入

1.原理图

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

  如果按键按下去,接地,管脚低电平

  案件松开,由于上拉电阻,管脚高电平

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

    

    连接到了CPU的PA0 PE2 PE3 PE4

2.硬件说明手册()

3.查看芯片参考手册,库函数手册

    输入数据的获取通过读输入数据寄存器

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

  获取输入电平的库函数

        uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

        参数:

            GPIOx - 哪一组GPIO

            GPIO_Pin - 哪一个脚

        返回对应脚的状态(1 - 高电平 0 - 低电平)

 

物理按键在理想情况下按下松开是如下的电平信号

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

实际上物理按键在按下和松开的时候会有一段时间的抖动(<10ms),造成发生多次按键操作的假象,我们需要通过延时操作消除抖动

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

 消抖的代码

    if(按下){

        //延时10ms

        if(按下){

            //真实按键事件

        }

    }

以上的按键驱动叫做轮询操作,轮询操作实现简单,但是效率比较低

更多的时候我们会使用中断来实现事件的响应,效率比较高

.中断

1.概念

  中断指的是计算机运行期间,出现了某些需要立即处理的事务,计算机能够自动停止当前正在运行的程序,转而去执行处理需要立即处理的事务的代码,执行完成后回到被打断的程序位置继续往下执行。

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

2.stm32中断处理层次结构

 2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

3.NVIC向量中断控制器

1)特性

     2019年9月9日星期一(STM32 内部时钟 中断)

 

 

    NVIC的其他细节信息包含在 权威指南 中,其中包括 寄存器介绍以及优先级

2stm32中断优先级

    stm32中断优先级分为响应优先级和抢占优先级

    高抢占优先级的中断可以打断正在执行的低抢占优先级的中断

    如果抢占优先级相同,高响应优先级的中断不能抢占低响应优先级的中断

    如果抢占优先级相同,当两个中断同时发生,优先响应响应优先级高的中断

    如果抢占优先级和响应优先级都相同,哪个中断先发生就响应哪个中断

注意事项:

    1)数字越小,优先级越高

    2)抢占优先级和响应优先级一起占用固定的空间(4位二进制位)

        设置每种优先级占的位数叫做优先级分组,优先级分组程序中只能设置一次,多次设置带来不可预知的后果

    3)中断处理程序的时间尽可能短,禁止延时(睡眠)

4.中断源(外部中断)

  由外部硬件设备触发的中断叫外部中断,外部中断可以配置为 电平触发和边沿触发,包含23个可编程的外部中断源,其中由IO口触发的中断是

  EXINT0 ---- EXINT15

     2019年9月9日星期一(STM32 内部时钟 中断)

 

 

   

  EXINT0可以选择任意一个GPIO组中的0号管脚接入(PA0 PB0...)

  之后的外部中断线依此类推

  EXINT15可以选择任意一个GPIO组中的15号管脚接入(PA15 PB15...)

注:

  EXINT0 --- EXINT4有单独的中断号

  EXINT5-9共用一个中断号

  EXINT10-15共用一个中断号

外部中断处理框图

     2019年9月9日星期一(STM32 内部时钟 中断)

 

 

5.中断编程实现

1)在程序开头设置优先级分组

    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

2019年9月9日星期一(STM32 内部时钟 中断)

 

 

        


/******************中断初始化*******************************************/

2)使能SYSCFG时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

//中断源部分

3)初始化GPIO为输入模式

    GPIO_Init(...)

4)设置IO口和中断线的映射关系

    void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)

    参数:

        EXTI_PortSourceGPIOx - 哪一组

        EXTI_PinSourcex - 哪个脚

5)初始化中断源

    void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

 typedef struct
{
  uint32_t EXTI_Line;               /*!< 中断线 @ref EXTI_Lines */
  
  EXTIMode_TypeDef EXTI_Mode;       /*!< 中断or事件 @ref EXTIMode_TypeDef */

  EXTITrigger_TypeDef EXTI_Trigger; /*!< 触发边沿 @ref EXTITrigger_TypeDef */

  FunctionalState EXTI_LineCmd;     /*!< 使能/禁止 ENABLE or DISABLE */
}EXTI_InitTypeDef;

//NVIC部分

    void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

  typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< 中断通道(中断号) */

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< 抢占优先级(不能超过分配的位数) */

  uint8_t NVIC_IRQChannelSubPriority;         /*!< 响应优先级(不能超过分配的位数) */

  FunctionalState NVIC_IRQChannelCmd;         /*!< 使能/禁止 ENABLE or DISABLE */  
} NVIC_InitTypeDef;
 


/*编写中断处理程序*/

中断处理程序是一个函数,无参无返回值,函数名要去异常向量表中找

 void EXTI0_IRQHandler(void)

{

    //..........

    //清除中断标识

    EXTI_ClearITPendingBit(EXTI_Line0);//

}

相关文章:

  • 2021-04-21
  • 2021-08-19
  • 2021-07-08
  • 2021-06-26
  • 2021-09-15
  • 2021-03-31
  • 2021-04-25
  • 2021-04-14
猜你喜欢
  • 2022-12-23
  • 2022-01-17
  • 2021-06-20
  • 2022-02-25
  • 2021-07-30
  • 2021-12-19
  • 2021-06-05
相关资源
相似解决方案