首页 理论教育 STM系列典型寄存器介绍

STM系列典型寄存器介绍

时间:2026-01-27 理论教育 小龙哥 版权反馈
【摘要】:一个寄存器负责使能相应设备,一个寄存器则关闭相应设备。图6.8RCC_APB2RSTR和RCC_APB2ENR寄存器结构这一点与很多处理器的控制寄存器不同,一般都是通过置1来使能,置0来关闭。图6.9RCC_APB1RSTR和RCC_APB1ENR寄存器结构时钟控制寄存器组RCC的数据结构stm32f10x_map.h文件中定义了下面的数据结构体来对应RCC寄存器组,偏移量就是寄存器相对于结构体基地址的偏移位置,RCC的基地址是:0x40021000。每个端口对应外部16位数据线,通过内部的一组寄存器可以操作相应的I/O数据线。

1)时钟控制寄存器组RCC

为了很好地实现低功耗,Cortex-M3通过一个强大的时钟管理系统来调度内部资源,开发人员可以及时降低工作频率,关闭或者暂停某个区域,从而保证CM3始终工作在节能状态,管理这个强大时钟系统的就是RCC寄存器组。

CM3总共有4个时钟源,即外部高速时钟(HSE)、内部高速时钟(HSI)、低速外部时钟(LSE)和低速内部时钟(LSI)。此外内部还有一个锁相环PLL时钟,能够对HSI或HSE进行倍频。HSI、HSE和PLL用来驱动系统时钟SYSCLK;LSI作为看门狗时钟或者RTC,LSE也可以选作RTC。当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。整个系统时钟如图6.5所示。

时钟控制寄存器组主要包括时钟控制寄存器(RCC_CR)、时钟配置寄存器(RCC_CFGR)、APB2外设时钟使能寄存器(RCC_APB2ENR)、APB1外设时钟使能寄存器(RCC_APB1ENR)等,这些寄存器都是32位的。

(1)时钟控制寄存器(RCC_CR)

时钟控制寄存器用来控制时钟的打开和关闭,判断时钟是否就绪,以及对HSI的RC时钟进行校准。它的复位值为:0x0000xx83,其中X代表未定义,如图6.6所示。

图示

图6.6 RCC_CR寄存器结构

①时钟源开启:位[0]开启/关闭HSI,位[16]开启/关闭HSE,上电默认开启HSI。

外部时钟源HSE: HSEON=1(开)/0(关)

内部时钟源HSI:HSION=1(开)/0(关)

例:要开启HSE,只需要把CR寄存器位[16]置1即可,C语言实现如下

图示

②开启锁相环:置位位[24]开启,复位位[24]则关闭锁相环PLL。

PLL:PLLON=1(开)/0(关)

需要注意的是,配置锁相环之前应该先关闭锁相环(如何配置见后)。

例:开启锁相环PLL

图示

③时钟状态。

通过读取HSIRDY(位[1])、HSERDY(位[17])、PLLRDY(位[25]),可以确定时钟是否正确打开,1——就绪;0——未就绪。

例:读取HSIRDY

图示

(2)时钟配置寄存器(RCC_CFGR)

时钟配置寄存器CFGR主要用来选择系统时钟SYSCLK的时钟源、选择锁相环时钟源、确定锁相环倍频,以及对各种局部时钟进行预分频等。配置CFGR寄存器要紧密结合时钟树,如图6.7所示。

图示

图6.7 RCC_CFGR寄存器结构

位[1:0](SW[1:0]):

选择SYSCLK的时钟源,如下:

00:HSI作为系统时钟;

01:HSE作为系统时钟;

10:PLL输出作为系统时钟;

11:不可用。

如果SYSCLK切换结束,可以通过读取SWS[1:0]来判断是否切换就绪。

位[16](PLLSRC):

选择锁相环的时钟源,如下:

0:HSI振荡器时钟经2分频后作为PLL输入时钟;

1:HSE时钟作为PLL输入时钟。

位[17](PLLXTPRE):

HSE分频器作为锁相环的时钟源,如下:

0:HSE不分频;

1:HSE 2分频。

位[20:18](PLLMUL):

PLL倍频系数,0000~1110:分别对应2~16倍频。

ADCPRE对ADC进行分频;PPRE1对低速APB预分频(APB1);PPRE2对高速APB预分频(APB2);HPRE对低速AHB预分频;USBPRE对低速USB预分频。在进行预分频或者倍频的时候需要注意,不同型号的芯片对最高频率有不同的限制,比如STM32的F103VC就要求倍频后的频率不能超过72 MHz。

例:设置SYSCLOCK工作在72 MHz。

图示

图示

