STM32学习笔记——使用函数库编程控制GPIO口输出

发布者:Weasel最新更新时间:2015-08-14 来源: eefocus关键字:STM32  函数库  编程控制  GPIO口 手机看文章 扫描二维码
随时随地手机看文章
看了网上许多人的代码以及各类开发板所带的例程,大多数使用的都是官方发布的函数库来编程,通过查询后发现,使用函数库来编程可以简化开发过程,并不需要追溯到各个寄存器,通过查看库手册,新手也可以快速应用STM32,因此,决定先从函数库开始入门!

1. 建立带函数库的IAR项目工程

先从网上下载3.5版(据说3.0版以后的固件库才逐渐稳定)stm32固件库(stm32f10x_stdperiph_lib)。由于与固件库版本兼容问题,重新下载安装了IAR6.30版。

1.1 创建项目文件夹“project”;

1.2  解压“stm32f10x_stdperiph_lib.rar”后,

   将...stm32f10x_stdperiph_libSTM32F10x_StdPeriph_Lib_V3.5.0下的“Libraries”文件夹拷贝到“project”文件夹,并在“project”文件夹中新建“project”文件夹以便与“Libraries”文件夹区分开;

1.3 将...stm32f10x_stdperiph_libSTM32F10x_StdPeriph_Lib_V3.5.0ProjectSTM32F10x_StdPeriph_Template下的“main.c”、“stm32f10x_conf.h”、“stm32f10x_it.c”、“stm32f10x_it.h”拷贝至...projectproject文件夹中;

1.4 将...stm32f10x_stdperiph_libSTM32F10x_StdPeriph_Lib_V3.5.0ProjectSTM32F10x_StdPeriph_TemplateEWARM下的“stm32f10x_flash.icf”、“stm32f10x_flash_extsram.icf”、“stm32f10x_nor.icf”、“stm32f10x_ram.icf”拷贝至...projectprojectEWARM文件夹中。

1.5   新建IAR工程项目,添加分组及文件如图:

STM32学习笔记——使用函数库编程控制GPIO口输出

其中:

  Core_cm3.c在…projectLibrariesCMSISCM3CoreSupport文件夹中;

  System_stm32f10x.c在…projectLibrariesCMSISCM3DeviceSupportSTSTM32F10x文件夹中;

  Startup_stm32f10x_md.s在...projectLibrariesCMSISCM3DeviceSupportSTSTM32F10xstartupiar文件夹中,此外根据所使用芯片大小不同,所选择的startup文件也不同,具体选择如下:

 

startup_stm32f10x_cl.s   互联型的器件,STM32F105xx,STM32F107xx
startup_stm32f10x_hd.s     大容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_hd_vl.s  大容量的STM32F100xx
startup_stm32f10x_ld.s     小容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_ld_vl.s  小容量的STM32F100xx

startup_stm32f10x_md.s    中容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_md_vl.s  中容量的STM32F100xx
startup_stm32f10x_xl.s     FLASH在512K到1024K字节STM32F101xx,STM32F102xx,STM32F103xx

其中大、中、小容量的区分如下图所示:

STM32学习笔记——使用函数库编程控制GPIO口输出

各型号名称辨识如下图所示:

STM32学习笔记——使用函数库编程控制GPIO口输出

个人所使用的芯片型号是STM32F103VBT6,所以是属于中等容量,所以选择的是”startup_stm32f10x_md.s”文件。

 

      LWIB组则根据需要添加,由于要点亮led灯需要用到GPIO和时钟,所以添加了stm32f10x_gpio.c和stm32f10x_rcc.c两个文件,均     在...projectLibrariesSTM32F10x_StdPeriph_Driversrc下

       根据需要修改“main.c”文件,也可自己创建空白文件,但需要包含#include "stm32f10x.h"代 码。

项目设置

   除了“学前准备”文中所需要的设置外,还需要设置的项有:

    GeneralOptions>Library Configuration项:

STM32学习笔记——使用函数库编程控制GPIO口输出

 

C/C++Compiler>Preprocessor项:

STM32学习笔记——使用函数库编程控制GPIO口输出

    OutputConverter项:

STM32学习笔记——使用函数库编程控制GPIO口输出

   Output项:

STM32学习笔记——使用函数库编程控制GPIO口输出

至此,工程设置完毕,可以往main文件里写空代码试着编译,如:

 

[cpp] view plaincopy
 
  1. #include “stm32f10x.h”  
  2. Int main()  
  3. {While(1);}  


