极简STM32:基于HAL库与FreeRTOS的Arm Cortex-M4编程与开发 课件 第2章 STM32编程基础_第1页
极简STM32:基于HAL库与FreeRTOS的Arm Cortex-M4编程与开发 课件 第2章 STM32编程基础_第2页
极简STM32:基于HAL库与FreeRTOS的Arm Cortex-M4编程与开发 课件 第2章 STM32编程基础_第3页
极简STM32:基于HAL库与FreeRTOS的Arm Cortex-M4编程与开发 课件 第2章 STM32编程基础_第4页
极简STM32:基于HAL库与FreeRTOS的Arm Cortex-M4编程与开发 课件 第2章 STM32编程基础_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章STM32编程基础2.2.1开发方式

2.2.2开发环境2.2.3程序下载及调试运行工具2.1STM32程序开发方式与开发环境

2.1STM32程序开发方式与开发环境

1.基于寄存器的程序开发该编程方法涉及直接操作底层硬件寄存器,能够充分利用硬件资源,实现系统性能的最优化,但是对开发人员的专业知识和实践经验要求较高,设计人员必须深入理解STM32的硬件架构及其寄存器功能。该开发方式尽管难度较大,会导致代码复杂且维护困难,但为开发者提供了极大的灵活性,允许直接管理硬件资源,实现底层硬件的优化配置。在特定应用场景下,如对实时性要求极高的系统或需要精确控制硬件行为的场合,这种编程方法能够展现其独特的优势。2.1.1程序开发方式2.1STM32程序开发方式与开发环境

2.基于固件包和HAL库的STM32程序开发在STM32的开发过程中,固件包扮演着至关重要的角色。它不仅提供了硬件抽象层(Hardware-Abstraction-Layer,HAL)库,还提供了启动代码、中间件组件和示例项目等丰富资源,为开发者提供了快速启动和运行项目的捷径,大大缩短了开发周期。同时,固件包中的代码具有良好的可移植性和可维护性,这为项目的长期发展提供了保障。1)HAL库HAL库是ST公司专门为STM32系列微控制器量身打造的。基于HAL库的程序开发是在商议中开发方式的基础上,通过抽象化的方式隐藏硬件操作的复杂性,使得开发者在进行硬件交互时,能够更加便捷和高效。HAL库提供了包括时钟管理、模拟数字转换、串行外设接口通信等在内的众多硬件操作功能,这些功能都是通过高级应用程序接口(Application-ProgrammingInterface,API)函数的形式呈现给开发者的。开发者无需深入硬件底层,就可以轻松地进行硬件操作,从而大大简化了编程过程,使得快速开发和原型设计变得更加容易。2.1STM32程序开发方式与开发环境

2)STM32CubeMX为了进一步简化和方便基于HAL库的程序开发流程,ST公司还专门提出了图形化配置工具STM32CubeMX,通过图形化界面配置微控制器的各种参数,并生成初始化代码。这大大降低了开发难度,使得开发者可以更专注于应用逻辑的实现,而不是底层硬件的配置。通过这种方式,开发者可以更加高效地利用STM32的性能,实现各种复杂的功能。2.1STM32程序开发方式与开发环境

3.基于FreeRTOS的STM32程序设计FreeRTOS是一个免费且开源的实时操作系统,专门为微控制器和嵌入式系统量身打造,具备轻量级、高效性、易移植性以及强大的功能特性。该系统因其卓越的可移植性,特别适合资源受限的微控制器环境,已成为众多嵌入式开发者的首选。FreeRTOS支持多种架构下的不同型号处理器,例如STM32系列的F1、F4、F7和H7等,均可实现FreeRTOS的移植。同时,ST公司已在STM32CubeMX生态系统中集成了对FreeRTOS操作系统的支持,这显著提升了开发者学习和应用FreeRTOS操作系统的便捷性。在FreeRTOS的架构中,开发者能够更加高效地管理任务、优先级、时间片、信号量、消息队列等资源,从而使得程序结构更为清晰,代码的可维护性得到增强。此外,FreeRTOS提供了丰富的API函数,赋予开发者更大的灵活性以控制任务的创建、删除、挂起、恢复等操作,以满足多样化的应用需求。同时,FreeRTOS还支持任务间的通信机制,包括队列、信号量、二值信号量等,这使得任务间的数据交换和同步更为便捷。2.1STM32开发环境

