STM32库函数编程思路总结及其与寄存器编程的对比剖析

发布者:温暖梦想最新更新时间:2019-01-30 来源: eefocus关键字:STM32  库函数  编程思路  寄存器编程 手机看文章 扫描二维码
随时随地手机看文章

一、STM32库函数编程思路总结


1、基于STM32库函数的开发过程


进行具体的项目开发前,做好项目创建工作,通常包括如下步骤:


(1)新建工程项目的文件夹和子文件夹(如user、output、listing等)


(2)使用MDK新建(或打开项目),选择目标CPU、添加CMSIS核心、STM32启动代码和外设驱动程序,构成运行环境。


(3)添加包含main()函数的主程序文件。


(4)配置目标选项。


这些项目创建的步骤是通用的,项目构建确认无误后,可以复制整个项目文件夹的内容并保存,再次创建项目时可以直接应用(仅需适当改变项目名称等)。


通过以下步骤对项目本身流程进行分析,以明确并掌握相关外设的STM32驱动函数(以GPIO控制LED为例):


(1)为每个目标板上的外设编写一个驱动程序源文件[ led.c ],包含外设初始化函数[ led_init() ]和简单通用的外设操控函数      [ led_on_all()](直接应用性质的控制函数)


(2)将外设驱动程序的常量定义、函数声明等写入对应的头文件[ led.h ]。源程序文件[ led.c ]要包含其头文件[ led.h ],并添加到项目的源文件组中[ user ]。


(3)单独编写一个主程序文件[ main() ],实现项目需要的主控流程。主程序应包含外设驱动头文件[ led.h ](无需包含GPIO和RCC的头文件,尽管它们是必须被调用的。如下图所示,因为在配置RTE时已经在StdPeriph Drivers中选择了GPIO和RCC等外设驱动,故已经自动添加了该部分,无需在自己编写的源程序main()、led()中添加),并调用外设操控函数[ led_on_all()]或STM32库函数[ GPIO_ResetBits() ]实现外设控制。

主函数的调用关系如下图所示:

项目构建后最好先进行软件模拟,然后将程序下载到目标板进行硬件调试和运行。除了常规的寄存器、存储器等显示窗口,还应该利用外设窗口和逻辑分析仪窗口观测外设及其引脚的工作状态,尤其是在软件模拟时。


二、使用STM32库函数的一般规则


CMSIS和STM32库本身比较复杂,但有统一的规范。熟悉这些规律有助于我们更好地使用驱动程序。


1、常量定义


各种参数有宏定义或者枚举常量。对于每个寄存器而言,各个参量的值即为填入寄存器中某位的数值,名称一致。


2、外设函数


外设函数名用一个下划线分割两部分。各种外设往往具有功能雷同的函数,STM32库采用统一的函数名称,如下表所示。


3、外设结构类型


每种外设至少有2个结构体数据类型:位于stm32f10x.h头文件中的外设寄存器结构体PPP_TypeDef,用于访问外设寄存器;另一个是位于外设头文件stm32f10x_ppp.h中的外设初始化结构体PPP_InitTypeDef,用于配置外设初始化参数。


其中,


stm32f10x.h头文件中主要包含三部分内容:


(1)所有外设的寄存器结构体


(2)所有外设的内存映射


(3)用于每个寄存器位设置的宏定义常量(名称和寄存器的位名称一致,便于移植和应用)


stm32f10x_ppp.h头文件中主要包含:


(1)库函数,用于实现外设具备的各种功能


(2)宏定义、枚举常量以及外设初始化的结构体,用于抽象化硬件。常量就是设置相应寄存器位功能的数值,以达到所需的功能。


有了这两个外设结构体,就可以使用外设驱动程序库进行编程,步骤如下:


(1)开启外设时钟:使用RCC的外设时钟命令函数。——可以工作


(2)初始化外设:定义外设初始化结构变量,为外设初始化结构变量成员赋值,调用外设初始化函数配置外设。——如何工作


