为了使工程更加有条理,我们把 LED 灯控制相关的代码独立分开存储,方便以后移植。
在“工程模板”之上新建“ bsp_led.c”及“ bsp_led.h”文件,其中的“ bsp”即 Board
Support Packet 的缩写(板级支持包),这些文件也可根据您的喜好命名,这些文件不属于
STM32 标准库的内容,是由我们自己根据应用需要编写的。
在学习过程中,经常看到有人问这样一个问题,为什么下面的时钟初始化可以用按位或(|)的方式。其实这里就是在于ST底层库的实现,需要我们灵活运用C语言。
void LED_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启LED相关的GPIO外设时钟*/ RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK| LED2_GPIO_CLK| LED3_GPIO_CLK, ENABLE); //这里可以用 | 的方式,因为底层库寄存器配置是个uint32_t的寄存器,可以多位同时操作 /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED1_PIN; /*设置引脚模式为输出模式*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /*设置引脚的输出类型为推挽输出*/ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*设置引脚为上拉模式*/ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /*设置引脚速率为2MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/ GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure); //有了上面的 | 配置思路之后,我们在想,下面这样复用的代码能否可以也通过 | 的方式呢? //答案是否定的,这里的寄存器配置是个GPIO_TypeDef*的类型,用 | 操作已然不合适。 /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED2_PIN; GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED3_PIN; GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure); /*关闭RGB灯*/ LED_RGBOFF; }
或许还有疑问就是为什么后面的LED2,3不用再配置模式那些,这其实还是属于c语言问题,在我们三个IO口都是相同模式选择的情况下,我们可以只改变结构体中控制引脚的部分,其他部分保留,但是如果有引脚的对应模式需要改变,那就不能这样了。
STM32 标准库补充知识
1. SystemInit 函数去哪了?
在前几章我们自己建工程的时候需要定义一个 SystemInit 空函数,但是在这
STM32 标准库的工程却没有这样做, SystemInit 函数去哪了呢?
这个函数在 STM32 标准库的“ system_stm32f4xx.c”文件中定义了,而我们
经包含该文件。标准库中的 SystemInit 函数把 STM32 芯片的系统时钟设置成了
即此时 AHB1 时钟频率为 180MHz, APB2 为 90MHz, APB1 为 45MHz。当 ST
电后,执行启动文件中的指令后,会调用该函数,设置系统时钟为以上状态 。
2.断言
断言一般用在调试程序的时候使用,ST虽然在库函数中有断言,但是默认是没有开启的,需要定义一个宏。
除了启用这个宏之外,我们还要在外部定义一个asset_failed函数,因为这个函数在这里只有声明。这些都在conf.h头文件中。FILE LINE这种,是预处理宏,不需要头文件支持,是c编译器具备的。
3.防止重复包含