STM32
直播中

李星童

7年用户 1061经验值
私信 关注
[问答]

如何使用固件库函数去点亮LED呢

新建固件库工程里面都有哪些文件呢?
如何使用固件库函数去点亮LED呢?

回帖(1)

谢微微

2021-11-30 12:00:45
使用固件库函数点亮LED

新建固件库工程里面都有哪些文件:
1-汇编编写的启动文件
startup_stm32f10x_hd.s:设置堆栈指针、设置PC指针、初始化中断向量表、配置系统时钟、对用C库函数_main最终去到C的世界
2-时钟配置文件
system_stm32f10x.c:把外部时钟HSE=8M,经过PLL倍频为72M。
3-外设相关的
stm32f10x.h:实现了内核之外的外设的寄存器映射
xxx:GPIO、USRAT、I2C、SPI、FSMC
stm32f10x_xx.c:外设的驱动函数库文件
stm32f10x_xx.h:存放外设的初始化结构体,外设初始化结构体成员的参数列表,外设固件库函数的声明
4-内核相关的
CMSIS - Cortex 微控制器软件接口标准
core_cm3.h:实现了内核里面外设的寄存器映射
core_cm3.c:内核外设的驱动固件库
NVIC(嵌套向量中断控制器)、SysTick(系统滴答定时器)
misc.h
misc.c
5-头文件的配置文件
stm32f10x_conf.h:头文件的头文件
//stm32f10x_usart.h
//stm32f10x_i2c.h
//stm32f10x_spi.h
//stm32f10x_adc.h
//stm32f10x_fsmc.h

新建固件库工程模板:网上有视频教程,跟着做就可以了
如何使用固件库点亮LED呢?
1、找一个固件库工程模板,在USER文件夹中,新建本工程的.c和.h文件
2、.c文件用来存放函数代码,.h文件用来存放宏定义,函数声明
3、在魔术棒中指定头文件的路径,这样的话我们而定编译器才会找到这个头文件
4、我们在自己写头文件的时候,为了避免头文件在被调用的时候出现重复定义的错误,我们给每一个头文件都加上条件编译

#ifndef _BSP_LED_H
#define _BSP_LED_H


#endif /*_BSP_LED_H*/


5、GPIO的映射在stm32f10x.h这个头文件中,我们将其包含进来。后续我们会在bsp_led.c文件中编写一些驱动LED的函数,函数的声明都放到这个头文件中。


#ifndef _BSP_LED_H
#define _BSP_LED_H


#include “stm32f10x.h”


#endif /*_BSP_LED_H*/


6、我们的主函数会调用LED的驱动函数,我们将bsp_led.h包含到mian.c文件中。


#include "stm32f10x.h"
#include "bsp_led.h"


int main(void)
{
        //
}


在这里我们可以看到,因为主函数中已经声明了stm32f10x.h这个头文件,然后在进行到第二步,bsp_led.h的时候,又有一个stm32f10x.h的文件在这里,如果不在头文件中进行条件编译的操作,那么就会产生重复编译的问题。
7、回到bsp_led.c文件,先对GPIO进行初始化,先新建一个函数LED_GPIO_Config().


#include "bsp_led.h"


void LED_GPIO_Config()
{
       
}


8、我们要操作GPIO就要先找到GPIO的固件库函数,stm32f10x_gpio.c,他的所有函数的成名以及初始化结构体都在他的头文件里面。要想初始化一个外设,他的头文件里都会有一个XXX_InitTypeDef的结构体函数,我们只要往结构体里面的成员写相对应的值就可以初始化了,而且所有结构体成员的值,都已经在这个头文件里面定义好了。那么我们先新建一个初始化结构体:


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;
}


9、然后我们往这个结构体内部的成员添加我们要控制的参数:引脚,模式,速度,模式选择推挽输出即可,速度跟功率成正比


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;


        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
}


10、为了提高程序的可移植性,我们将硬件相关的我们都定义成宏,在bsp_led.h中


#ifndef _BSP_LED_H
#define _BSP_LED_H
#include “stm32f10x.h”


#define LED_G_GPIO_Pin                                 GPIO_Pin_0
#define LED_G_GPIO_PART                                GPIOB


#endif /*_BSP_LED_H*/


11、然后我们的代码就成了这样,后续修改只要在宏定义里面修改一下引脚,就可以点亮任意LED


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;


        GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_Pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
}


12、然后我们需要一个初始化函数,来对外设进行初始化操作,


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;


        GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_Pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;


        GPIO_Init(LED_G_GPIO_PART, &GPIO_InitStruct);//第二个变量是一个指针,我们对变量取地址就变成指针了
}