2.1.2开发环境KeilMDK:提供了一个全面的集成开发环境,支持多种嵌式平台,支持C++和汇编语言,可以开发绝大多数的单片机嵌入式系统,拥有强大的调试功能,包括单步调试、锻炼调试、变量监视以及寄存器监视等。IAR:瑞典IARSystem公司提供的一系列软件开发工具,在界面、代码编辑以及调试和支持工具包等方面与MDK基本相同。VSCode:全称是VisualStudioCode,适用于多种编程语言,同样有断点变量监测等调试的基本功能。只需要安装相应的插件即可用于嵌入式系统开发。STM32CubeIDE:ST公司官方提供的免费软件开发工具,提供了GCC编译工具链和GDB调试工具,支持添加第三方功能插件,并集成了STM32CubeMX以便进行STM32配置和项目创建,提供了一体化工具体验,可以完成从芯片选型、项目配置、代码生成到代码编写、编译、调试和烧录的所有工作,简化了开发环境的搭建,有效地缩短了开发时间。2.1STM32开发环境

STM32Cube生态系统是针对STM32微控制器和微处理器的完整软件解决方案,不仅适用于需要STM32完整且免费的开发环境的用户,也适用于已经有IDE(包括Keil或IAR)的用户,可以轻松地集成STM32CubeMX、STM32CubeProgrammer或STM32CubeMonitor等各种组件。STM32Cube是一系列软件工具和嵌入式软件包的结合体,其中提供了一整套满足完整项目开发周期所有需求的软件工具(SoftwareTools)和嵌入式软件(EmbeddedSoftware)模块,如图2-1所示。STM32Cube生态系统2.1STM32开发环境

软件工具嵌入式软件2.1STM32开发环境

CubeIDE的下载和安装

下载和安装Java环境。Java官网,目前最新版本是V1.8.421。安装包文件名为jre-8u421-windows-x64.exe,直接双击即可安装。下载和安装CubeIDE软件。通过ST官网下载,在主页/中通过搜索stm32cubeide,在出现的页面中单击STM32CubeIDE即可跳转到下载页面,如图2-2所示。2.1STM32开发环境

2.1STM32开发环境

2.1.3程序下载及调试运行工具STM32开发过程中用到的仿真器主要有3种,即DAP、STink和JLink。DAP是ARM公司的开源仿真器,可支持STM32仿真调试,并且带有虚拟串口功能,有高速和低速两个版本,具有免驱、速度快、价格便宜等特点。STLink是ST公司生产的仿真器,支持STM32和STM8仿真调试,目前最常用的是STLinkV2,支持全面、性能稳定,并且廉价。JLink是Segger公司的仿真器,可支持STM32仿真调试,具有稳定、高速的特点,但价格偏贵。仿真器的安装和程序下载运行2.1STM32开发环境

串口工具主要包括串口下载工具和串口调试助手。串口下载工具用于将HEX文件下载到开发板或实验箱。与仿真器的主要区别在于,串口下载工具不能实现在线硬件和软件联合调试。串口调试助手用于实现PC机与MCU之间的数据传送,通常用于在进行MCU串口功能和程序调试运行过程中观察运行结果。串口工具和程序下载嵌入式开发中既有底层硬件的开发,又涉及到上层应用的开发,因此应用程序的开发将同时需要涉及系统的硬件和软件。C语言既具有汇编语言操作底层的优势,又具有高级语言功能性强的特点,特别适合作为开发首选语言。1程序总是从main函数开始执行;2345函数是C语言的基本结构;函数由两部分组成:函数说明部分和函数体。

