DAY03-位段操作启动和时钟系统,NVIC

135 阅读5分钟

九.位段操作

寄存器的操作通常以二进制位为单位,相对来说不那么方便,stm32中提供了位段操作让开发者以更方便和高效率地去访问寄存器中的位。

image.png stm32规定了寄存器地址到位段地址的映射公式(参考手册的2.3.3节)

   bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4)
​
 其中:   
​
 bit_word_addr 代表别名区域中将映射到目标位的字的地址   
​
 bit_band_base 代表别名区域的起始地址    
​
byte_offset 代表目标位所在位段区域中的字节编号    
​
bit_number 代表目标位的位位置 (0-7)              

位段操作既方便了编程,也提高了代码运行效率,如果对一个寄存器频繁访问,可以使用位段操作。

十.芯片启动和时钟系统

1.芯片启动

首先stm32会根据启动方式(2.4节)从启动位置加载启动代码到内存中,之后开始执行启动代码,一般启动代码使用官方提供的即可 ------ xxx.s

image.png

启动代码的工作:

初始化堆栈空间,定义异常向量表 
​
执行SystemInit ----- 系统初始化    
​
初始化时钟,调整异常向量表
​
 执行main ----- 主函数           

芯片要开始工作,必须初始化时钟和内存,stm32的内存使用片内的SRAM,可以直接使用,时钟系统需要初始化,ARM芯片需要定义异常向量表,执行C语言必须初始化堆栈。

stm32f407推荐的主时钟频率168MHz

2.产生原始频率的硬件

  1.晶振 
​
2.RC(LC)振荡电路 

原始频率都不会很高,使用前必须升频,升频使用PLL(锁相环)电路

CPU时钟系统的大体结构:

image.png

3.stm32f407的原始时钟

HSI RC ------- 高速内部振荡时钟 16M 
​
HSE OSC ------ 高速外部晶振 4~26M(8M) 
​
//以上两个时钟源可以直接作为系统主时钟,也可以通过PLL升频后作为主时钟
​
 LSI RC ------ 低速内部振荡时钟 32K ----- 看门狗
​
 LSE OSC ----- 低速外部晶振 32.768K ---- 实时时钟      

stm32的时钟树

image.png

PLL的输出时钟 = PLL输入时钟 X PLLN / PLLM / PLLP

image.png

       168M = 8M X 336 / 8 / 2              

4.将keil5工程的系统时钟配置为168M

(1)修改system_stm32f4xx.c的254行

      #define PLL_M      8   

(2)修改stm32f4xx.h的127行

      //改文件的属性是只读,要去文件系统中找到改文件,去掉只读属性才能修改 #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */    

练习:

修改PLL,调节系统主频

 #define PLL_N      336 //168M #define PLL_N      432 //216M 超频 #define PLL_N      168 //84M 降频        

系统总线时钟:

SYSCLK时钟 -------- 168MHz 

HCLK/AHB总线 ------ 168MHz 

APB1时钟 ---------- 42MHz 

APB2时钟 ---------- 84MHz        

十一.按键驱动

1.看原理图

image.png

image.png image.png 从原理图上可知:

按键松开 ---------------- 引脚高电平 

按键按下 ---------------- 引脚低电平 按键对应的引脚:   

S1 ----- PA0    

S2 ----- PE2    

S3 ----- PE3    

S4 ----- PE4             

如何读取输入引脚的电平

1.读取输入寄存器(IDR)对应的位的值   

 1 ----- 输入高电平  

0 ----- 输入低电平 

2.位段操作    

PAin(0)==0 ----- 输入低电平    

PAin(0)==1 ----- 输入高电平 

3.库函数    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);  

  //传入哪一组哪个脚,返回该引脚的电平  

练习:

完成其他三个按键的检测程序,分别使用位段,寄存器,库函数

实现以下功能:

 按下S2,D2亮 

按下S3,D3亮 

按下S4,D4亮              

按键消抖

image.png 以上按键程序不管是否有按键事件发生,都会占用CPU来进行判断,这种方法叫做轮询,效率比较低,CPU提供了效率更高的方式 ------------ 中断

十二.中断

1.概念

中断指的是在计算机工作期间,出现了需要停止正在运行的程序,转而去处理意外发生的情形。发生中断之后,CPU会去执行实现写好的中断处理程序,处理完成后回到被打断的位置继续执行。

image.png 中断处理程序编写注意事项:

中断处理程序的执行时间要尽量短,不能睡眠延时(让出CPU) 中断中访问的共享数据要进行保护

2.stm32的中断

image.png stm32中,中断源产生中断信号,提交给向量中断控制器(NVIC),NVIC做进一步的处理后在提交给CPU,由CPU来执行中断处理程序。

3.NVIC

(1)介绍

image.png NVIC外部中断(中断信号来自于芯片外部) --------- 一类中断源

一共有23个外部中断,包括16个GPIO中断和7个其他中断

image.png

image.png

image.png

image.png

image.png

image.png (2)中断优先级(数字越小,优先级越高)

stm32的中断优先级分为2类:抢占优先级和响应优先级

抢占优先级:

抢占优先级高的中断可以打断抢占优先级低的中断

image.png

响应优先级:

响应优先级高的中断不能打断响应优先级低的中断,当抢占优先级相同的两个中断同时发生,CPU优先处理响应优先级高的中断。

image.png 抢占优先级和响应优先级一起最多占8位(4位),配置两个优先级所占的位数叫做优先级的分组。

image.png 以上NVIC的配置,通过库函数NVIC_Init来实现

优先级分组通过NVIC_PriorityGroupConfig来配置,该函数智能在程序开头调用,并且只能调用一次。

 void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); 

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);            

作业:

编写代码,实现对4个按键的轮询实现(消抖版本)

  S2 ---- D2 

 S3 ---- D3 BEEP

 S4 ---- D4