(3)APB2外设时钟复位寄存器RCC_APB2RSTR和使能寄存器RCC_APB2ENR

高速局部总线APB2上挂载的设备由RCC_APB2RENR和RCC_APB2RSTR两个寄存器来负责使能和复位,它们的结构完全一样,如图6.8所示。一个寄存器负责使能相应设备,一个寄存器则关闭相应设备。

图示

图6.8 RCC_APB2RSTR和RCC_APB2ENR寄存器结构

这一点与很多处理器的控制寄存器不同,一般都是通过置1来使能,置0来关闭。而CM3设计成两个寄存器,对于使能寄存器APB2ENR,置1使能相应位,置0则不起作用,或者无效;对于复位寄存器APB2RSTR,置1则复位相应位,而置0则不起作用。这样操作有一个好处,就是在对某些位置位或者复位时,不会影响到其他位的状态,减少开发人员误操作。如果既在APB2ENR进行了置位操作,又在APB2RSTR进行了复位,那么该关闭还是打开呢?答案是:最后的操作起作用,如果后复位,复位起作用;如果后置位,则置位起作用。

在使用某个片上设备之前必须要先打开相应的时钟,比如使用IOPA口,先要使能IOPA口时钟,操作如下:

RCC->APB2ENR |=1<<2;

复位A口时钟,则

RCC->APB2RSTR |=1<<2;

当然也可以同时使能多个设备时钟,比如同时使能ADC3、USART1、IOPC和AFIO,实现如下:

RCC->APB2ENR =0xC011;

(4)APB1外设时钟复位寄存器RCC_APB1RSTR和使能寄存器RCC_APB1ENR

功能和操作方式与APB2外设时钟控制寄存器类似,此处不再赘述,如图6.9所示。

图示

图6.9 RCC_APB1RSTR和RCC_APB1ENR寄存器结构

(5)时钟控制寄存器组RCC的数据结构

stm32f10x_map.h文件中定义了下面的数据结构体来对应RCC寄存器组,偏移量就是寄存器相对于结构体基地址的偏移位置,RCC的基地址是:0x40021000。

图示

对RCC_TypeDef指针又重新进行了定义,如下:

#define RCC ((RCC_TypeDef∗)RCC_BASE)

如要访问CFGR寄存器,则对应C语句为RCC->CFGR。

2)I/O口寄存器组GPIOx

CM3有一组输入输出端口,称为通用输入输出口(GPIO),一般编号为A—G,根据型号不同减少或者增加。每个端口对应外部16位数据线,通过内部的一组寄存器可以操作相应的I/O数据线。我们用GPIOx来表示某输入输出口(其中x=A—G),每个GPIO口都有一组功能一样的寄存器,这些寄存器主要包括工作模式配置寄存器CRH(用来配置高8位)和CRL(用来配置低8位),输入寄存器IDR,输出寄存器ODR,置位和复位寄存器BSRR以及复位寄存器BRR等。

(1)配置寄存器CRH和CRL

每个GPIOx拥有16位数据线,每根数据线都可以在不同的工作模式和不同的速度下,操作非常灵活。通过GPIOx_CRH和GPIOx_CRL可以设置每一根数据的工作模式和速度,这两个寄存器都是32位的,如图6.10所示(只给出了CRL,CRH结构相同)。

图示

图6.10 GPIOx_CRL寄存器结构

从图6.10可以看出,每根数据线对应4位信息,2位设置速度和2位设置工作模式,这样32位的CRL寄存器只能设置8位I/O口;另外的高8位I/O位的设置则由CRH来胜任。

例:把GPIOE口16位全部设置成推挽式输出,速度是50 MHz。

图示

例:把GPIOD口低8位推挽式输出,速度是50 MHz;高8位浮空输入。

