目录
1. 什么是系统时钟
2. 时钟树
2.1 LSI
2.2 LSE
2.3 HSI
2.4 HSE
2.5 PLLCLK
2.6 SYSCLK
2.7 HCLK
2.8 PCLK1
2.9 PCLK2
2.10 RTC/AWU
3 SysTick定时器
3.1 为什么会有Systick定时器?
3.2 SysTick定时器的作用
3.3 SysTick定时器的寄存器
4. IO引脚复用和映射
5. NVIC中断优先级
5.1 中断寄存器
5.2 NVIC中断优先级设置函数
5.3 中断优先级设置步骤
嵌入式入坑者,与君共勉,大家一起加油!
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习
1. 什么是系统时钟
时钟系统就像人的心脏一样,在单片机系统中起着脉搏的作用;时钟是由电路产生的具有周期性的脉冲信号,要想使用单片机的外设必须开启相应的时钟,也就是给时钟使能。我们知道,操作一个外设的本质是操作其对应的寄存器,而寄存器由D触发器构成,必须通过时钟才能改写触发器的值,所以想要操作外设必须使能相应的时钟;对于CPU来说,时钟的频率越高,其时钟值越小,这里可以理解时钟是一个信号的周期,时钟=1/f,频率越高,时钟越小,也就是单位时间内 CPU 能够做到更多的事,也就是我们常说的CPU运行快;
STM32F4xx的时钟系统主要是给不同外设提供时钟,不同外设所需的时钟频率不同,如果像51单片机一样共用一个系统时钟,会造成资源浪费,给CPU运行带来负担,况且有些外设也接受不了这么大的频率;所以默认状态下,所有时钟是关闭的,操作哪个外设,就首先对哪个外设对应的时钟进行使能;
STM32 共有5个时钟源:HSE(高速外部时钟)、HSI(高速内部时钟)、LSE(低速外部时钟)、LSI(低速内部时钟)、PLL(锁相环倍频输出);
2. 时钟树
按照从上到下,从左到右的顺序,我们依次来看时钟树的结构:使用任何外设之前一定要先使能对应的时钟,否则无法使用对应的外设;
首先,LSI 低速内部时钟供到独立看门狗使用,32KHz,同时接到RTCSEL上,图中梯形形状代表着选择作用,也就是RTC可以选择LSE低速外部时钟使能,也可以选择LSI,在这里,通常选择LSE,因为LSE外接晶振,精度较高;LSE直接供RTC使用,LSE还可以经过1-5的分频后供MCO1使用;HSI 可以经过1-5 的分频后供 MCO1使用,HSI 也可以供给系统时钟 SYSCLK 选择使用,HSI 还可以通过分频后,在经过倍频,经过PLLP或者PLLQ后通过PLL输出;HSE通过1-5分频后可以供MCO2使用,HSE也可以供给系统时钟选择使用;PLL锁存倍频输出可以直接供外设使用;PLLI2S称为专用PLL;系统时钟可以是HSI、HSE、PLLCLK供应,其可以供应以太网PTP时钟;也可以通过AHB总线协议到AHB总线、内核、存储器和DMA,或者到Cortex系统定时器;
2.1 LSI
① LSI:low speed Internal Clock signal,低速内部(硬件焊接时不用外部加晶振,内部集成晶振 ag. CH340C)时钟。RC振荡器,频率32KHz左右。供看门狗(IWDG)和自动唤醒单元(AWU)使用。LSI RC更多的是担当一个低功耗时钟源的角色,可以在停机或者待机模式下保持运行。
使用:LSI RC是通过RCC时钟控制和状态寄存器RCC_CSR中的 LSION 位打开或关闭;RCC时钟控制和状态寄存器RCC_CSR中的 LSIDAY 标志指示低速内部振荡器是否稳定,硬件将此位置1,此时钟才可以使用;LSI RC更多的是担当一个低功耗时钟源的角色,可以在停机或者待机模式下保持运行。
为独立看门狗或者RTC提供时钟;(上图)
RCC时钟控制和状态寄存器RCC_CSR;(下图)
2.2 LSE
② LSE:low Speed External Clock signal,低速外部(外部焊接时加上晶振和滤波电容)时钟。接32.768KHz的石英晶体,主要作为RTC的时钟源来提供时钟/日历或其他定时功能,具有功率低且精度高的优点。 其使用方法和 LSI 不尽相同。
使用:LSE 晶振是通过RCC备份域控制寄存器RCC_BDCR中的 LSION 位打开或关闭;RCC备份域控制寄存器RCC_BDCR中的 LSEDAY 标志指示LSE晶振是否稳定,硬件将此位置1,此时钟才可以使用;如在RCC 时钟中断寄存器 (RCC_CIR) 中使能中断,则可产生中断。
原理图上32.768MHz的外部晶振,直接接到芯片的引脚上。
主要作为RTC使能(上图);
RCC备份域控制寄存器RCC_BDCR(下图);
2.3 HSI
④ HSI:High Speed Internal Clock signal,高速内部时钟。RC振荡器,频率16MHz,可以直接用作系统时钟或者PLL输入;当HSE故障时,系统会自动的使用HSI,直到HSE启动成功(可做辅助时钟使用);HSI RC振荡器能够在不需要任何外部器件的条件下提供系统时钟(成本较低)。它的启动时间比HSE晶体振荡器短。然而,即使在校准之后它的时钟频率精度仍较差。
使用:RCC 时钟控制寄存器 (RCC_CR) 中的 HSIRDY 标志指示 HSI RC 是否稳定。在启动时,硬件将此位置 1 后,HSI 才可以使用。HSI RC 可通过 RCC 时钟控制寄存器 (RCC_CR) 中的 HSION 位打开或关闭。
D:SW:系统时钟切换(System Clock switch);由软件置 1 或者清 0 来选择系统时钟源,再停止或者待机模式中直接或者间接的作为系统时钟的HSE出现故障时,HSI作为辅助时钟被系统强制的作为系统时钟;其中:
- 00:HSI作系统时钟;
- 01:HSE作系统时钟;
- 10:PLL输出作系统时钟;
- 11:不可用;
控制寄存器 (RCC_CR) (下图)
2.4 HSE
③ HSE:High Speed External Clock signal,高速外部时钟;可以接石英/陶瓷谐振器,频率范围为4MHz~26MHz。HSE也可以直接作为系统时钟或者PLL输入。
HSE的特点是 精度非常高;
RCC 时钟控制寄存器 (RCC_CR) 中的 HSERDY 标志指示高速外部振荡器是否稳定。在启动时,硬件将此位置 1 后,此时钟才可以使用。如在 RCC 时钟中断寄存器 (RCC_CIR) 中使能 中断,则可产生中断。HSE 晶振可通过 RCC 时钟控制寄存器 (RCC_CR) 中的 HSEON 位打开或关闭。
原理图上8MHZ的外部晶振,直接接到芯片引脚上。
RCC 时钟控制寄存器 (RCC_CR) (下图)
2.5 PLLCLK
⑤ PLLCLK:锁相环倍频输出;
由于在 PLL 使能后主 PLL 配置参数便不可更改,所以建议先对 PLL 进行配置,然后再使能 (选择 HSI 或 HSE 振荡器作为 PLL 时钟源,并配置分频系数 M、N、P 和 Q)。PLL总时钟经SystemInit 初始化以后的状态为168MHz;
主PLL(PLL)由 HSE或者HSI 提供时钟信号,并具有两个不同的输出时钟;第一个输出PLLP用于生成高速的系统时钟(最高168MHz);第二个输出PLLQ用于生成USB OTG FS的时钟(48MHz),随机数发生器的时钟和SDIO时钟。
专用PLL(PLLI2S)用于生成精确时钟,从而在I2S接口实现高品质音频性能。
主PLL先经过一个分频系数为M(PLL/M)的分频器,然后经过倍频系数为N的倍频器,出来之后经过分频系数为P(第一输出PLLP)或者第二输出(PLLQ)的分频器分频之后,最终生成主PLL时钟。ag . 外部晶振选择8MHz,设置相应的分频器M=8,倍频器倍频系数N=336,分频器分频系数P=2,可以计算得到主PLL生成的第一个输出高速时钟PLLP为:
PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz
2.6 SYSCLK
SYSCLK:系统时钟,最高为72M,通常的配置是SYSCLK=PLLCLK=168M。HSI、HSE、PLLCLK均可直接充当系统时钟;通过CFGR和SW进行控制;SW 系统切换已在2.3 HSI中讲解;在库函数里面关于CFGR(寄存器)主要是设置了HCLK、APB1和APB2 的时钟频率,还有通过寄存器后两位选择HSE/HSI/PLL这三个其中一个作为系统时钟。系统时钟经SystemInit函数初始化以后的状态为168MHz;
2.7 HCLK
HCLK:AHB(AHB是一种总线的协议,AHB用于高性能、高时钟频率的系统结构,典型的应用如ARM核与系统内部的高速RAM、NAND FLASH、DMA、Bridge的连接。)总线时钟;为AHB总线的外设提供时钟,为CorTex系统定时器提供时钟(SysTick)、为内核提供时钟(FCLK);
AHB总线时钟时钟经SystemInit函数初始化以后的状态为168MHz;HCLK=SYSCLK;
HCLK是通过系统时钟分频得到的,分频因子可以是1、2、4、8、16、128、256、512。通过CFGR、HPRE寄存器进行控制;
2.8 PCLK1
PCLK1:APB1总线时钟;PCLK1(APB1总线时钟)由PCLK经过低速APB1预分频得到,分频因子可以是1、2、4、8、16。PCLK1属于低速的总线时钟,最高可以为42MHz;APB1总线时钟经SystemInit函数初始化以后的状态为42MHz;PCLK1=SYSCLK/4;
PCLK1为APB1总线的外设提供时钟。1 或 2 倍频之后则为APB1总线的定时器2~7 提供时钟;
2.9 PCLK2
PCLK2:APB2总线时钟;由PCLK经过高速APB2预分频得到,分频因子可以是1、2、4、8、16。PCLK2属于高速的总线时钟,最高可以达到72MHz。APB2总线时钟为APB2总线的外设提供时钟。精确的说是为APB2的定时器1和8 提供时钟,最大为84M。APB2总线时钟时钟经SystemInit函数初始化以后的状态为84MHz;PCLK2=SYSCLK/2;
见时钟树的APBx外设时钟和APBx定时器时钟;
2.10 RTC/AWU
一旦选定 RTCCLK 时钟源后,要想修改所做选择,只能复位电源域。
RTCCLK 时钟源可以是 HSE 1 MHz(HSE 由一个可编程的预分频器分频)、LSE 或者 LSI 时钟。选择方式是编程 RCC 备份域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC 时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只能通过复位备份域的方式修改。
如果选择 LSE 作为 RTC(实时时钟) 时钟,则系统电源丢失时 RTC 仍将正常工作。
如果选择 LSI 作为 AWU(自动唤醒单元)时钟,则在系统电源丢失时将无法保证 AWU 的状态。如果 HSE 振荡器通过一个介于 2 和 31 之间的值进行分频,则在备用或系统电源丢失时将无法保证 RTC 的状态。
3 SysTick定时器
3.1 为什么会有Systick定时器?
SysTick定时器被捆绑在NVIC(中断优先级)中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
3.2 SysTick定时器的作用
SysTick是一个24位的倒计数定时器,计到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把他在SysTick控制及状态寄存器中的使能位清除,就永不停歇,即使在睡眠模式下也能工作;
SysTick定时器除了能服务于操作系统之外,还可以作为一个时钟,用于测量时间。但是需要注意:当处理器在调试期间被喊停时,SysTick定时器也会暂停运作;SysTick定时器常用来做延时,或者实时系统的心跳时钟;
SysTick定时器能产生中断;SysTick中断的优先级也可以设置;
定时器的作用简单来说就是我们在中断中定义一个时间,时间会从当前值Value--;当减到0以后,重装载寄存器会重装载到定义的值,也就是回到定义的数值,源源不断的进行减减;就像51单片机里面的定时器中断一样,我定义interruptCount=1000,1000--;执行中断的内容;if(interruptCount==0){interruptCount=1000;}源源不断的进行;
3.3 SysTick定时器的寄存器
有4个寄存器控制SysTick定时器:
SysTick控制及状态寄存器:
COUNTFLAG:16位,读取寄存器,复位值0,如果在上次读取本寄存器后,SysTick已经数到了0,则该位为1。如果读取该位,该位将自动清0;
CLKSOURCE:2位,读写寄存器,复位值0,0=外部时钟源(STCLK),1=内核时钟(FCLK);外部时钟源是AHB总线时钟的1/8,内核时钟是HCLK时钟;
TICKINT:1位,读写寄存器,复位值0,1=SysTick倒数到0时产生SysTick异常请求;(确定我们是否要产生中断)
ENABLE:0位,读写寄存器,复位值0,SysTick定时器的使能位;(使能);
SysTick重装载数值寄存器:
RELOAD:23:0位段,读写寄存器,复位值0,当倒数至零时,将被重装载值;
SysTick当前数值寄存器:
CURRENT:23:0位段,读写寄存器,复位值0,读取时返回当前倒计数的值,写入时他则使之清0,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志;
SysTick校准数值寄存器:
NOREF:31位,读取寄存器,1=没有外部参考时钟(STCLK不可用),0=外部参考时钟可用;
SKEW:30位,读取寄存器,1=校准值不是准确的10ms,0=校准值是准确的10ms;
TENMS:23:0位,读写寄存器,10ms时间内倒计数的格数;
配置函数:SysTick_CLKSourceConfig();
SysTick_Config(uint32_t ticks);初始化SysTick,时钟为HCLK,并开启中断;
void SysTick_Handler(void);中断服务函数;
4. IO引脚复用和映射
STM32F4有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。
ag. 引脚上标注 PC11——PC11/SPI3 MISO/U3 RX/U4 RX/SDIO D3/DCMI D4/I2S3ext SD 那么,PC11可以作为SPI3_MISO/U3_RX/U4_RX/SDIO_D3/DCMI_D4/I2S3ext_SD等复用功能输出;但是这么多的复用功能,如果同时的全部开启,系统会乱套;STM32F4的复用选择功能可以让PC11仅连接到某个特定的外设,防止相互之间的干扰;
STM32F4系列微控制器IO引脚通过一个复用器连接到内置外设或模块。该复用器一次只允许一个外设的复用功能(AF)连接到对应的IO口。这样可以确保共用同一个IO引脚的外设之间不会发生冲突。
我们配置相应的寄存器GPIOx_AFRL或者GPIOx_AFRH,让对应引脚通过复用器连接到对应的复用功能外设。GPIOx_AFRH控制的是一组IO口的高八位,GPIOx_AFRL控制的是一组IO口的低八位。
对于外设复用功能的配置,除了ADC和DAC要将IO配置为模拟通道之外其他外设功能一律 要配置为复用功能模式,这个配置是在IO口对应的GPIOx_MODER寄存器中配置的。同时要配置GPIOx_AFRH或者GPIOx_AFRL寄存器,将IO口通过复用器连接到所需要的复用功能对应的AFx。
通过MCU微控制器的PA9和PA10引脚我们来介绍一下如何配置串口1为复用功能:
1. 首先打开IO时钟和复用功能时钟(切记:32不同于51的最大区别就是想要使用任何外设,必须先对外设所对应时钟的寄存器进行使能)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); ---使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); ---使能USART1时钟
2. 在初始化GPIO口的寄存器GIPOx_MODER中将所需的IO配置为复用功能(ADC和DAC设置为模拟通道)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;---复用功能
3. 配置GPIOx_AFRL或者GPIOx_AFRH寄存器,将IO连接到所需的AFx。
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); ---PA9复用为USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); ---PA10复用为USART1
5. NVIC中断优先级
CM4内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置;开发板STM32F4xx系列共92个中断,包括10个内核中断和82个可屏蔽中断;其中最常用的就是82个可屏蔽中断;
5.1 中断寄存器
ISER[8]:
ISER全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。
CM4内核支持256个中断,在ISER中用8个32位寄存器来控制;要想使能某个中断,必须设置相应的ISER位为1,使该中断使能(但需要注意:这里也仅仅是使能,要想设置一个完整的中断还需要配合中断分组、屏蔽、IO口映射)
ICER[8]:
ICER全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。
除能---使能;正如其名,该寄存器和ISER作用正好相反,是用来清除某中断使能的;NVIC的这些寄存器都是写1有效的,写0是无效的。
ISPR[8]:
ISPR全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。
通过置1,将正在进行的中断挂起,而执行同级或更高级别的中断。
ICPR[8]:
ICPR全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。
通过置1,可以将挂起的中断解挂;
IABR[8]:
IABR全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。
对应位所代表的中断和ISER一样,如果为1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。
IP[240]:-----------NVIC寄存器中最重要的寄存器
IP全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。
IP寄存器由240个8bit寄存器组成,8bit的高四位和低四位分别表示抢占优先级和响应优先级;抢占优先级在前;
规则:
1. 抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。
2. 如果两个中断的抢占优先级和响应优先级都是一样的话,看哪个中断先发生就先执行。
3. 高优先级的抢占优先级是可以打断正在进行的低强占优先级中断的。
ag. 假定设置中断优先级组为2,然后设置中断3(RTC_WKUP中断)的抢占优先级为2,响应优先级为1。中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。那么这3个中断的优先级顺序为:中断7>中断3>中断6。 切记:抢占优先级数值越小,所代表的优先级就越高。
5.2 NVIC中断优先级设置函数
1. 首先进行中断优先级分组:NVIC_PriorityGroupConfig
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); --- 根据上述表格,设置2位抢占优先级,2位响应优先级;
2. 中断初始化函数NVIC_Init
中断初始化函数和GPIO初始化函数是一样的,是用结构体来进行初始化的;其共有4个成员变量;
NVIC_InitTypeDef NVIC_InitStructure;---定义结构体变量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; ---中断通道是否使能(使能)
NVIC_Init(&NVIC_InitStructure); ---取地址,初始化NVIC寄存器
5.3 中断优先级设置步骤
1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和响应优先级的分配位数。调用函数为NVIC_PriorityGroupConfig(); main函数
2. 设置所用到的中断的中断优先级别。对每个中断调用函数为NVIC_Init();