[page]

编译无误后即可开始写自己的代码。

附注:关于CMSIS的core_cm3文件,在编译的时候经常会报错,一般是无法找到”core_cm3.h”文件,但实际上该文件与”core_cm3.c”同处于同一个目录,具体原因未明。解决方法如下:

 

   IAR 6.20版本注释有如下一段话:

A special note on CMSISintegration:

If your application source code include CMSISheader files explicitly, then you should not check theUse CMSIS check-box Project>Options...>GeneralOptions>Library Configuration>UseCMSIS. Some of the Cortex-M application examplesincludes CMSIS source files explicitly, do not check the saidcheck-box in these projects.
However, due to the evolution of the IAR C/C++ Compiler for ARM,older versions of CMSIS are incompatible with the current versionof the compiler. One simple example of how to solve this issueis:
a) Press F4 to bring up the erroneous source (header) file in theeditor - in most cases named core_cm3.h.
b) Right-click on the window tab of that editor window,choose File Properties....
c) Add (or remove) any character to the file name - so the compilerwon't find it any more.
d) Modify project options: Check Project>Options...>GeneralOptions>Library Configuration>UseCMSIS.
Steps a) to c) might need to be done for more than one file.Normally, the names of these files are core_cm0.h, core_cm3.h,core_cm4.h, core_cmFunc.h and core_cmInstr.h.

即将”core_cm3.h”改名或删除,然后勾选工程设置中的”Use CMSIS”选项即可。

    经过摸索,通过拷贝IAR安装文件夹…IAR SystemsEmbedded Workbench6.0armCMSISInclude下的“core_cm3.h”、“core_cmFunc.h”、“core_cmInstr.h”三个文件到...projectLibrariesCMSISCM3DeviceSupportSTSTM32F10x文件中亦可成功编译。

 

2. 使用函数库编程

   个人觉得,使用函数库编程,主要是根据《基于ARM的32位MCU STM32F101xx 和 STM32F103xx固件库手册》(以下简称《固件库手册》),知晓各函数的用法,然后对其进行顶层调用。

2.1 与本例程有关的几个函数:

 2.1.1 RCC_APB2PeriphClockCmd函数

函数名

RCC_APB2PeriphClockCmd

函数原型

Void RCC_APB2PeriphClockCmd(u32RCC_APB2Periph,FunctionalState

 NewState)

行为描述

使能或关闭高速APB(APB2)外围设备时钟

输入参数1

RCC_APB2Periph:用于门控时钟的AHB2外围设备

涉及章节:RCC_AHB2Periph结构详细说明了这个参数允许的值。

输入参数2

NewState:专用外围设备时钟的新状态。

这个参数可以是:ENABLE或DISABLE。

输出参数

返回参数

调用前提条件

调用函数

 

RCC_APB2Periph值:

RCC_APB2Periph

描述

RCC_APB2Periph_AFIO

交替功能I/O时钟

RCC_APB2Periph_GPIOA

IO端口A时钟

RCC_APB2Periph_GPIOB

IO端口B时钟

RCC_APB2Periph_GPIOC

IO端口C时钟

RCC_APB2Periph_GPIOD

IO端口D时钟

RCC_APB2Periph_GPIOE

IO端口E时钟

RCC_APB2Periph_ADC1

ADC1接口时钟

RCC_APB2Periph_ADC2

ADC2接口时钟

RCC_APB2Periph_TIM1

TIM1时钟

RCC_APB2Periph_SPI1

SPI1时钟

RCC_APB2Periph_USART1

USART1时钟

RCC_APB2Periph_ALL

所有APB2外围设备时钟


例子:

 

[cpp] view plaincopy
 
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_SPI1,ENABLE);  

 

2.1.2 标签定义
   为了访问GPIO寄存器,_GPIO,_AFIO,_GPIOA,_GPIOB,_GPIOC,_GPIOD及_GPIOE必须在stm32f10x_conf.h中进行定义:

 

[cpp] view plaincopy
 
  1. #define _GPIO  
  2. #define _GPIOA  
  3. #define _GPIOB  
  4. #define _GPIOC  
  5. #define _GPIOD  
  6. #define _GPIOE  
  7. #define _AFIO  

 

关于此标签定义,还存在疑问,因为即便是没有进行如此定义,编译依旧通过,寄存器依旧可用。

 

2.1.3声明PPP_InitTypeDef结构

在初始化和配置外围模块时,必须在主应用程序文件中,声明一个PPP_InitTypeDef结构(PPP是外围模块),例如:

 