图示(https://www.xing528.com)

(2)输入寄存器IDR和输出寄存器ODR

IDR寄存器用来读取外部引脚的状态,ODR寄存器把数据传送到外部引脚。虽然IDR和ODR寄存器都是32寄存器(CM3好像把所有的寄存器都设计成32位),但是每个I/O口外部引脚只有16根,所以IDR和ODR寄存器只有低16位有效,如图6.11所示。

图示

图6.11 GPIOx_ODR/IDR寄存器结构

IDR寄存器是只读的,往IDR里写内容是无效的;ODR则是可读可写的。IDR和ODR只能按字来进行操作,也就是说只能一次读出IDR的所有位信息,或一次把所有位信息写入ODR。IDR的读操作不会影响外部设备的工作状态;而ODR的写操作则不同,会改变连接在GPIOx口上设备的工作状态。每一次往ODR寄存器写入新的内容,所有位信息都会改变。假如GPIOx现在接了16个开关,那就意味着16个开关状态都要改变。很显然这样的操作是不方便的,工程实际中都是只改变相应的开关,不会改变所有开关。为了解决这个问题,CM3提供了多个方案,一是可以通过位带别名区来操作,通过查阅手册会发现,ODR寄存器正好就处于位带区;另外一个就是通过置位/复位寄存器来实现。

(3)置位复位寄存器BSRR和复位寄存器BRR

置位复位寄存器的结构如图6.12所示,复位寄存器的结构如图6.13所示。

图示

图6.12 GPIOx_BSRR寄存器结构

图示

图6.13 GPIOx_BRR寄存器结构

比较图6.12和图6.13,可以看出BSRR低16位用来置位16位端口信息,相应位置1则置位相应数据位,置0无效;高16位用来复位16位端口信息,相应位置1则复位相应数据位,置0无效。如果置位和复位同时都设置为1,CM3的解决办法是置位优先,也就是说出现了置位和复位冲突时,置位起作用,复位无效。因此BSRR寄存器在使用时要么只操作高16位(低16位全0),要么只操作低16位(高16位全0)。

例:把GPIOC的0位和3位置1,15位和14位复位。

第一种操作:GPIOC->BSRR=0xC0000005; //一次操作32位

第二种操作:GPIOC->BSRR=0x5; //先修改低16位

GPIOC->BSRR=0xC0000000; //后修改高16位

这样操作复位,只有高16位起作用,却要写一个32位数,于是CM3又提供了一个专用的复位寄存器BRR。如图6.13所示,BRR寄存器只有低16位,高16位无效。这样BRR寄存器用来复位,BSRR寄存器用来置位,都只使用它们的低16位。上例中复位的第二种操作也可以使用BRR寄存器来实现,如下:

图示

通常用BRR来复位,用BSRR低16位来置位。当然,用户要一次同时完成置位和复位,那就只能使用BSRR寄存器。要对GPIOx进行位操作可以通过以下方式实现:

①通过位带别名区来操作,缺点是一次只能操作一位;

②通过BSRR寄存器来操作,一次操作一个32位数;

③通过BSRR+BRR寄存器来操作,两次操作,一次操作一个16位数。

思考下面二者的区别:

图示

(4)GPIOx寄存器组的数据结构

同样stm32f10x_map.h文件中也定义了GPIOx寄存器组结构体,偏移量就是寄存器相对于结构体基地址的偏移位置,GPIOA的基地址是:0x40010800。

图示

3)复用功能寄存器组AFIO

如果要使用GPIOx的其他功能,不再用来输入输出0和1,那么就要用到复用功能,这个时候AFIO寄存器就要工作了,AFIO就是来实现GPIOx的复用功能的。如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。当然,要使用复用功能就必须要在时钟控制寄存器组中打开AFIO时钟。

(1)事件控制寄存器(AFIO_EVCR)

事件控制寄存器就是内部事件输出到外部引脚,当内部事件发生就在外部相应引脚上输出一个时钟周期的脉冲。AFIO_EVCR寄存器结构如图6.14所示。

图示

图6.14 AFIO_EVCR寄存器内部结构及参数设置

(2)复用重映射和调试I/O配置寄存器(AFIO_MAPR)

为了优化64脚或100脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。设置复用重映射和调试I/O配置寄存器(AFIO_MAPR)实现引脚的重新映射。AFIO_MAPR寄存器结构如图6.15所示。

图示

图6.15 AFIO_MAPR寄存器内部结构

这时,复用功能不再映射到它们的原始分配上。例如通过位USART1_REMAP修改串口通信USART1映射,如下:

0:PA9作为发送端TX,PA10作为接收端RX;//默认值

1:PB6作为发送端TX,PB7作为接收端RX;

把USART1_REMAP的值设置为1,就把串口1的端子映射到PB6和PB7了。

再比如要关闭JTAGT调试端口,打开SW调试端口,操作如下:

AFIO->MAPR &=0XF8FFFFFF; //清除MAPR的[26:24]

AFIO->MAPR|=0X02000000; //010关闭JTAG,打开SW

重映射在实践中很少使用,如果遇到其他位的定义,可以参考操作手册。

(3)外部中断配置寄存器(AFIO_EXTICR[4])

外部中断配置寄存器用来配置GPIOx的某个引脚作为外部中断信号输入,总共可以配置16个外部中断请求线,编号为0—15。总共有4个32位寄存器,每个寄存器只有低16位有效,高16位无效,如图6.16所示。

图示

图6.16 AFIO_EXTICR四个寄存器内部结构

