件。HCLK:由AHB预分频器直接输出得到,它是高速总线AHB的时钟信号,提供给存储器、DMA及Cortex内核,是Cortex内核运行的时钟,CPU主频就是这个信号,它的大小与STM32运算速度、数据存取速度密切相关。FCLK:同样由AHB预分频器输出得到,是内核的“自由运行时钟”(freerunningclock)。“自由”表现在它不来自时钟HCLK,因此在HCLK时钟停止时FCLK也会继续运行。它的存在,可以保证在处理器休眠时,也能够采样中断和跟踪休眠事件,它与HCLK互相同步。PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总线上的外设(低速外设)。PCLK2:外设时钟,由APB2预分频器输出得到,最大频率可为72MHz,提供给挂载在APB2总线上的外设.(高速外设)。5.时钟输出的使能及其流程在以上的时钟输出中有很多是带使能控制的,如AHB总线时钟、内核时钟、各种APBI外设时钟、APB2外设时钟等。当需要使用某模块时,必须先使能对应的时钟。需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。连接在APB1上的设备(低速外设)有:电源接口、备份接口、CAN、USB、I2CI、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意:USB模块虽然需要一个单独的48MHz时钟信号,但它不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。连接在APB2上的设备(高速外设)有:GPIOA-E、USART1、ADC1、ADC2、ADC3、TIM1、TIM8、SPI1、AFIO。其中需要理解的是APB1和APB2的区别,APB1上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、IC1、IC2、UART2、UART3等等,APB2上面连接的是高速外设,包括UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA_PE)、第二功能IO口等。APB2下面所挂的外设的时钟要比APB1的高。在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。以下是时钟设置的基本流程。假设,使用HSE时钟,并且使用ST的固件库函数,那么在程序中设置时钟参数的流程如下。第1步:将RCC寄存器重新设置为默认值,即调用函数RCC_Delnit;第2步:打开外部高速时钟晶振HSE,调用函数RCC_HSEConfig(RCC_HSE_ON);第3步:等待外部高速时钟晶振工作,调用HSEStartUpStatus=RCC_WaitForHSEStartUp() ;第4步:设置AHB时钟,即调用函数RCC_HCLKConfig;第5步:设置高速AHB时钟,即调用函数RCC_PCLK2Config;16
16 件。 HCLK:由AHB预分频器直接输出得到,它是高速总线AHB的时钟信号,提供给存储 器、 DMA及Cortex内核,是Cortex内核运行的时钟,CPU主频就是这个信号,它的大小与STM32运 算速度、数据存取速度密切相关。 FCLK:同样由AHB预分频器输出得到,是内核的“自由运行时钟”(free running clock)。“自由”表现在它不来自时钟HCLK,因此在HCLK时钟停止时FCLK也会继续运 行。 它的存在,可以保证在处理器休眠时,也能够采样中断和跟踪休眠事件,它与HCLK 互相同 步。 PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总 线上的外设(低速外设)。 PCLK2:外设时钟,由APB2预分频器输出得到,最大频率可为72MHz,提供给挂载在 APB2总线上的外设.(高速外设)。 5.时钟输出的使能及其流程 在以上的时钟输出中有很多是带使能控制的,如AHB总线时钟、内核时钟、各种 APB1 外设时钟、APB2外设时钟等。 当需要使用某模块时,必须先使能对应的时钟。需要注意的是定时器的倍频器,当 APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。 连接在APB1上的设备(低速外设)有:电源接口、备份接口、CAN、USB、I2C1、 I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意:USB模块虽然 需要一个单独的48MHz时钟信号,但它不是供USB模块工作的时钟,而只是提供给串行接口 引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。 连接在APB2上的设备(高速外设)有:GPIO_A-E、USART1、ADC1、ADC2、ADC3、 TIM1、TIM8、SPI1、AFIO。 其中需要理解的是APB1和APB2的区别,APB1上面连接的是低速外设,包括电源接口、 备份接口、CAN、USB、I 2 C1、I 2 C2、UART2、UART3 等等,APB2上面连接的是高速外设,包 括UART1、 SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口等。APB2下 面所挂的外设的时钟要比APB1的高。 在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种 APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。 以下是时钟设置的基本流程。 假设,使用HSE时钟,并且使用ST的固件库函数,那么在程序中设置时钟参数的流程如 下。 第1步:将RCC寄存器重新设置为默认值,即调用函数RCC_Delnit; 第2步:打开外部高速时钟晶振HSE,调用函数RCC_HSEConfig(RCC_HSE_ON); 第3步:等待外部高速时钟晶振工作,调用HSEStartUpStatus=RCC_WaitForHSEStartUp (); 第4步:设置AHB时钟,即调用函数RCC_HCLKConfig; 第5步:设置高速AHB时钟,即调用函数RCC_PCLK2Config;
第6步:设置低速AHB时钟,即调用函数RCC_PCLK1Config;第7步:设置PLL,即调用函数RCC_PLLConfig;第8步:打开PLL,即调用函数RCCPLLCmd(ENABLE);第9步:等待PLL工作,while(RCC_GetFlagStatus(RCC_FLAG—PLLRDY)==RESET);第10步:设置系统时钟,即调用函数RCC_SYSCLKConfig;第11步:判断PLL是否是系统时钟,while(RCCGetSYSCLKSource(!=OxO8);第12步:打开要使用的外设时钟,即调用函数RCCAPB2PeriphClockCmd;或者RCC_APB1PeriphClockGmd O。4.3STM32程序开发的模式STM32单片机系统的开发模式通常有两种:一是基于寄存器开发:二是基于ST公司官方提供的固件库开发。当然,还有一种是基于嵌入式操作系统的开发模式。4.3.1基于寄存器的开发模式1.理论基础(1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通信USART、串行接口总线(SPI、I2C)、中断及其机理等。(2)熟悉主要寄存器【控制寄存器(模式寄存器)、状态寄存器、数据寄存器、中断寄存器等】,掌握主要寄存器的功能、每个寄存器位的定义与作用,通过赋值语句来设置或获取相关寄存器的值。(3)明确程序开发要使用的功能部件及其程序设计要点,能按照要求初始化相关寄存器、查询和设置相关寄存器。2.工程模板的建立基于寄存器的程序开发模式可以使用更加精简的工程模板。但是,也可以与基于库函数的开发模式一起,使用统一的工程模板。关于如何建立STM32单片机系统的工程模板的内容比较复杂,这里先不不予展开。3.实践基础(1)根据欲开发的程序的功能与性能要求,合理规划程序模块,合理选择STM32的功能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。(2)采用分而治之的思想,先设计、调试各个模块的程序。(3)最后将各模块程序有机组合,再对程序进行统调和测试。4.基于寄存器的开发模式的特点(1)特点一:与硬件关系密切。程序编写直接面对底层的部件、寄存器和引脚。(2)特点二:要求对STM32的结构与原理把握得很清楚。要求编程者比较熟练地掌握STM32单片机的体系架构、工作原理,尤其是对寄存器及其功能要很熟悉。(3)特点三:程序代码比较紧、短小,代码完余相对较少,因此源程序生成的机器17
17 第6步:设置低速AHB时钟,即调用函数RCC_PCLKlConfig; 第7步:设置PLL,即调用函数RCC_PLLConfig; 第8步:打开 PLL,即调用函数RCC_PLLCmd(ENABLE); 第9步:等待 PLL工作,while(RCC_GetFlagStatus(RCC_FLAG—PLLRDY)== RESET); 第10步:设置系统时钟,即调用函数RCC_SYSCLKConfig; 第11步:判断PLL是否是系统时钟,while(RCC_GetSYSCLKSource()!=0x08); 第12步:打开要使用的外设时钟,即调用函数RCC_APB2PeriphClockCmd();或者 RCC_APB1PeriphClockGmd()。 4.3 STM32程序开发的模式 STM32单片机系统的开发模式通常有两种:一是基于寄存器开发;二是基于ST公司官方 提供的固件库开发。当然,还有一种是基于嵌入式操作系统的开发模式。 4.3.1 基于寄存器的开发模式 1.理论基础 (1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通 信USART、串行接口总线(SPI、I2C)、中断及其机理等。 (2)熟悉主要寄存器【控制寄存器(模式寄存器)、状态寄存器、数据寄存器、中断 寄 存器等】,掌握主要寄存器的功能、每个寄存器位的定义与作用,通过赋值语句来设置 或获取相关寄存器的值。 (3)明确程序开发要使用的功能部件及其程序设计要点,能按照要求初始化相关寄存 器、查询和设置相关寄存器。 2.工程模板的建立 基于寄存器的程序开发模式可以使用更加精简的工程模板。但是,也可以与基于库函 数的开发模式一起,使用统一的工程模板。关于如何建立STM32单片机系统的工程模板的内 容比较复杂,这里先不不予展开。 3.实践基础 (1)根据欲开发的程序的功能与性能要求,合理规划程序模块,合理选择STM32的功 能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。 (2)釆用分而治之的思想,先设计、调试各个模块的程序。 (3)最后将各模块程序有机组合,再对程序进行统调和测试。 4.基于寄存器的开发模式的特点 (1)特点一:与硬件关系密切。程序编写直接面对底层的部件、寄存器和引脚。 (2)特点二:要求对STM32的结构与原理把握得很清楚。要求编程者比较熟练地掌握 STM32单片机的体系架构、工作原理,尤其是对寄存器及其功能要很熟悉。 (3)特点三:程序代码比较紧凑、短小,代码冗余相对较少,因此源程序生成的机器
码比较短小。(4)特点四:开发难度较大、开发周期较长,后期维护、调试比较烦琐。在编程过程中,必须十分熟悉所涉及的寄存器及其工作流程,必须按照要求完成相关设置、初始化工作,开发难度相对较大。如果要扩充硬件、增加功能,这些后期的维护升级,相较于基于固件库的开发模式,要困难很多。4.3.2基于固件库的开发模式1.理论基础(1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通信USART、串行接口总线(SPI、I2C)、中断及其机理等。(2)熟悉固件库中相关部件所涉及的主要库函数各自的功能、调用要领、注意事项,包括系统初始化等函数。2.工程模板工程模板的建立比较复杂,单对基于于固件库函数的工程模板现在有了图形化工程模板建立软件STM32CubeMX,下面有关章节最详细说明。3.实践基础(1)根据欲开发的程序的功能与性能要求,合理规化程序模块,合理选择STM32的功能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。(2)采用分而治之的思想,先设计、调试各个模块南程序。3)最后将各模块有机组合,对程序进行统调和测试。4.基于固件库函数的开发模式的特点(1)特点一:与硬件关系比较疏远。由于函数的封装,使得与底层硬件接口的部分被封装,编程时不需要太关注硬件。(2)特点二:对STM32的结构与原理把握的要求相对较低。只要对硬件原理有一定的理解,能按照库函数的要求给定函数参数、利用返回值,即可调用相关函数,实现对某个部件、寄存器的操作。(3)特点三:程序代码比较烦琐、偏多。由于考虑到函数的稳健性、扩充性等因素,使得程序的穴余部分会较大。(4)特点四:开发难度较小、开发周期较短,后期维护、调试比较容易。外围设备的参考函数比较容易获取,也比较容易修改。4.3.3基于操作系统的开发模式1.操作系统的基本概念操作系统(OperatingSystem),简称oS,而嵌入式操作系统(EmbeddedOperatingSystem),简称EOS,它专门用于嵌入式系统。操作系统有实时和非实时之分,实时系统主要用于对时间响应要求比较高的场合。常用的嵌入式操作系统有:SmallRTOS,下C/oS-II,clinux,Linux,WinCE,eCoS18
18 码比较短小。 (4)特点四:开发难度较大、开发周期较长,后期维护、调试比较烦琐。在编程过程 中,必须十分熟悉所涉及的寄存器及其工作流程,必须按照要求完成相关设置、初始化工 作,开发难度相对较大。如果要扩充硬件、增加功能,这些后期的维护升级,相较于基于 固件库的开发模式,要困难很多。 4.3.2 基于固件库的开发模式 1.理论基础 (1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通 信USART、串行接口总线(SPI、I2C)、中断及其机理等。 (2)熟悉固件库中相关部件所涉及的主要库函数各自的功能、调用要领、注意事项, 包括系统初始化等函数。 2.工程模板 工程模板的建立比较复杂,单对基于于固件库函数的工程模板现在有了图形化工程模 板建立软件STM32CubeMX,下面有关章节最详细说明。 3.实践基础 (1)根据欲开发的程序的功能与性能要求,合理规化程序模块,合理选择STM32的功能 部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。 (2)采用分而治之的思想,先设计、调试各个模块南程序。 (3)最后将各模块有机组合,对程序进行统调和测试。 4.基于固件库函数的开发模式的特点 (1)特点一:与硬件关系比较疏远。由于函数的封装,使得与底层硬件接口的部分被 封装,编程时不需要太关注硬件。 (2)特点二:对STM32的结构与原理把握的要求相对较低。只要对硬件原理有一定的 理解,能按照库函数的要求给定函数参数、利用返回值,即可调用相关函数,实现对某个 部 件、寄存器的操作。 (3)特点三:程序代码比较烦琐、偏多。由于考虑到函数的稳健性、扩充性等因素, 使得程序的冗余部分会较大。 (4)特点四:开发难度较小、开发周期较短,后期维护、调试比较容易。外围设备的 参考函数比较容易获取,也比较容易修改。 4.3.3 基于操作系统的开发模式 1.操作系统的基本概念 操作系统(Operating System),简称0S,而嵌入式操作系统(Embedded Operating System),简称EOS,它专门用于嵌入式系统。 操作系统有实时和非实时之分,实时系统主要用于对时间响应要求比较高的场合。 常用的嵌入式操作系统有:small_RT0S,卜C/OS-II, clinux, Linux, WinCE, eCOS
jxCLinux,FreeRTOS等。eCOS是真正的GPL实时嵌入式OS,大概比gC/OS-II大一倍,它是为解决Linux的实时性不好而开发的,很有前途。RC/OS-II是赫赫有名的开源嵌入式.OS,但如果用于商业目的则需要授权。它的内核简单清晰,是学习嵌入式实时操作系统极好的入门材料。近来增加了pC/GUI图形界面,ixC/FS文件系统,pC/TCP网络功能。它对一般的项目开发是一个不错的选择。它已被广泛地使用在8位的51系列单片机应用系统中,同时它也支持16位、32位的系统。2.为什么要用操作系统在8位或16位嵌入式系统应用中,由于CPU的资源量比较少,任务比较简单,程序员可以在应用程序中管理CPU资源,而不一定要专用的系统软件。如果嵌入式系统比较复杂并且采用32位CPU时,情况就完全不同了。32位CPU的资源量非常大,处理能力也非常强大,如果还是采用手工编制CPU的管理程序,面对复杂的应用,很难发挥出32位CPU的处理能力:并且程序也不一定可靠。举个例子:我们平时用的计算机,有比较丰富的外设资源,如果不使用操作系统,我们自已用开发工具从底层开始写程序,搞个一年半载的,或许也可以让计算机跑起来,在显示器上搞个类似的Windows界面。然而,如此的“裸系统”根本无法让PC发挥出强大的处理能力,并且要想在已有的程序上增加应用功能,必须要熟悉全部程序的流程,或许还要去熟悉硬件知识,看硬件的datasheet。如果想移植到另外一台配置不同的计算机上,估计大部分程序都得推倒重来!在嵌入式上使用操作系统有两个方面的好处:(1)操作系统的一个强项就是它可以使应用程序编码在很大程度上与目标板的硬件和结构无关,使程序员可以将尽可能多的精力放在应用程序本身,而不必去花更多的精力去关注系统资源的管理。(2)使系统开发变得简单,缩短了开发周期:而且使应用系统更加健壮、高效、可靠。3.基于操作系统的程序开发模式就是程序的开发建立在系统嵌入操作系统的基础上,通过操作系统的API接口函数完成系统的程序开发。这种模式至少有两个基本步骤。第一步:首先选择和使用合适的操作系统并将操作系统裁减后嵌入系统。第二步:基于操作系统的API接口函数,完成系统所需功能的程序开发。4.该模式的特点从理论上讲,基于操作系统的开发模式,具有快捷、高效的特点,开发的软件移植性、后期维护性、程序稳健性等都比较好。但是,不是所有系统都要基于操作系统,因为这神模式要求开发者对操作系统的原理有比较深透的掌握,一般功能比较简单的系统,不建议使用操作系统,毕竞操作系统也占用系统资源;也不是所有系统都能使用操作系统,因为操作系统对系统的硬件有一定的要求。因此,在通常情况下,虽然STM32单片机是32位系统,但不主张嵌入操作系统,19
19 jxCLinux, FreeRTOS等。eCOS是真正的GPL实时嵌入式OS,大概比gC/OS-II大一倍,它是为 解决Linux的实时性不好而开发的,很有前途。RC/0S-II是赫赫有名的开源嵌入式. 0S,但 如果用于商业目的则需要授权。它的内核简单清晰,是学习嵌入式实时操作系统极 好的入 门材料。近来增加了 pC/GUI图形界面,ixC/FS文件系统,pC/TCP网络功能。它对一般的项 目开发是一个不错的选择。它已被广泛地使用在8位的51系列单片机应用系统中,同时它也 支持16位、32位的系统。 2.为什么要用操作系统 在8位或16位嵌入式系统应用中,由于CPU的资源量比较少,任务比较简单,程序员可 以在应用程序中管理CPU资源,而不一定要专用的系统软件。如果嵌入式系统比较复杂并且 采用32位CPU时,情况就完全不同了。32位CPU的资源量非常大,处理能力也非常强大,如 果还是采用手工编制CPU的管理程序,面对复杂的应用,很难发挥出32位CPU的处理能力, 并且程序也不一定可靠。 举个例子:我们平时用的计算机,有比较丰富的外设资源,如果不使用操作系统,我 们自己用开发工具从底层开始写程序,搞个一年半载的,或许也可以让计算机跑起来,在 显示器上搞个类似的Windows界面。然而,如此的“裸系统”根本无法让PC发挥出强大的处 理能力,并且要想在己有的程序上增加应用功能,必须要熟悉全部程序的流程,或许还要 去熟悉硬件知识,看硬件的datasheet。如果想移植到另外一台配置不同的计算机上,估计 大部分程序都得推倒重来! 在嵌入式上使用操作系统有两个方面的好处: (1)操作系统的一个强项就是它可以使应用程序编码在很大程度上与目标板的硬件和 结构无关,使程序员可以将尽可能多的精力放在应用程序本身,而不必去花更多的精力去 关 注系统资源的管理。 (2)使系统开发变得简单,缩短了开发周期;而且使应用系统更加健壮、高效、可靠。 3.基于操作系统的程序开发模式 就是程序的开发建立在系统嵌入操作系统的基础上,通过操作系统的API接口函数完成 系统的程序开发。 这种模式至少有两个基本步骤。 第一步:首先选择和使用合适的操作系统并将操作系统裁减后嵌入系统。 第二步:基于操作系统的API接口函数,完成系统所需功能的程序开发。 4.该模式的特点 从理论上讲,基于操作系统的开发模式,具有快捷、高效的特点,开发的软件移植性 、后期维护性、程序稳健性等都比较好。但是,不是所有系统都要基于操作系统,因为这 神模式要求开发者对操作系统的原理有比较深透的掌握,一般功能比较简单的系统,不建 议使用操作系统,毕竟操作系统也占用系统资源;也不是所有系统都能使用操作系统,因 为操作系统对系统的硬件有一定的要求。因此,在通常情况下,虽然STM32单片机是32位系 统,但不主张嵌入操作系统
4.3.43种开发模式的选用建议基于操作系统的开发模式,对于初学者不是很合适,因为它对操作系统、多任务等理论把握的要求较高。建议学习者在对嵌入式系统的开发达到一定的阶段后,再开始尝试这种开发模式。从高效开发的角度,从学习容易上手的角度,建议使用基于固件库函数的开发模式毕竟这种模式把底层比较复杂的一些原理和概念封装起来了,更容易理解。这种模式开发的程序更容易维护、移植,开发周期更短,程序出错的概宇更小。当然,也可以采用基于寄存器和基于固件库混合的方式。4.3.5库函数与寄存器开发的关系很多用户都是从学51单片机开发转而想进一步学习STM32开发,他们习惯了51单片机的寄存器开发方式,突然一个STM32固件库摆在面前会一头雾水,不知道从何下手。下面我们将通过一个简单的例子来告诉STM32固件库到底是什么,和寄存器开发有什么关系?其实一句话就可以概括:固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API)。在51的开发中我们常常的作法是直接操作寄存器,比如要控制某些10口的状态,我们直接操作寄存器:PO=0X11;而在STM32的开发中,我们同样可以操作寄存器:GPI0F->BSRR=0x00000001://这里是针对STM32F4系列这种方法当然可以,但是这种方法的劣势是你需要去掌握每个寄存器的用法,你才能正确使用STM32,而对于STM32这种级别的MCU,数百个寄存器记起来又是谈何容易。于是ST(意法半导体)推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整套接口(API)供开发者调用。大多数场合下,我们不需要去知道操作的是哪个寄存器,只需要知道调用哪些函数即可。比如上面的控制BSRRL寄存器实现电平控制,官方HAL库封装了一个函数:voidHAL_GPIO_WritePin(GPIO_TypeDef*GPIOx,uint16_tGPIO_PinGPIO_PinStatePinState)这个时候我们不需要再直接去操作BSRRL寄存器了,只需要知道怎么使用HAL_GPIO_WritePin这个函数就可以了。在我们对外设的工作原理有一定的了解之后,再去看固件库函数,基本上函数名字能告诉你这个函数的功能是什么,该怎么使用,这样开发会方便很多。任何处理器,不管它有多么的高级,归根结底都是要对处理器的寄存器进行操作。但是固件库不是万能的,我们如果想要把STM32学透,光读STM32固件库是远远不够的。我们还是要了解一下STM32的原理,了解STM32各个外设的运行机制。只有了解了这些原理,在进行固件库开发过程中才可能得心应手游刃有余。只有了解了原理,才能做到“知其然知20
20 4.3.4 3种开发模式的选用建议 基于操作系统的开发模式,对于初学者不是很合适,因为它对操作系统、多任务等理 论把握的要求较高。建议学习者在对嵌入式系统的开发达到一定的阶段后,再开始尝试这 种开发模式。 从高效开发的角度,从学习容易上手的角度,建议使用基于固件库函数的开发模式, 毕竟这种模式把底层比较复杂的一些原理和概念封装起来了,更容易理解。这种模式开发 的程序更容易维护、移植,开发周期更短,程序出错的概宇更小。 当然,也可以采用基于寄存器和基于固件库混合的方式。 4.3.5 库函数与寄存器开发的关系 很多用户都是从学 51 单片机开发转而想进一步学习STM32开发,他们习惯了51单片机 的寄存器开发方式,突然一个STM32固件库摆在面前会一头雾水,不知道从何下手。下面我 们将通过一个简单的例子来告诉STM32 固件库到底是什么,和寄存器开发有什么关系?其 实一句话就可以概括:固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直 接打交道,向上提供用户函数调用的接口(API)。 在51的开发中我们常常的作法是直接操作寄存器,比如要控制某些IO口的状态,我们 直接操作寄存器: P0=0X11; 而在 STM32 的开发中,我们同样可以操作寄存器: GPIOF->BSRR=0x00000001; //这里是针对 STM32F4 系列 这种方法当然可以,但是这种方法的劣势是你需要去掌握每个寄存器的用法,你才能 正确使用STM32,而对于STM32这种级别的MCU,数百个寄存器记起来又是谈何容易。于是 ST(意法半导体)推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整 套接口(API)供开发者调用。大多数场合下,我们不需要去知道操作的是哪个寄存器,只 需要知道调用哪些函数即可。比如上面的控制 BSRRL 寄存器实现电平控制,官方 HAL 库 封装了一个函数: void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 这个时候我们不需要再直接去操作BSRRL寄存器了,只需要知道怎么使用 HAL_GPIO_WritePin 这个函数就可以了。在我们对外设的工作原理有一定的了解之后,再 去看固件库函数,基本上函数名字能告诉你这个函数的功能是什么,该怎么使用,这样开 发会方便很多。 任何处理器,不管它有多么的高级,归根结底都是要对处理器的寄存器进行操作。但 是固件库不是万能的,我们如果想要把STM32学透,光读STM32固件库是远远不够的。我们 还是要了解一下STM32的原理,了解STM32各个外设的运行机制。只有了解了这些原理,在 进行固件库开发过程中才可能得心应手游刃有余。只有了解了原理,才能做到“知其然知