[cpp] view plaincopy
 
  1. PPP_InitTypeDef PPP_InitStructure;  

 

PPP_InitStructure是一个位于数据存储区的有效变量。

 

2.1.4 GPIO_Init函数

函数名

GPIO­_Init

函数原型

void GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef* GPIO_InitStruct)

功能描述

按照GPIO_InitStruct的特定参数初始化GPIO部件

输入参数1

GPIOx:x可为A到E来选择特定的GPIO部件

输入参数2

GPIO_InitStruct:指向GPIO_InitTypeDef结构的指针,它包含特定GPIO部件的配置信息。参考GPIO_InitTypeDef结构

输出参数

返回参数

前提条件

调用函数

 

GPIO_InitTypeDef结构

GPIO_InitTypeDef在stm32f10x_gpio.h中如下定义:

 

[cpp] view plaincopy
 
  1. typedef struct  
  2. {  
  3.       u16 GPIO_Pin;  
  4.       GPIO_Speed_TypeDef GPIO_Speed;  
  5.       GPIO_Mode_TypeDef GPIO_Mode;  
  6. } GPIO_InitTypeDef  

 

GPIO_Pin值

可用”|”完成多引脚的配置。

GPIO_Pin

描述

GPIO_Pin_None

没有引脚被选择

GPIO_Pin_x

引脚x被选择(x=0…15)

GPIO_Pin_All

所有引脚都被选择

 

GPIO_Speed值

GPIO_Speed

描述

GPIO_Speed_10MHz

最大输出频率=10MHz

GPIO_Speed_2MHz

最大输出频率=2MHz

GPIO_Speed_50MHz

最大输出频率=50MHz

 

GPIO_Mode值

GOIO_Mode是用来配置选定引脚的操作模式的。

GPIO_Mode

描述

GPIO_Mode_AIN

模拟输入

GPIO_Mode_IN_FLOATING

浮点输入

GPIO_Mode_IPD

下拉输入

GPIO_Mode_IPU

上拉输入

GPIO_Mode_Out_OD

开漏输出

GPIO_Mode_Out_PP

推拉输出

GPIO_Mode_AF_OD

开漏输出备用功能

GPIO_Mode_AF_PP

推拉输出备用功能


实例:

 

[cpp] view plaincopy
 
  1. GPIO_InitTypeDefGPIO_InitStructure;  
  2. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;  
  3. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  
  4. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;  
  5. GPIO_Init(GPIOA,&GPIO_InitStructure);  

 

2.1.5 GPIO_SetBits函数

函数名

GPIO_SetBits

函数原型