(3)控制外设:使用驱动程序库函数编写应用程序。——进行工作


4、外设初始化


外设初始化和配置的一般步骤如下:


(1)定义外设初始化结构变量:PPP_InitTypeDef   PPP_initStructure;


(2)用允许的成员值填充外设初始化结构成员变量


    方法1:逐个成员地填充整个结构体


PPP_InitStructure.number1=Val1;


...........


PPP_InitStructure.numberN=ValN;


   方法2:当成员较多,且无需全部设置为用户指定的特定值时,可以用PPP_StructInit()函数先将所有成员值设置为系统默认值后,再对其中的部分参数进行重新赋值。


PPP_StructInit(&PPP_InitStructure);


PPP_InitStructure.numberX=ValX;


PPP_InitStructure.numberY=ValY;


(3)调用PPP_Init()函数初始化外设


PPP_Init(PPP,&PPP_InitStructure)


(4)用PPP_Cmd()函数打开外设时钟,允许外设开始工作


PPP_Cmd(PPP,ENABLE);


经过以上4步对外设初始化后,可以灵活运用库函数进行应用程序的开发。


以初始化GPIO为例(库函数):


void GPIO_Init(void)


{


GPIO_InitTypeDef GPIO_InitStructure;


GPIO_InitStructure.GPIO_Pin = PIN_LED;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);


        RCC_APB2PeriphClockCmd(RCC_LED, ENABLE);  


GPIO_ResetBits(GPIOB,GPIO_Pin_All);

}


二、采用库函数和直接对外设寄存器编程的对比



以初始化GPIO为例(库函数):源代码共86行代码,在写入寄存器数值前需要大量代码去判断工作模式和配置的引脚,最后才组合出正确的数值


void GPIO_Init(void)


{


GPIO_InitTypeDef GPIO_InitStructure;


GPIO_InitStructure.GPIO_Pin = PIN_LED;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);


        RCC_APB2PeriphClockCmd(RCC_LED, ENABLE);  


GPIO_ResetBits(GPIOB,GPIO_Pin_All);

}



以初始化GPIO为例(寄存器):源代码只有1条语句,直接对端口配置寄存器CRL进行赋值,即可初始化配置端口


void GPIO_Init(void)


{


GPIOB->CRL=0X44444443;


}


由上面的例子可知,STM32库函数本质上是对外设寄存器直接编程,只是为了方便应用封装成了函数。所以用户的应用程序也可以绕过库函数,直接对寄存器编程。


直接对寄存器编程的代码效率最高。不过,需要花费较多的时间学习和查阅STM32数据手册,这个过程繁琐、易错,难以移植。


库函数就是用宏定义、枚举标识符等代表的数值写入寄存器,替用户摆脱枯燥的机械过程。在一些代码要求高效率的情况下,对寄存器编程是非常必要的。同时,对寄存器的学习与操作,将非常有助于我们在出错时进行程序调试。


关键字:STM32  库函数  编程思路  寄存器编程 引用地址:STM32库函数编程思路总结及其与寄存器编程的对比剖析

上一篇:STM32F103串口配置,并且使用printf进行打印
下一篇:STM32标准库函数命名规则

推荐阅读最新更新时间:2024-03-16 16:23

