完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
使用固件库函数点亮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也带上,那个是声明的时候用的,调用函数就直接用函数。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1777 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1080 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1678 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
595浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
554浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 03:06 , Processed in 1.382646 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号