由图6.16可以看出,每个EXTICR寄存器的低16位管理4个外部中线的配置,EXTICR[0]管理0—3号;EXTICR[1]管理4—7号;EXTICR[2]管理8—11号;EXTICR[3]管理11—15号。每个号码对应一个四位信息[3:0],如果是0000,则代表A口;如果是0001,则代表B口;以此类推。

例如,要设置PC13作为外部中断请求输入线。先找到EXTI13,然后让EXTI13[3:0]=0010;EXTI13代表13号,0010代表C口;于是C口的13号引脚就被设置为外部中断请求线。C语言实现如下:

图示

整个过程都保持其他位的信息不变。

4)中断控制寄存器组NVIC

实现多任务操作,及时响应外部的各种突发事件,中断是计算机必不可少的技术。中断功能的实现由中断程序负责,中断程序的调用比子程序调用复杂很多。涉及中断使能和除能(允许中断或者禁止中断)、中断的挂起与解挂(中断请求标志与清除)、中断优先级和中断激活等概念和技术。

CM3最多可以管理240个外部中断(根据厂家型号不同而不同,一般都少于240个),对应的0—239个外部中断源,中断编号为16—255。

(1)中断使能寄存器SETENA0—SETENA7与除能寄存器CLRENA0—CLRENA7

SETENAx都是3位寄存器,每一位对应一个外部设备中断允许,这样的寄存器共有8个,共56位,理论上可以允许256个外设中断。实际情况不是这样的,CM3理论确实可以管理256个中断,但是有一些内部系统的中断是非常重要的,一旦内部出现异常情况,若不处理,CPU可能就无法工作了,所以这部分中断不允许用户使能和除能。这样的系统中断有16个,对应中断编号是0—15,那么外部中断最多不能超过240个。再回头看SETNENAx共有256位,现在最多只能管理240个外部中断,那么就多出来了16位。从SETENA0到SETENA6,共有7×32=224位,SETENA7只剩16位了,所以SETENA7寄存器的高16位是无效的。

同样,CLRENA0—CLRENA6,以及CLRENA7的低16,总共构成240位,来除能(或称为禁止)外部240个中断,见表6.1。

表6.1 使能与除能寄存器列表

图示

这里同样把使能和除能设计成两组寄存器,而不是用一组寄存器。如果用一组寄存器,相应位置1使能中断,置0除能中断;那么在往一个32位寄存器写数来使能某些位时其他位的数据就可能被误修改了。现在设计成两组寄存器,SETENAx只管使能,相应位设置1使能,置0则不起作用,这样就不怕因为误写0而改变别的位;CLRENAx也是一样的道理。

(2)中断挂起寄存器SETPEND0—SETPEND7与解挂寄存器CLRPEND0—CLRPEND7

挂起寄存器和解挂寄存器与中断使能寄存器和中断除能寄存器结构一样,每位代表的外设都一样。挂起寄存器就是当中断允许的情况,外部的某一个设备发出了中断请求,则挂起寄存器的相应位就会置1。例如,SETPEND1的第2位被置1了,代表34号外部中断有请求。当中断程序响应结束,解挂寄存器相应的位就会被置1,代表请求已经被响应。挂起与解挂寄存器地址范围见表6.2。

表6.2 挂起与除能解挂寄存器列表

图示

续表

图示

(3)中断激活寄存器ACTIVE0—ACTIVE7

当某个中断被响应,只要中断程序还没有结束,ACTIVEx的相应位就会被置1,即使此时中断被更高级别的中断打断了,激活位仍然保持为1,并且新的高级别中断的相应位也会处于激活状态,被置1,直到中断响应结束,才清除响应的激活状态,相应位被清零。如果7个激活寄存器里出现了多个位为1,则代表有中断嵌套。激活寄存器地址范围见表6.3。

表6.3 激活寄存器列表

图示

(4)中断优先级寄存器PRI0—PRI239

PRI0—PRI239对应的地址范围是0xE000E400~0xE000E4EF。每个外部中断都有一个对应的优先级寄存器,每个寄存器占用8位,但是允许最少只使用最高3位。4个相邻的优先级寄存器拼成一个32位寄存器。根据优先级组设置,优先级可以被分为高低两个位段,分别是抢占优先级和亚优先级。到底抢占优先级和亚优先级分别占几位,则由AIRCR的PRIGROUP决定。AIRCR寄存器结构见表6.4。

表6.4 AIRCR寄存器结构

图示

从表6.4可以看到,AIRCR的[10:8]这三位来对优先级分组,具体分组情况跟芯片厂家和型号有关。比如STM32芯片,只使用了8位当中的高4位(低4位无效),AIRCR的[10:8]如果是111,则代表0位抢占优先级,4位响应优先级;如果是110,则代表1位抢占优先级,3位响应优先级;以此类推。数值越小,则优先级越高。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