一个C语言程序包含若干个源程序文件(.c文件)和头文件(.h文件)。采用外设功能模块化设计方法,一个外设功能模块包括一个源文件(.c文件)和一个头文件(.h文件)。2.2嵌入式C语言基础2.2嵌入式C语言基础2.2.1结构体与枚举2.2.2数据类型别名 2.2.3指针2.1.4C语言中的位操作 2.1.5预处理与条件编译结构体数据类型及变量的定义声明结构体类型的基本语法格式为:struct结构体名{ 成员列表;}变量名列表;2.2.1结构体和枚举例如,如下语句

structTYPE_USA{ intbaudRate;

intwordLength; }usart1,usart2;声明了一个名为TYPE_USA的结构体数据类型,同时定义了两个该结构体类型的变量usart1和usart2。2.2嵌入式C语言基础结构体变量可以在结构体类型申明时同时进行定义,也可以在申明之后再用其他的语句进行定义。定义结构体变量的基本语法格式为:

struct结构体名

结构体变量列表;例如,前面定义的两个结构体变量也可以用如下语句定义:

structTYPE_USAusart1,usart2;一个结构体是由多个成员变量构成的,结构体中成员变量的引用方法为:

结构体变量名.成员名

比如可以用表达式usart1.baudRate引用结构体变量usart1中的成员变量baudRate。2.2嵌入式C语言基础与数组类似,在为结构体变量分配存储空间时,结构体变量中的各成员变量将按照结构体中定义的顺序依次分配连续的存储单元,各成员变量所占用的单元数取决于其数据类型。因此,一旦确定了结构体变量存储的起始单元地址,其中每个成员变量所占用的存储单元地址也就确定了。2.2嵌入式C语言基础枚举2.2嵌入式C语言基础枚举也是一种数据类型,用于将一个变量或对象的所有可能取值逐一列出,变量取值只限于列举出来的值(枚举成员)。枚举成员具有自动编号的功能,第一个枚举成员其默认值为整型的0,后续枚举成员的值递增1。例如,如下语句typedefenum{GPIO_PIN_RESET=0, //枚举成员取值设为0GPIO_PIN_SET

//取值默认递增1等于1}GPIO_PinState;将GPIO引脚的高低电平两种状态定义为枚举类型GPIO_PinState。关键字typedef用于为现有的数据类型创建一个新的名字,称为数据类型别名,用来简化变量的定义。例如,如下语句

typedefunsignedlonguint32;将数据类型unsignedlong重新命名(别名)为uint32。利用该别名,要定义一个无符号长整型变量i,可以用如下语句实现:

uint32i=0x20000000;2.2.2数据类型别名2.2嵌入式C语言基础结构体也是一种数据类型,因此也可以用typedef为其定义一个别名。例如,如下语句typedefstructTYPE_USA{ intbaudRate; intwordLength;}USART;定义了一个结构体类型别名UASRT,之后即可用如下类似语句 USARTusart1,usart2;定义两个结构体变量usart1、usart2。2.2嵌入式C语言基础指针也是一个变量,指向给定的存储单元。利用指针变量可以在程序中对存储单元和外设寄存器等实现绝对地址访问。指针变量一般以p开头,例如,如下语句

char*p_str=“Thisisatest!”;申明了一个p_str指针,指向字符串在内存中存放的首地址。2.2.3指针2.2嵌入式C语言基础在程序中,指针变量的典型应用有两种,分别是指针变量的赋值和指针指向单元的访问,并分别用运算符“*”和“&”实现。指针变量的赋值指的是将指针所指向的变量在存储器中所在单元的地址保存到指针变量中,例如,如下语句chari;char*p;p=&i;定义了一个字符型变量i和指针变量p,第三条语句将变量i所在存储单元的地址保存到指针变量p中,从而使指针p指向变量i。2.2嵌入式C语言基础利用上述方法使指针指向了某个存储单元或者单元中存放的变量后,即可用下面的语句

*p=0x00000100;向该存储单元中存入数据0x00000100,相当于为变量i赋值。结构体指针:指向一个结构体变量。例如,如下语句

structTYPE_USA*usart1;定义了结构体指针usart1,指向前面定义的TYPE_USA结构体类型的变量usart1。

2.2嵌入式C语言基础需要注意的是,对结构体指针变量,引用其中的结构体成员变量是通过“->”符号实现的。例如,要访问usart1结构体指针指向的结构体的成员变量baudRate,必须用如下表达式:

usart1->baudRate;在嵌入式系统编程中,位运算比其他运算更常用。这是由于嵌入式系统涉及到很多有关硬件寄存器的操作,而硬件寄存器由若干位组成,每位分别具有不同的作用和含义,经常需要单独对其中指定的位进行读写操作。C语言中基本的位运算操作符有6个:&:按位与; |:按位或;^:按位异或; ~:按位取反;<<n:左移n位; >>n:右移n位。2.2.4C语言中的位操作2.2嵌入式C语言基础对变量中指定的某些二进制位赋值,而不改变其他位。

2.2嵌入式C语言基础先对需要设置的位用“&”操作符进行清零操作,然后用“|”操作符进行赋值。例如:

GPIOA->MODER&=0xfffffbf;//将GPIOA-MODER中的D6位清零GPIOA->MODER|=0x00000040; /*设置D6位的值为1*/

利用移位操作提高代码的可读性2.2嵌入式C语言基础例如,

GPIOA->MODER|=1<<1;//将MODER中的D1位置1同样的功能,改用如下语句实现:

GPIOA->MODER|=0x0002;//可读性差,修改麻烦。

按位取反操作的使用技巧

2.2嵌入式C语言基础按位取反在设置寄存器的时候经常被使用,常用于清除指定寄存器中的某一位或某几个位。例如,下面的语句

GPIOA->MODER&=~(1<<0); /*关闭SYSTICK*/该语句仅设置MODER寄存器的D0位为0,其他位的值保持不变,实现的功能与下面的语句等效:GPIOA->MODER&=0XFFFFFFFE; /*关闭SYSTICK*/显然前者的可读性和可维护性都要比后者好。按位异或操作的使用技巧

2.2嵌入式C语言基础该功能非常适合用于控制某个位翻转,常见的应用场景就是控制LED闪烁。例如,如下语句

GPIOB->ODR^=1<<5;每执行一次,就会使PB5引脚的输出状态翻转一次,如果将LED接在PB5上,就可以看到LED闪烁一次,即亮/灭状态切换一次。

预处理

在编译之前所做的工作,由预处理程序负责完成,编译时系统将自动引用预处理程序对源程序中的预处理部分进行处理。

2.2.5预处理与条件编译2.2嵌入式C语言基础预处理通常用命令define实现,该命令一般放在程序文件的前面,用于将一个标识符(宏名,常量等)定义为一个字符串(替换文本)或常数值,称为宏常量。宏定义的一般格式为:

#define标识符

表达式

其中,“标识符”为所定义的宏常量名,一般全部用大写字母;

“表达式”可以是常数、表达式、格式串等。2.2嵌入式C语言基础例如:

#defineHSE_VALUE0x80000000U //定义宏常量预处理命令定义的宏也可以带有参数,称为宏函数。预处理命令定义的宏也可以带有参数,称为宏函数。例如,

#defineIS_GPIO_SPEED(SPEED)((SPEED==GPIO_SPEED_FREQ_LOW) ||(SPEED==GPIO_SPEED_FREQ_MEDIUM) ||(SPEED==GPIO_SPEED_FREQ_HIGH) ||(SPEED==GPIO_SPEED_FREQ_VERY_HIGH))嵌入式C语言常使用条件编译,通过条件判断来确定是否对某段源程序进行编译。一般用在头文件或文件开头部分。条件编译的用途:可以用源程序产生不同版本。条件编译说明#if条件编译命令,如果#if后面的表达式为true,则执行语句#ifdef判断某个宏是否被定义,若被定义,则执行语句#ifndef判断某个宏是否未被定义,若未被定义,则执行语句,与#ifdef相反#elif#else指令用于#if指令之后,当#if指令的条件不为真时,就编译#else后面的代码,elif相当于elseif#endif条件编译的结束命令,用在#if、#ifdef、#ifndef之后常用的条件编译命令条件编译2.2嵌入式C语言基础例如,如果选择了器件***405xx,则编译时包含该器件的头文件;否则,……:#ifdefined(STM32F405xx)

#include"stm32f405xx.h"……#elifdefined(STM32F407xx)

#include"stm32f407xx.h"……#else#error"PleaseselectfirstthetargetSTM32F4xxdeviceusedinyourapplication(instm32f4xx.hfile)"#endif如果没有定义***头文件,就定义该头文件:#ifndef__STM32F4xx_HAL_GPIO_H

#define__STM32F4xx_HAL_GPIO_H告诉编译器:如果是C++代码,下面的代码是用C语言编写的,应该用C语言规则调用:#ifdef__cplusplus

extern"C"{#endif2.2嵌入式C语言基础2.3基于寄存器的STM32程序设计

在基于寄存器的程序开发方式中,通过查阅官方用户手册对所需外设内部的寄存器组成、结构及各位的功能和含义说明,利用程序配置和访问相应的寄存器,从而实现相应的功能。设计步骤——创建和指定工作空间新建工程新建文件并编写程序工程配置、编译和下载运行2.3基于寄存器的STM32程序设计

2.3基于寄存器的STM32程序设计

2.3基于寄存器的STM32程序设计

2.3基于寄存器的STM32程序设计

【实践案例2-1】基于寄存器的STM32程序设计本案例要求实现的功能是点亮开发板上的一个LED。在开发板中,利用GPIOF端口的PF6、PF7和PF8引脚分别连接了红、绿、蓝三种颜色的LED,相关硬件电路如图2-9所示。2.3基于寄存器的STM32程序设计

新建工程选择目标器件2.3基于寄存器的STM32程序设计

头文件reg.h在工程浏览器中单击Inc文件夹,再单击File/New/HeaderFile菜单命令,在弹出的NewHeaderFile(新建头文件)对话框中,确认Sourcefolder为工程ex2_1下的Inc文件夹,并输入头文件名(Headerfile)为reg.h,如图2-10所示。2.3基于寄存器的STM32程序设计

头文件reg.h用于定义有关GPIO寄存器映射的代码,相当于C51程序中的reg51.h和reg52.h头文件。#definePERIPH_BASE ((unsignedint)0x40000000) //片上外设基地址

#defineAHB1PERIPH_BASE (PERIPH_BASE+0x00020000) //总线基地址

#defineRCC_BASE (AHB1PERIPH_BASE+0x3800) //RCC外设基地址

#defineRCC_AHB1ENR *(unsignedint*)(RCC_BASE+0x30) //RCC寄存器地址映射

#defineGPIOF_BASE (AHB1PERIPH_BASE+0x1400) //GPIOF外设基地址

#defineGPIOF_MODER *(unsignedint*)(GPIOF_BASE+0x00) //GPIOF寄存器地址映射

#defineGPIOF_OTYPER *(unsignedint*)(GPIOF_BASE+0x04)#defineGPIOF_OSPEEDR *(unsignedint*)(GPIOF_BASE+0x08)#defineGPIOF_PUPDR *(unsignedint*)(GPIOF_BASE+0x0C)#defineGPIOF_IDR *(unsignedint*)(GPIOF_BASE+0x10)#defineGPIOF_ODR *(unsignedint*)(GPIOF_BASE+0x14)#defineGPIOF_BSRR *(unsignedint*)(GPIOF_BASE+0x18)#defineGPIOF_LCKR *(unsignedint*)(GPIOF_BASE+0x1C)#defineGPIOF_AFRL *(unsignedint*)(GPIOF_BASE+0x20)#defineGPIOF_AFRH *(unsignedint*)(GPIOF_BASE+0x24)2.3基于寄存器的STM32程序设计

以GPIO的模式寄存器为例,相应的寄存器映射宏定义语句为:

#defineGPIOF_MODER *(unsignedint*)(GPIOF_BASE+0x00)等价于如下语句:p=(unsignedint*)(GPIOF_BASE+0x00)

#defineGPIOF_MODER *p则

GPIOF_MODER=0x00001000;等价于 *p=0x00001000;实现的功能是将指针p指向的存储单元(即GPIOF_MODER寄存器)赋值为0x00001000,从而设置GPIOF外设的引脚PF6为输出模式。2.3基于寄存器的STM32程序设计

#include<reg.h> /*导入寄存器映射头文件*/intmain(void){ RCC_AHB1ENR |=(1<<5); /*开启GPIOF时钟*/ GPIOF_MODER &=~(0x03<<(2*6)); GPIOF_MODER |=(1<<2*6); /*PF6MODER6=01b输出模式*/ GPIOF_OTYPER &=~(1<<1*6); GPIOF_OTYPER |=(0<<1*6); /*PF6OTYPER6=0b推挽模式*/ GPIOF_OSPEEDR &=~(0x03<<2*6); GPIOF_OSPEEDR |=(0<<2*6); /*PF6OSPEEDR6=0b速率2MHz*/ GPIOF_PUPDR &=~(0x03<<2*6); GPIOF_PUPDR |=(1<<2*6); /*PF6PUPDR6=01b上拉模式*/ GPIOF_BSRR =(1<<16<<6); /*PF6引脚输出低电平,点亮红灯*/ for(;;);}源文件(主程序文件)main.c2.3基于寄存器的STM32程序设计

例如,如下语句GPIOF_MODER&=~(0x03<<(2*6)); 使GPIOF_MODER寄存器中的D13D12位清零,而其余位保持不变。之后,再执行如下语句GPIOF_MODER|=(1<<2*6); 将GPIOF_MODER将D12位置位,其余所有位清零。MODER寄存器各位的含义2.3基于寄存器的STM32程序设计

例如,如下语句GPIOF_BSRR=(1<<16<<6);由PF6引脚复位,输出低电平,以点亮开发板上的红色LED。类似地,如下语句: GPIOF_BSRR=(1<<6); 使PF6引脚输出高电平,从而熄灭红灯。BSRR寄存器各位的含义2.3基于寄存器的STM32程序设计

根据上述介绍对工程属性进行配置,之后在工程浏览器中单击工程名,再单击工具栏上的Build按钮,编译工程。编译成功后,利用FlyMcu工具将Debug文件夹中的HEX文件下载到开发板,即可启动运行。工程配置、编译和下载运行2.3基于寄存器的STM32程序设计

【照猫画虎2-1】基于寄存器的STM32程序设计修改程序,实现开发板绿色或蓝色LED的闪烁。提示:在开发板中,绿色和蓝色LED分别接在STM32F07MCU的PF7和PF8引脚,当引脚输出低电平时,LED点亮。2.4库的创建2.4.1GPIO外设的封装与结构体定义2.4.2GPIO操作函数的创建【实践案例2-2】利用自定义库函数点亮LED【照猫画虎2-2】GPIO操作访问函数的定义2.4库的创建2.4.1GPIO外设的封装与结构体定义/*reg.h头文件*/#definePERIPH_BASE ((unsignedint)0x40000000) //片上外设基地址

#defineAHB1PERIPH_BASE (PERIPH_BASE+0x00020000) //总线基地址

#defineRCC_BASE (AHB1PERIPH_BASE+0x3800) //RCC外设基地址

#defineRCC_AHB1ENR *(unsignedint*)(RCC_BASE+0x30) //RCC寄存器地址映射#defineGPIOF_BASE (AHB1PERIPH_BASE+0x1400) //GPIOF外设基地址

#defineGPIOF_MODER *(unsignedint*)(GPIOF_BASE+0x00)//GPIOF寄存器映射

#defineGPIOF_OTYPER *(unsignedint*)(GPIOF_BASE+0x04)#defineGPIOF_OSPEEDR *(unsignedint*)(GPIOF_BASE+0x08)……

GPIO外设结构体和结构体指针定义删除2.4库的创建typedefstruct{ /*GPIO外设结构体定义

*/ __IO uint32_tMODER; /*GPIO模式寄存器*/ __IO uint32_tOTYPER; /*GPIO输出类型寄存器*/ __IO uint32_tOSPEEDR; /*GPIO输出速度寄存器

*/ __IO uint32_tPUPDR; /*GPIO上拉/下拉寄存器*/ __IO uint32_tIDR; /*GPIO输入数据寄存器*/ __IO uint32_tODR; /*GPIO输出数据寄存器*/ __IO uint16_tBSRRL; /*GPIO置位/复位寄存器低16位*/ __IO uint16_tBSRRH; /*GPIO置位/复位寄存器高16位*/ __IO uint32_tLCKR; /*GPIO配置锁定寄存器*/ __IO uint32_tAFR[2]; /*GPIO复用功能配置寄存器*/}GPIO_TypeDef;2.4库的创建考虑到外设寄存器的地址都是基于外设基地址的偏移地址,都是在外设基地址上逐个连续递增的,每个寄存器为32个字节,占用连续的4个字节存储单元。这种方式跟结构体里面的成员类似,所以可以定义一种结构体,将外设中各寄存器顺序作为结构体的成员变量。如果设置结构体的地址等于外设的基地址,则可以通过结构体访问外设中的全部寄存器。2.4库的创建/*定义GPIO外设结构体指针*/#defineGPIOF((GPIO_TypeDef*)GPIOF_BASE)其中通过强制类型转换将GPIOF_BASE转换为指向GPIO_TypeDef结构体类型的指针,并将其定义为GPIOF宏,代表GPIOF外设。通过对该宏的操作,即可访问GPIOF外设中的寄存器。2.4库的创建GPIO的初始化结构体在使用各种外设之前,都需要配置其工作模式、设置一些必须的参数等。在基于寄存器的开发方式中,为了对外设进行初始化,也需要查阅大量的手册和资料。为了方便,还是希望将这些初始化操作及所需的参数等定义和封装为库的一部分。不同外设的初始化所需配置的参数各不相同,因此一般将初始化所需的参数、数据等分别定义在不同的外设配置文件中。这里新建两个文件gpioInit.h和gpioInit.c,用于存放GPIO外设相关的初始化定义和封装代码。2.4库的创建GPIO工作模式的定义(gpioInit.h)typedefenum

{GPIO_Mode_IN =0x00, /*输入模式*/GPIO_Mode_OUT =0x01,

/*输出模式*/GPIO_Mode_AF =0x02,

/*复用模式*/GPIO_Mode_AN =0x03

/*模拟模式*/}GPIOMode_TypeDef;typedefenum{GPIO_OType_PP =0x00,

/*推挽模式*/GPIO_OType_OD =0x01 /*开漏模式*/}GPIOOType_TypeDef;……2.4库的创建初始化结构体的定义/*GPIO初始化结构体类型定义*/typedefstruct{uint32_t

GPIO_Pin;

/*选择要配置的GPIO引脚*/GPIOMode_TypeDef GPIO_Mode;

/*选择GPIO引脚的工作模式*/GPIOSpeed_TypeDefGPIO_Speed;

/*选择GPIO引脚的速率*/GPIOOType_TypeDefGPIO_OType;

/*选择GPIO引脚输出类型*/GPIOPuPd_TypeDef GPIO_PuPd;

/*选择GPIO引脚的上/下拉模式*/}GPIO_InitTypeDef;2.4库的创建GPIO引脚定义在上述结构体中,第一个成员用于指定需要初始化配置的GPIO引脚,为了方便,将这些代表引脚的取值常数定义为如下16个宏:#defineGPIO_PIN_0 ((uint16)(1<<0))#defineGPIO_PIN_1 ((uint16)(1<<1))#defineGPIO_PIN_2 ((uint16)(1<<2))#defineGPIO_PIN_3 ((uint16)(1<<3))……#defineGPIO_PIN_15 ((uint16)(1<<15))#defineGPIO_PIN_All ((uint16)0xFFFF)2.4库的创建2.4.2GPIO操作函数的创建前面定义了GPIO外设结构体,在此基础上即可使用函数来封装对GPIO外设的基本操作,所有对GPIO寄存器的操作访问都可以通过调用这些函数进行,而不再需要寄存器的地址和位格式等信息。GPIO的操作函数主要包括对GPIO引脚的初始化和GPIO引脚的读写访问等。这些函数都将定义在gpioInit.c文件中,而在对应的gpioInit.h头文件中,需要对这些函数做原型声明。2.4库的创建在头文件gpioInit.h中,添加GPIO操作函数的原型声明:此外,在gpioInit.h文件中还需要添加如下代码,将GPIO寄存器映射头文件reg.h包含进来:#include"reg.h"之后再将gpioInit.h导入gpioInit.c文件。voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct);voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16GPIO_Pin);voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16GPIO_Pin);2.4库的创建初始化函数的定义/*

函数功能:初始化引脚模式*参数说明:GPIOx,该参数为GPIO_TypeDef类型的指针,指向GPIO端口的地址*

GPIO_InitTypeDef:GPIO_InitTypeDef结构体指针,指向初始化变量*/voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct){uint32_tpinpos=0x00,pos=0x00,currentpin=0x00;for(pinpos=0x00;pinpos<16;pinpos++) /*pinpos引脚序号作为循环计数变量*/{ pos=((uint32_t)0x01)<<pinpos;

currentpin=(GPIO_InitStruct->GPIO_Pin)&pos;

/*确定指定引脚的序号*/2.4库的创建

if(currentpin==pos) {

GPIOx->MODER&=~(3<<(2*pinpos));

GPIOx->MODER|=(((uint32_t)GPIO_InitStruct->GPIO_Mode)<<(2*pinpos));

GPIOx->PUPDR&=~(3<<((2*pinpos)));

GPIOx->PUPDR|=(((uint32_t)GPIO_InitStruct->GPIO_PuPd)<<(2*pinpos));

/*若模式为"输出/复用"模式,则设置速度与输出类型*/

……

}

}}2.4库的创建使用举例GPIO_InitTypeDefInitStruct; /*定义初始化结构体变量*/InitStruct.GPIO_Pin=GPIO_Pin_6; /*指定GPIO引脚*/InitStruct.GPIO_Mode=GPIO_Mode_OUT; /*设置引脚模式为输出模式*/InitStruct.GPIO_OType=GPIO_OType_PP; /*设置输出类型为推挽输出*/InitStruct.GPIO_PuPd=GPIO_PuPd_UP; /*设置引脚为上拉模式*/InitStruct.GPIO_Speed=GPIO_Speed_2MHz; /*设置引脚速率为2MHz*/GPIO_Init(GPIOF,&InitStruct); /*调用初始化函数实现初始化*/2.4库的创建GPIO引脚的读写访问函数voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){ GPIOx->BSRRL=GPIO_Pin;}voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){ GPIOx->BSRRH=GPIO_Pin;}在stm32f4xx_gpio.c文件中,定义的两个GPIO引脚位操作函数如下:例如,通过PF6输出低电平:GPIO_ResetBits(GPIOF,GPIO_PIN_6);2.4库的创建【实践案例2-2】利用自定义库函数点亮LED在上述自定义库的基础上,本案例调用库中G

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论