13、接下来我们还要对时钟进行设置,开时钟,对于这个部分要注意在更改控制IO的时候,特别是在控制串口的时候,要注意对应的时钟,不然光改串口不改时钟就无法运行。时钟是由RCC这个外设控制的,RCC开时钟是通过总线来控制,使用的时候要找准外设挂载的总线是哪一个。我们找到RCC的固件库,然后找到他的头文件,在头文件里找到相应的函数,这里需要的是RCC_APB2PeriphClockCmd(),Cmd就是使能的意思,看一下这个函数的原型,看看他的输入都是什么数据。上面有输入数据的所有形参的类型和格式。最终我们可以看到这个函数操作的是RCC_APB2ENR这个寄存器。大家在编程的时候最好养成这个习惯,虽然调用的是固件库的函数,但是我们也要了解一下,他这个函数到底操作的是什么寄存器。


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;
        void RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)


        GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_Pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;


        GPIO_Init(LED_G_GPIO_PART, &GPIO_InitStruct);//第二个变量是一个指针,我们对变量取地址就变成指针了
}


14、还是老规矩,RCC_APB2periph_GPIOB我们将其定义成一个宏,方便后续的代码移植,然后代码就变成下面的样子:


#ifndef _BSP_LED_H
#define _BSP_LED_H
#include “stm32f10x.h”


#define LED_G_GPIO_Pin                                 GPIO_Pin_0
#define LED_G_GPIO_PART                                GPIOB
#define LED_G_GPIO_CLK                                RCC_APB2Periph_GPIOB


void LED_GPIO_Config(void);


#endif /*_BSP_LED_H*/


#include "bsp_led.h"


void LED_GPIO_Config()
{
        GPIO_InitTypeDef GPIO_InitStruct;
        RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK, ENABLE)


        GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_Pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;


        GPIO_Init(LED_G_GPIO_PART, &GPIO_InitStruct);//第二个变量是一个指针,我们对变量取地址就变成指针了
}


15、接下来我们就可以将LED初始化的函数写进mian.c然后看一下有什么效果,我们会发现由于板载的LED灯是低电平点亮,而我们的ODR数据输出寄存器它的默认值为0,就正好让我们的LED灯点亮了。固件库中也有专门的函数,来对位进行高低位的操作,我么将其找到,写入函数中。


/*main函数*/
#include "stm32f10x.h"
#include "bsp_led.h"
/*软件延时函数*/
void Delay(uint32_t count)
{
        for(;count!=0;count--);
}


int main()
{
        LED_GPIO_Config();


        while(1)
        {
                GPIO_SetBits(LED_G_GPIO_PART,LED_G_PIN);
                Delay(0xFFFFF);
                GPIO_ResetBits(LED_G_GPIO_PART,LED_G_PIN);
                Delay(0xFFFFF);
        }


}


16、最后呢,为大家再展示一下更加简洁的版本:


#ifndef _BSP_LED_H
#define _BSP_LED_H
#include “stm32f10x.h”


#define LED_G_GPIO_Pin                                 GPIO_Pin_0
#define LED_G_GPIO_PART                                GPIOB
#define LED_G_GPIO_CLK                                RCC_APB2periph_GPIOB


#define ON                                1
#define OFF                                0
#define LED_G(a)                if(a)
                                                         GPIO_ResetBits(LED_G_GPIO_PART,LED_G_PIN);
                                                else GPIO_SetBits(LED_G_GPIO_PART,LED_G_PIN);


void LED_GPIO_Config(void);


#endif /*_BSP_LED_H*/


/*main函数*/
#include "stm32f10x.h"
#include "bsp_led.h"
/*软件延时函数*/
void Delay(uint32_t count)
{
        for(;count!=0;count--);
}


int main()
{
        LED_GPIO_Config();


        while(1)
        {
                //GPIO_SetBits(LED_G_GPIO_PART,LED_G_PIN);
                Delay(0xFFFFF);
                LED_G(ON);
                //GPIO_ResetBits(LED_G_GPIO_PART,LED_G_PIN);
                LED_G(OFF);
                Delay(0xFFFFF);
        }


}


注意事项:

1、Delay函数中赋值是16进制的0xFFFF,不要写成FFFF
2、声明函数时,如果void LED_GPIO_Config(void);中括号里的那个void没有加进去会Warning
3、调用函数时,不要直接拷贝过来把前面那个声明void也带上,那个是声明的时候用的,调用函数就直接用函数。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分