九.位段操作
寄存器的操作通常以二进制位为单位,相对来说不那么方便,stm32中提供了位段操作让开发者以更方便和高效率地去访问寄存器中的位。
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
启动代码的工作:
初始化堆栈空间,定义异常向量表
执行SystemInit ----- 系统初始化
初始化时钟,调整异常向量表
执行main ----- 主函数
芯片要开始工作,必须初始化时钟和内存,stm32的内存使用片内的SRAM,可以直接使用,时钟系统需要初始化,ARM芯片需要定义异常向量表,执行C语言必须初始化堆栈。
stm32f407推荐的主时钟频率168MHz
2.产生原始频率的硬件
1.晶振
2.RC(LC)振荡电路
原始频率都不会很高,使用前必须升频,升频使用PLL(锁相环)电路
CPU时钟系统的大体结构:
3.stm32f407的原始时钟
HSI RC ------- 高速内部振荡时钟 16M
HSE OSC ------ 高速外部晶振 4~26M(8M)
//以上两个时钟源可以直接作为系统主时钟,也可以通过PLL升频后作为主时钟
LSI RC ------ 低速内部振荡时钟 32K ----- 看门狗
LSE OSC ----- 低速外部晶振 32.768K ---- 实时时钟
stm32的时钟树
PLL的输出时钟 = PLL输入时钟 X PLLN / PLLM / PLLP
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.看原理图
从原理图上可知:
按键松开 ---------------- 引脚高电平
按键按下 ---------------- 引脚低电平 按键对应的引脚:
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亮
按键消抖
以上按键程序不管是否有按键事件发生,都会占用CPU来进行判断,这种方法叫做轮询,效率比较低,CPU提供了效率更高的方式 ------------ 中断
十二.中断
1.概念
中断指的是在计算机工作期间,出现了需要停止正在运行的程序,转而去处理意外发生的情形。发生中断之后,CPU会去执行实现写好的中断处理程序,处理完成后回到被打断的位置继续执行。
中断处理程序编写注意事项:
中断处理程序的执行时间要尽量短,不能睡眠延时(让出CPU) 中断中访问的共享数据要进行保护
2.stm32的中断
stm32中,中断源产生中断信号,提交给向量中断控制器(NVIC),NVIC做进一步的处理后在提交给CPU,由CPU来执行中断处理程序。
3.NVIC
(1)介绍
NVIC外部中断(中断信号来自于芯片外部) --------- 一类中断源
一共有23个外部中断,包括16个GPIO中断和7个其他中断
(2)中断优先级(数字越小,优先级越高)
stm32的中断优先级分为2类:抢占优先级和响应优先级
抢占优先级:
抢占优先级高的中断可以打断抢占优先级低的中断
响应优先级:
响应优先级高的中断不能打断响应优先级低的中断,当抢占优先级相同的两个中断同时发生,CPU优先处理响应优先级高的中断。
抢占优先级和响应优先级一起最多占8位(4位),配置两个优先级所占的位数叫做优先级的分组。
以上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