voidGPIO_SetBits(GPIO_TypeDef* GPIOx,u16 GPIO_Pin

功能描述

置位选定的端口位

输入参数1

GPIOx:x=A…E

输入参数2

GPIO_Pin:GPIO_Pin_x的任意组合,x=0…15。

输出参数

返回参数

前提条件

调用函数

 

实例:

 

[cpp] view plaincopy
 
  1. GPIO_SetBits(GPIOA,GPIO_Pin_10|GPIO_Pin_15);  

 

2.1.6 GPIO_ResetBits函数

函数名

GPIO_ResetBits

函数原型

void ResetBits(GPIO_TypeDef* GPIOx,u16 GPIO_Pin)

功能描述

清除选定的数据端口位

输入参数1

GPIOx:x=A…E

输入参数2

GPIO_Pin:GPIO_Pin_x(x=0…15)的任意组合

输出参数

返回参数

前提条件

调用函数

 

实例:

 

[cpp] view plaincopy
 
  1. GPIO_ResetBits(GPIOA,GPIO_Pin_10|GPIO_Pin_15);  

 

[page]

2.1.7 GPIO_Write 函数

函数名

GPIO_Write

函数原型

voidGPIO_Write(GPIO_TypeDef* GPIOx,u16 PortVal)

功能描述

写数据到指定的GPIO端口数据寄存器

输入参数1

GPIOx:x=A…E

输入参数2

PortVal:写入到数据端口寄存器的值

输出参数

返回参数

前提条件

调用函数

 

实例:

 

[cpp] view plaincopy
 
  1. GPIO_Write(GPIOA,0x1101);  

 

2.2 完整程序:

 

[cpp] view plaincopy
 
  1. #include "stm32f10x.h"  
  2. void delay(void);  
  3. void GPIO_Configuration(void);  
  4. int main(void)  
  5. {  
  6. //使能GPIOC时钟  
  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);  
  8.    
  9. //此条语句一定要在时钟使能后,否则无效(费了好多时间才找到原因)  
  10. GPIO_Configuration();   
  11. while(1)  
  12.   {  
  13.     //利用GPIO_SetBits函数与GPIO_ResetBits函数点亮与熄灭led  
  14.    GPIO_ResetBits(GPIOC,GPIO_Pin_7|GPIO_Pin_9);  
  15.    GPIO_SetBits(GPIOC,GPIO_Pin_6|GPIO_Pin_8);  
  16.    delay();  
  17.    GPIO_ResetBits(GPIOC,GPIO_Pin_6|GPIO_Pin_8);  
  18.    GPIO_SetBits(GPIOC,GPIO_Pin_7|GPIO_Pin_9);  
  19.    delay();  
  20.       
  21. //利用GPIO_Write函数点亮与熄灭led  
  22.    GPIO_Write(GPIOC,0x0140);  
  23.    delay();  
  24.    GPIO_Write(GPIOC,0x0280);  
  25.    delay();  
  26.   }  
  27. }  
  28.    
  29. //GPIO口设置  
  30. void GPIO_Configuration(void)  
  31. {  
  32.    
  33. //声明结构体  
  34.   GPIO_InitTypeDefGPIO_InitStructure;  
  35.    
  36. //设置选择引脚  
  37.  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;  
  38.    
  39. //设置引脚最大输出频率  
  40.  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  
  41.    
  42. //设置引脚输出模式  
  43.  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  
  44.    
  45. 根据设置的InitStructure 初始化GPIO口  
  46.  GPIO_Init(GPIOC,&GPIO_InitStructure);  
  47. }  
  48.    
  49. void delay(void)  
  50. {  
  51.  unsigned longj,n=100000;  
  52.  while(n--)  
  53.  {  
  54.   j=12;  
  55.   while(j--);  
  56.  }  
  57. }  


 

编译通过烧写到开发板上后,最终结果是:led1和led3与led2和led4两两交替亮灭。

 

参考文献

[1]jhliuzj.IAR FOR ARM6.20工程创建建议(固件库为3.5)[EB/OL].

http://hi.baidu.com/jhliuzj/item/459830ae7e19e136020a4d3f,2011-10-03/2012-08-25.

[2]kiropower.IARSTM32项目工程创建[EB/OL].http://hi.baidu.com/kiropower/item/e20faad0007502352b35c785,2011-11-10/2012-08-25.

[3]gasbi.startup_stm32f10x_xx.s 启动代码文件选择[EB/OL].

http://blog.csdn.net/gasbi/article/details/7545568,2012-05-08/2012-08-25.

[4]IAR Systems AB.Releasenotes for the IAR C/C++ Compiler for ARM 6.20.1[EB/OL].http://supp.iar.com/FilesPublic/UPDINFO/005832/arm/doc/infocenter/iccarm.ENU.html,2012-08-25

[5]Changing.用stm32点个灯[操作寄存器+库函数][EB/OL].

http://www.ichanging.org/stm32_gpio_led.html, 2012-06-29/2012-08-25.

 
20120827附:
关于标签定义问题,由于在main函数开头即声明#include "stm32f10x.h",而该头文件里又有如下代码:
[cpp] view plaincopy
 
  1. #ifdef USE_STDPERIPH_DRIVER  
  2.  #include "stm32f10x_conf.h"   
  3. #endif  
 
即当定义USE_STDPERIPH_DRIVER时,就会包含stm32f10x_conf.h,而我们在设置项目的时候,在"c/c++ compiler>define" 项中已经对其进行了预定义,所以也会自动加入stm32f10x_conf.h文件,该文件中包含了所有外设的头文件,因此可以直接调用函数。对不需要使用的外设,可以直接在该文件中将其注释掉,这样在编译的时候就不会编译被注释的文件。 
参考文献:jack.stm32f10x_conf.h与stm32f10x.h(转载)[EB/OL].http://blog.sina.com.cn/s/blog_7b93041501013o5b.html,2012-05-01/2012-08-27
关键字:STM32  函数库  编程控制  GPIO口 引用地址:STM32学习笔记——使用函数库编程控制GPIO口输出

上一篇:STM32的功能引脚重映射和复用功能
下一篇:STM32学习笔记——利用通用定时器TIM2进行精确延时

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