STM32 ADC应用要注意的几点问题
所有的STM32芯片中都带有逐次逼近型ADC模块,关于它的应用非常广泛和频繁。不过,应用过程中时常也会遇到些问题,这尽力小结下,与大家分享出来算作一些提醒。 1、Vdda没有供电或没有正常供电;STM32系列众多,该参数不可一概而论,细节请参考各个芯片数据手册。 2、采样电阻取值不合适,跟采样时间不匹配,经常表现为输入电阻过大、配置的采样时间偏短。实际设计时可以参考下STM32官方各系列评估板的相关电路。另外可以参考ST官方的应用笔记AN2834。关于ADC 应用其它的应用笔记,可以去WWW.STMCU.COM.CN搜索ADC即可。 3、ADC上电开启到稳定需要一段时间,即Tstab,该参数在数据手册里有介绍。在
[单片机]
<font color='red'>STM32</font> ADC应用要注意的几点问题
STM32+FreeRTOS+CUBEMX_学习笔记(五 )ADC采样
前言 ADC采样是一种常见的功能 1、STM系列ADC的参数: 手册中关于ADC的介绍 ● 12位分辨率 ● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断 ● 单次和连续转换模式 ● 从通道0到通道n的自动扫描模式 ● 自校准 ● 带内嵌数据一致性的数据对齐 ● 采样间隔可以按通道分别编程 ● 规则转换和注入转换均有外部触发选项 ● 间断模式 ● 双重模式(带2个或以上ADC的器件) ● ADC转换时间: ─ STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs) ─ STM32F101xx基本型产品:时钟为28MHz时为1μs(时钟为36MHz为1.55μs) ─ STM3
[单片机]
STM32+FreeRTOS+CUBEMX_学习笔记(五 )ADC采样
STM32学习笔记整理之(2)——外部中断
学习STM32也快一年了,现在工作的内容跟用的是STM32平台的,趁着年前工作量比较小,总结一下STM32的基础知识,不出意外的话将会连续发布完整的笔记整理,学习的时候主要是跟着野火教程学的,然后在整理出适合自己的笔记。 2.1 NVIC配置 1、中断分组 在配置优先级的时候,NVIC 只可以配置 16 种中断向量的优先级,抢占优先级和响应优先级的数量由一个 4 位的数字来决定,把这个 4 位数字的位数分配成抢占优先级部分和响应优先级部分。 有 5 组分配方式: 第0组:所有4位用来配置响应优先级。 第1组:最高1位配抢占优先级,低3位配响应优先级。2^1=2 种抢占优先级(0,1),2^3=8 种响应优先级, 第2组:2位
[单片机]
stm32的滴答时钟systick
SysTick定时器被捆绑在NVIC中,用于产生SysTick异常(异常号:15)。 Systick 部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是: STK_CSR, 0xE000E010 -- 控制寄存器 STK_LOAD, 0xE000E014 -- 重载寄存器 STK_VAL, 0xE000E018 -- 当前值寄存器 STK_CALRB, 0xE000E01C -- 校准值寄存器 所有的Cortex‐M3处理器内部都包含了这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟free clock),或者是外部时钟( C
[单片机]
STM32启动文件简介、详细步骤及代码讲解
01启动文件简介 startup_stm32f429_439xx.s是STM32的启动文件。 刚开始我一直认为STM32程序开始执行是从main函数开始。后来网上查查不是。原来在执行main函数之前,需要先执行一段汇编程序和完成C语言资源硬件的初始化工作。就是以下几个功能: 1--初始化栈指针MSP=_initial_sp。 2--初始化复位程序计数寄存器值=Reset_Handler。 3--初始化异常/ 中断向量表。 4--系统时钟配置。 5--C库函数_main初始化用户堆栈的调用 。 02文件启动步骤 1-在启动的时候,先对堆栈的大小定义,并在代码区的起始位置建立异常中断向量表。然后在复位中断中服务程序中跳转执行C标
[单片机]
<font color='red'>STM32</font>启动文件简介、详细步骤及代码讲解
STM32的按键扫描
key.c #include key.h #include SysTick.h /******************************************************************************* * 函 数 名 : KEY_Init * 函数功能 : 按键初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void KEY_Init(void) { GPIO_InitTypeDef GP
[单片机]
STM32时钟配置方法详解
一、在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 二、在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法:如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理: ①对于
[单片机]
关于STM32存储的堆栈地址
由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。-程序结束后有系统释放 4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放 5、程序代码区—存放函数体的二进制代码。 STM32的地址
[单片机]
关于<font color='red'>STM32</font>存储的堆栈地址
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved