led.c 文件中输入如下代码
#include "led.h"
//初始化PF9和PF10为输出口.并使能这两个口的时钟
//LED IO 初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF时钟
//GPIOF9,F10 初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1对应IO 口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10设置高,灯灭
}
该代码里面就包含了一个函数 void LED_Init(void),该函数的功能就是用来实现配置 PF9和PF10 为推挽输出。这里需要注意的是:在配置STM32 外设的时候,任何时候都要先使能该外设的时钟!GPIO 是挂载在AHB1 总线上的外设,在固件库中对挂载在 AHB1 总线上的外设时钟使能是通过函数RCC_AHB1PeriphClockCmd ()来实现的。
对于这个入口参数设置,看看我们的代码:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF时钟
这行代码的作用是使能AHB1总线上的GPIOF时钟。
在设置完时钟之后,LED_Init 调用 GPIO_Init 函数完成对 PF9 和 PF10 的初始化配置,然后调用函数GPIO_SetBits控制 LED0和 LED1输出 1(LED 灭) 。至此,两个LED的初始化完毕。这样就完成了对这两个 IO 口的初始化。这段代码的具体含义,大家可以看前面一小节,我们有详细的讲解。初始化函数代码如下:
//GPIOF9,F10 初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1对应IO 口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10设置高,灯灭
保存 led.c代码,然后我们按同样的方法,新建一个 led.h 文件,也保存在LED文件夹下面。
在 led.h中输入如下代码:
#ifndef __LED_H
#define __LED_H
#include "sys.h"
//LED 端口定义
#define LED0 PFout(9) // DS0
#define LED1 PFout(10)// DS1
void LED_Init(void);//初始化
#endif
这段代码里面最关键就是2个宏定义:
#define LED0 PFout(9) // DS0 PF9
#define LED1 PFout(10)// DS1 PF10
这里使用的是位带操作来实现操作某个 IO 口的 1 个位的,需要说明的是,这里同样可以使用固件库操作来实现 IO 口操作。
如下:
GPIO_SetBits(GPIOF, GPIO_Pin_9); //设置GPIOF.9 输出 1,等同 LED0=1;
GPIO_ResetBits (GPIOF, GPIO_Pin_9); //设置 GPIOF.9输出 0,等同 LED0=0;
有兴趣的朋友不妨修改我们的位带操作为库函数直接操作,这样也有利于学习。
回到主界面后,在main函数里面编写如下代码:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
int main(void)
{
delay_init(168); //初始化延时函数
LED_Init(); //初始化 LED 端口
while(1)
{
GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.9 拉低,亮 等同 LED0=0;
GPIO_SetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉高,灭 等同LED1=1;
delay_ms(500); //延时 500ms
GPIO_SetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.0拉高,灭 等同LED0=1;
GPIO_ResetBits(GPIOF,GPIO_Pin_10); //LED1对应引脚GPIOF.10拉低,亮 等同LED1=0;
delay_ms(500); //延时 500ms
}
}
代码包含了#include "led.h"这句,使得 LED0、LED1、LED_Init 等能在 main()函数里被调用。这里我们需要重申的是,在固件库中,系统在启动的时候会调用 system_stm32f4xx.c 中的函数SystemInit()对系统时钟进行初始化,在时钟初始化完毕之后会调用main()函数。 所以我们不需要再在 main()函数中调用SystemInit()函数。当然如果有需要重新设置时钟系统,可以写自己的时钟设置代码,SystemInit()只是将时钟系统初始化为默认状态。
main()函数非常简单,先调用delay_init()初始化延时,接着就是调用 LED_Init()来初始化GPIOF.9和GPIOF.10为输出。最后在死循环里面实现LED0和LED1交替闪烁,间隔为500ms。
上面是通过库函数来实现的 IO 操作,我们也可以修改main()函数,直接通过位带操作达到
同样的效果,大家不妨试试。位带操作的代码如下:
int main(void)
{
delay_init(168); //初始化延时函数
LED_Init(); //初始化 LED 端口
while(1)
{
LED0=0; //LED0亮
LED1=1; //LED1灭
delay_ms(500);
LED0=1; //LED0灭
LED1=0; //LED1亮
delay_ms(500);
}
}
当然我们也可以通过直接操作相关寄存器的方法来设置IO,我们只需要将主函数修改为如
下内容:
int main(void)
{
delay_init(168); //初始化延时函数
LED_Init(); //初始化 LED 端口
while(1)
{
GPIOF->BSRRH=GPIO_Pin_9;//LED0亮
GPIOF->BSRRL=GPIO_Pin_10;//LED1灭
delay_ms(500);
GPIOF->BSRRL=GPIO_Pin_9;//LED0灭
GPIOF->BSRRH=GPIO_Pin_10;//LED1亮
delay_ms(500);
}
}
将主函数替换为上面代码,然后重新执行,可以看到,结果跟库函数操作和位带操作一样的效果。大家可以对比一下。这个代码在我们跑马灯实验的main.c文件中有注释掉,大家可以替换试试。
上一篇:STM32f4---蜂鸣器实验代码
下一篇:STM32F4时钟使能和配置
推荐阅读最新更新时间:2024-03-16 16:14