STM32 基于 CubeMX配置GPIO点亮LED灯
1 前言 本文基于ST的STM32F767ZI NUCLEO144开发板,结合CubeIDE的插件CubeMX配置生成代码点亮板载的LED,点亮可谓是单片机开发中的hello world,非常简单; 2 理论分析 2.1 LED 原理 发光二极管简称为LED,生活中几乎无处不在,由含镓(Ga)、砷(As)、磷(P)、氮(N)等的化合物制成。当电子与空穴复合时能辐射出可见光,因而可以用来制成发光二极管。在电路及仪器中作为指示灯,或者组成文字或数字显示。砷化镓二极管发红光,磷化镓二极管发绿光,碳化硅二极管发黄光,氮化镓二极管发蓝光。因化学性质又分有机发光二极管OLED和无机发光二极管LED 1 。 LED是正向
[单片机]
<font color='red'>STM32</font> 基于 CubeMX配置<font color='red'>GPIO</font>点亮LED灯
STM32的ETR引脚计数功能
1. 基本介绍 1.1. 开发环境 开发板:WarShip STM32 BOARD V2.1 CPU:STM32F103ZET6 1.2. ETR引脚配置 由上可知,使用STM32的ETR引脚计脉冲数,需将定时器的时钟源选择为外部时钟模式2 选定此模式的方法:令TIMx_SMCR寄存器中的ECE=1 计数器能够在外部触发ETR的每一个上升沿或下降沿计数 例如,要配置在ETR引脚上,每2个上升沿计数一次的向上计数器,使用下列步骤: 1. 本例中不需要滤波器,置TIMx_SMCR寄存器中的ETF =0000 2. 设置预分频器,置TIMx_SMCR寄存器中的ETPS =01 3. 设置在ETR的上升沿检测,
[单片机]
<font color='red'>STM32</font>的ETR引脚计数功能
STM32利用互补通道产生PWM信号
定时器分为普通定时器和高级定时器。STM32和GD32都有TIMERX_CHX_ON或者TIMERX_CHXN,这种定时器是一种互补定时器,我们同样可以看到还存在与其名字很像的TIMERX_CHX,TIMERX_CHX,这些都是基本的定时器,按照基本的配置即可产生PWM信号,这里不做介绍 。 下面主要说一下利用互补通道产生PWM信号。 void TIM1_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitType
[单片机]
<font color='red'>STM32</font>利用互补通道产生PWM信号
STM32调试-串口打印函数及使用方法
1.在usart.h文件里,添加以下代码: #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1- SR&0X40)==0);//循环发送,直到发送完毕 USART1- DR = (u8) ch;
[单片机]
STM32——GPIO的CRL、CRH和CNF与MODE的关系
GPIO的CRL、CRH和CNF与MODE的关系 STM32的CRL控制着每个IO端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。 CRH的作用和CRL完全一样,只是CRL控制的是低8位输出口,而CRH控制的是高8位输出口。
[单片机]
STM32 通用定时器的一些概念解析
STM32一共有8个定时器,其中定TIM1和TIM8为高级控制定时器,除了具有通用定时器的功能外,还兼具控制功能,不仅能够输出PWM还可以采集编码器,驱动各种电机的功能。而基本定时器TIM6和TIM7一般不用作普通定时器,一般会给别的定时器提供基准时钟信号。 对于通用定时器TIM2~TIM5,基本的功能就不描述了,主要是看这些通用定时器如何使用: TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_DeInit(TIM2); //重新将Timer设置为缺省值 TIM_InternalClockCo
[单片机]
STM32串口使用方法
串口接收函数
[单片机]
<font color='red'>STM32</font>串口使用方法
SD NAND在STM32应用上的保姆级教程
SD NAND与正点原子精英板的连接 由于正点原子精英板没有SD NAND接口,只有TF卡接口,所以SD NAND需要用到转接板来连接。 SD NAND正常运行现象 本次实验的程序是正点原子的SD卡实验例程,先用读卡器把SD NAND接到电脑上,并复制一个文件进去,再插到开发板上; 用送的数据线连接USB UART接口,下载好程序,打开电脑上的串口助手,按下KEY0,即可读取到数据, 具体实验步骤和现象可以看例程文件夹中的readme, 另外LED-DS0闪烁也表示SD NAND芯片在正常运行, SD NAND芯片用的是MK-米客方德的工业级芯片MKDV1GIL-AS;MK-米客方德家还有其他各种型号的SD NAN
[单片机]
SD NAND在<font color='red'>STM32</font>应用上的保姆级教程
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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