使用STM32固件库函数操作控制LED灯

    直接使用寄存器地址来进行STM32开发要对每一个寄存器的地址通过查找芯片手册,对每一个寄存器的各个位的含义也要查清楚,然后决定对那个地址的哪些位进行怎样的设置。这种编程效率低,程序的可移植性差,程序的可读性差。

    STM32提供了对外设寄存器操作的功能函数,对寄存器操作只需要调用相应的库函数就可以,一般函数名单词组合与功能密切相关,增强了程序的可读性。

1、以CMSIS固件库项目为基础,在项目文件夹下新增"Lib"文件夹,在"Lib"文件夹下新增"inc"和"src"文件夹,在"inc"文件夹中复制"stm32f10x_gpio.h"和"stm32f10x_rcc.h"两个头文件,在"src"文件夹中复制"stm32f10x_gpio.c"和"stm32f10x_rcc.c"两个库函数程序文件,分别包含RCC和GPIO操作相关的库函数。

2、在“项目条目管理”对话框中添加"Lib"组,并向组中添加两个库函数程序文件。

3、修改"Include Paths",添加".\Lib\inc"路径

4、重写main.c中的main函数

① 包含需要的头文件:"stm32f10x_gpio.h"和"stm32f10x_rcc.h"

② 使能GPIOC时钟

    在RCC库函数中定义了RCC_APB2PeriphClockCmd函数,函数原型为:

void RCC_APB2PeriphClockCmd ( uint32_t  RCC_APB2Periph, FunctionalState  NewState )

其中参数RCC_APB2Periph取值为在"stm32f10x_rcc.h"中预定义的值,这里对GPIOC的操作为RCC_APB2Periph_GPIOC,定义如下:

这个值与前面程序中的表达式"0x1<<4"得到的值是一致的。

    函数的第二个参数NewState取值为FunctionState类型,FunctionState类型是在"stm32f10x_rcc.c"文件中定义的一个枚举类型,有DISABLE和ENABLE两个取值,定义如下:

    现在要使能GPIOC,则调用函数如下:

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );

③ 配置GPIOC_0为推挽式输出,50MHz速度。

    对GPIO引脚的配置调用"stm32f10x_gpio.c"中的库函数GPIO_Init实现,函数原型为:

void GPIO_Init ( GPIO_TypeDef *  GPIOx, GPIO_InitTypeDef * GPIO_InitStruct  )

其中第一个参数GPIOx的取值在"stm32f10x.h"中定义,这里用GPIOC;第二个参数GPIO_InitStruct为GPIO_InitTypeDef指针类型,GPIO_InitTypeDef类型在"stm32f10x_gpio.h"文件中定义:

这个结构体中的GPIO_Pin为IO口的引脚编号,这里为第一个LED灯,则取0;

GPIO_Speed为GPIOSpeed_TypeDef类型,GPIOSpeed_TypeDef类型在"stm32f10x_gpio.h"文件中定义:

为枚举类型,有三个枚举值。这里取GPIO_Speed_50MHz;

GPIO_Mode为GPIOMode_TypeDef类型,GPIOMode_TypeDef类型在"stm32f10x_gpio.h"文件中定义:

    这些枚举值分别为:

(1)GPIO_Mode_AIN 模拟输入

(2)GPIO_Mode_IN_FLOATING 浮空输入

(3)GPIO_Mode_IPD 下拉输入

(4)GPIO_Mode_IPU 上拉输入

(5)GPIO_Mode_Out_OD 开漏输出

(6)GPIO_Mode_Out_PP 推挽输出

(7)GPIO_Mode_AF_OD 复用开漏输出

(8)GPIO_Mode_AF_PP 复用推挽输出

    这里选择GPIO_Mode_Out_PP。

要配置GPIOC_0的工作模式,首先用GPIO_InitTypeDef类型定义一个变量,然后给这个结构体变量的成员赋值,最后调用GPIO_Init函数完成配置:

GPIO_InitTypeDef GPIOC_0_mode;

GPIOC_0_mode.GPIO_Pin = GPIO_Pin_0;

GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;

GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOC, &GPIOC_0_mode);

④ 通过GPIO_ResetBits和GPIO_SetBits函数来控制LED1的复位和置位,函数原型如下:

void GPIO_ResetBits ( GPIO_TypeDef *GPIOx,  uint16_t  GPIO_Pin )       //复位函数

void GPIO_SetBits  ( GPIO_TypeDef * GPIOx,  uint16_t GPIO_Pin ) //置位函数

函数的参数分别为哪个GPIO口和哪个引脚。

如果对GPIOC_0复位,则:GPIO_ResetBits( GPIOC, GPIO_Pin_0) ;

如果对GPIOC_0置位,则:GPIO_SetBits( GPIOC, GPIO_Pin_0) ;

最后的main.c程序如下:

#include "stm32f10x.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_gpio.h"

void delay(int t)

{

     int i;

     for( ;t>0; t--)

         for(i=0;i<1000;i++);

}

int main()

{

     GPIO_InitTypeDef GPIOC_0_mode;

     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); //使能GPIOC时钟

     GPIOC_0_mode.GPIO_Pin = GPIO_Pin_0;

     GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;

     GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;

     GPIO_Init(GPIOC, &GPIOC_0_mode);   //配置GPIOC_0引脚为推挽输出,50MHz速度

     while(1)

     {

         GPIO_ResetBits( GPIOC, GPIO_Pin_0);  //将GPIOC_0复位

         delay(1000);

         GPIO_SetBits( GPIOC, GPIO_Pin_0);    //将GPIOC_0置位

         delay(1000);

     }

}

5、连接错误及其解决方法。

在上述项目中,最后完成项目配置和编程后,编译连接时出现如下错误:

出现这个错误是由于STM32外设库函数的开发中用到了断言机制。正常使用库函数时,需要包含"stm32f10x_conf.h"头文件,在该文件中有如下定义

/* Exported macro ------------------------------------------------------------*/

#ifdef  USE_FULL_ASSERT

/**

  * @brief  The assert_param macro is used for function's parameters check.

  * @param  expr: If expr is false, it calls assert_failed function which reports

  *         the name of the source file and the source line number of the call

  *         that failed. If expr is true, it returns no value.

  * @retval None

  */

  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

/* Exported functions ------------------------------------------------------- */

  void assert_failed(uint8_t* file, uint32_t line);

#else

  #define assert_param(expr) ((void)0)

#endif /* USE_FULL_ASSERT */

在该头文件中定义了assert_param宏,根据项目配置,如果设置了"USE_FULL_ASSERT"参数,则对函数参数进行检查,检查不成功转到"assert_failed"函数处理;如果没有设置使用断言,则相当于不对参数进行检测。

解决方法:将这一段宏定义直接复制到"stm32f10x.h"文件中,因为所有的外设库函数文件都直接或间接地包含了该头文件。

6、编译连接项目,下载程序,开发板的LED1闪烁。

猜你喜欢

转载自blog.csdn.net/fanxp66/article/details/80215090