STM32F1系列以及CM3内核的时钟与中断内容详解

Stm32F1系统架构

STM32主系统有由四个驱动单元和四个被动单元:

驱动单元:内核DCode总线,系统总线,通用DMA1,通用DMA2
被动单元:AHB到APB的桥——连接所有APB设备,
内部FLASH内存,内部SRAM,FSMC

总线知识:

1、ICode:M3内核指令总线和闪存指令接口连接
2、Dcode:M3内核的DCode总线和闪存存储器的数据接口相连
3、系统总线:M3内核的系统总线到总线矩阵,总线矩阵协调内核和DMA间的访问
4、DMA总线:DMA的AHB主控接口和总线矩阵相连
5、总线矩阵:内核总线和DMA总线之间的仲裁协调
6、AHB\APB桥在AHB和APB总线间提供同步连接,APB1操作速度限于36MHz
APB2操作速度全速

STM32F1系列以及CM3内核的时钟与中断内容详解_第1张图片

STM32时钟系统

时钟系统简介

STM32F1系列以及CM3内核的时钟与中断内容详解_第2张图片
在 STM32 中,有五个时钟源,为 HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为 高速时钟源和低速时钟源,
高速时钟:HSI,HSE 以及 PLL
低速时钟:LSI 和 LSE
从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,
外部时钟源:HSE 和 LSE 是,其他的是内部时钟源。
下面我们看看 STM32 的 5 个时 钟源:
①HSI 是高速内部时钟,RC 振荡器,频率为 8MHz。
②HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。我们的开发板接的是 8M 的晶振。
③LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同 时 LSI 还可以作为 RTC 的时钟源。
④LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
⑤PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为2~16倍,但是其最大的输出频率不得超过72MHz。

这里总结一下 SystemInit()函数中设置的系统时钟大小:

SYSCLK(系统时钟) =72MHz
AHB 总线时钟(使用 SYSCLK) =72MHz
APB1 总线时钟(PCLK1) =36MHz
APB2 总线时钟(PCLK2) =72MHz
PLL 时钟 =72MHz

时钟系统的工作

A. MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,可以 选择为 PLL 输出的 2 分频、HSI、HSE、或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源。
B. 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及 HSE 的 128 分频。
C. 从图中可以看出 C 处 USB 的时钟是来自 PLL 时钟源。STM32 中有一个全速功能 的 USB 模块,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能 从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB 模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。
D. D 处就是 STM32 的系统时钟 SYSCLK,它是供 STM32 中绝大部分部件工作的时 钟源。系统时钟可选择为 PLL 输出、HSI 或者 HSE。系统时钟最大频率为 72MHz, 当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。 E. 这里的 E 处是指其他所有外设了。从时钟图上可以看出,其他所有外设的时钟最 终来源都是 SYSCLK。SYSCLK 通过 AHB 分频器分频后送给各模块使用。这些 模块包括:
①、AHB 总线、内核、内存和 DMA 使用的 HCLK 时钟。
②、通过 8 分频后送给 Cortex 的系统定时器时钟,也就是 systick 了。
③、直接送给 Cortex 的空闲运行时钟 FCLK。
④、送给 APB1 分频器。APB1 分频器输出一路供 APB1 外设使用(PCLK1,最大 频率 36MHz),另一路送给定时器(Timer)2、3、4 倍频器使用。
⑤、送给 APB2 分频器。APB2 分频器分频输出一路供 APB2 外设使用(PCLK2, 最大频率 72MHz),另一路送给定时器(Timer)1 倍频器使用。

其中需要理解的是 APB1 和 APB2 的区别:

APB1 上面连接的是低速外设,包括电源接口、 备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等
APB2 上面连接的是高速外设包 括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。 2>1, APB2 下面所挂的外设的时 钟要比 APB1 的高。
STM32F1系列以及CM3内核的时钟与中断内容详解_第3张图片

STM32中断系统

1、中断系统的介绍

1)CM3一共支持256个中断,其中16个内核中断和240个外部中断。
2)STM32没有使用完CM3的所有中断,共有84个中断,其中内核16,外部68,具有16级可编程的中断优先级
其中我们经常用的是68个可屏蔽的中断。
3)STM32F103系列中又只有60个可屏蔽的中断。

2、F1系列中断涉及的寄存器

ISER[8]:中断使能寄存器组。上面 说了 CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是 STM32F103 的可屏蔽中断只有 60 个,所以对我们来说,有用的就是两个(ISER[0]和 ISER[1]), 总共可以表示 64 个中断。而 STM32F103 只用了其中的前 60 位。ISER[0]的 bit0~bit31 分别对 应中断 0~31。ISER[1]的 bit0~27 对应中断 32~59;这样总共 60 个中断就分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO口映射等设置才算是一个完整的中断设置)。

具体每一位对应哪个中断,请 参考 stm32f10x.h 里面的第 140 行处(针对编译器 MDK5 来说)

ICER[8]:中断除能寄存器组。该寄存器组 与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICER 一样。 这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄 存器都是写 1 有效的,写 0 是无效的。
ISPR[8]:中断挂起控制寄存器组。每个位 对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别 的中断。写 0 是无效的。
ICPR[8]:中断解挂控制寄存器组。其作 用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断接挂。写 0 无效。
IABR[8]:中断激活标志位寄存器组。对应位 所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄 存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

IP[240]:中断优先级控制的寄存器组

这个寄存器组相当重要!STM32 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit 的寄 存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32 只用到 了其中的前 60 个。IP[59]~IP[0]分别对应中断 59~0。而每个可屏蔽中断占用的 8bit 并没有全部 使用,而是 只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先 级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。
STM32F1系列以及CM3内核的时钟与中断内容详解_第4张图片

3、中断优先级

第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行
第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断

抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

4、中断初始化设置流程

1、void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
EP:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
2、void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
EP:NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器

初始化:

1、 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的 分配位数。调用函数为 NVIC_PriorityGroupConfig();
2. 设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();

你可能感兴趣的:(STM32系列)