1、IO介绍
stm32f4的io由8个寄存器控制:MODER、、OTYPER、
OSPEEDR、PUPDR、ODR、IDR 、AFRH 和 AFRL。
我们主要使用io口的推挽输出功能,利用GPIO_Set 函数来设置,即可很简单的完成对 IO 口的配置。
io电平兼容问题:大部分io都是兼容5v,凡是有FT/FTf标志(在芯片的数据手册里)的,都是兼容5v的(如果是设置模拟输入模式,一定不能接5v!!!)。没有FT/FTf标志的io,不要接5v,不然可能会烧坏mcu。
2、硬件
单片机的PF9、PF10连接两个LED的阴极。
3、软件
打开keil,在hardware文件夹下面,保存一下代码为led.c。
新建led.c文件
#include "led.h"
//初始化 PF9 和 PF10 为输出口.并使能这两个口的时钟
//LED IO 初始化
void LED_Init(void)
{
RCC->AHB1ENR|=1<<5;//使能 PORTF 时钟
GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,
GPIO_SPEED_100M,GPIO_PUPD_PU); //PF9,PF10 设置
LED0=1;//LED0 关闭
LED1=1;//LED1 关闭
}
代码详解:
这个代码主要是设置PF9和PF10为推挽输出。IO 配置是采用 GPIO_Set 函数实现。
(1) NOTE:在配置stm外设的时候,任何时候都应该先使能外设的时钟!!!
AHB1ENR 是 AHB1 总线上的外设时钟使能寄存器,它的各位描述如图:
在这个例子上:我们要使能PORTF的时钟使能位,只要在这个寄存器的bit5置1就能使能PORTF的时钟了。
(2) 设置完时钟之后就是配置时钟了,LED_Init 调用 GPIO_Set 函数完成对 PF9 和 PF10的模式配置。
(3) 控制两个LED的亮灭。
(4) led的初始化完成。
新建led.h文件:
代码如下:
代码方式1:
#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 (1<<9) //led0 PF9
#define LED1 (1<<10) //led1 PF10
#define LED0_SET(x) GPIOF->ODR=(GPIOF->ODR&~LED0)|(x ? LED0:0)
#define LED1_SET(x) GPIOF->ODR=(GPIOF->ODR&~LED1)|(x ? LED1:0)
方式1通过LED0=0 和 LED0=1控制PF9和PF10的输出。
方式2通过LED0_SET(0)和LED0_SET(1)来控制PF9和PF10的输出0和1。
由此可以看出方式1的位带操作更方便,以后会使用方式1。
note:新建的.h文件路径要添加到工程中
main函数
代码如下:
#include "sys.h"
#include "delay.h"
#include "led.h"
int main(void)
{
Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
delay_init(168); //初始化延时函数
LED_Init(); //初始化 LED 时钟
while(1)
{
LED0=0; //DS0 亮
LED1=1; //DS1 灭
delay_ms(500);
LED0=1; //DS0 灭
LED1=0; //DS1 亮
delay_ms(500);
}
}
编译
编译信息可以看出:代码占用FLASH大小为:1828字节(1404+424),所用SRAM大小为:1336字节(12+1324)。
code:表示程序所占用FLASH大小(FLASH)。
RO-data:即read only data,表示程序定义的常量,如const类型(FLASH)。
RW-data:即read write data,表示已被初始化的全局变量。(SRAM)
ZI-data:即Zero init data,表示未被初始化的全局变量。(SRAM)