以下以STM32F407ZGT6为例。
一.GPIO的作用
1.当作输入输出口 输出数字信号 0/1
TTL电平 0 0~1.5V 1 2.5~5V
STM32中 - 0±0.1V 1 3.3±0.3V
2.直接驱动外部电路 如LED,蜂鸣器等等
3.使用I/O口模拟通信协议 IIC
4.模拟PWM波 通过循环改变占空比来实现
二.STM32F407ZGT6芯片中GPIO口的数量及命名
1.114个I/O口,每个I/O口上有不同的通用功能,复用功能等
2.命名 Port + 端口号 + 管脚号
端口号 : A B C D E F G H 在A~G上每个端口有16个管脚(0~15),H只有2个管脚(1,2)
例 PA5 A端口的第5个管脚
三.如何操作GPIO口
通过AHB1时钟总线与GPIO口通信 操作提供的接口----寄存器
四.STM32F407ZTG6中GPIO的寄存器
1.寄存器:一块存储空间(8/16/32位),具有RAM具有的特性(掉电数据丢失,读写速度快),每个位 都有自己独特的作用。
2.如何操作寄存器
通过指针操作 例如我们想操作一个地址为0x4000的寄存器只需要通过*(unsigned int *)0x4000进行我们需要的操作(赋值,加减,位操作)
3.寄存器的特性
有读/写,只读,只写,读取/清零,读取/置位,切换,保留(reserved)等
数据(DR)寄存器:保存接受/发送的数据,一般用=接受
配置(控制CR)寄存器:配置相关的工作模式,一般用&=~进行清零或|=置一 ^= 进行反转
状态(SR)寄存器:外设所处的状态,一般用 &1 操作来进行读取
4.GPIO的工作模式
上拉:1.拉高电平2.增强电路的驱动能力
下拉:1.拉低电平2.增强电路的驱动能力
输入:4种
浮空输入:输入的是数字量,不具有上下拉驱动能力的输入 – 按键识别
上拉输入:输入的是数字量,具有上拉驱动能力的输入
下拉输入:输入的是数字量,具有下拉驱动能力的输入
模拟输入:输入的是模拟量 – 模数转换 ADC
输出:4种
通用:IO功能
复用:除了IO以外的功能,比如串口,定时器等
开漏输出:只能输出0(想要输出1,需要接上拉电阻)--总线通信
推挽输出:既能输出0,又能输出1.
5.通过配置步骤(以LED为例)
1.查看原理图,找到led对应的IO口
以pf6为例,当向该引脚输出0时led亮。
2.查看该IO口的通用功能是否用作作IO口
在这里PF6的通用功能为io口的功能
3.打开该GPIO口对应的时钟
4.配置工作模式
在该图中A,B,C,D,E,F,G,H,I的时钟总线都是AHB1,所以在我们操作该GPIO口时要将该时钟打开,只需通过位操作将相应位置一即可,具体操作位
RCC->AHB1ENR |= (1<<0);这里左移0位即为将GPIOA置为1。
接下来配置GPIOF的工作模式,以第6位为例
因为时通用功能,所以复用暂时不看以后会提到
led的工作模式位通用推挽输出,无上下拉,快速模式(可自己选择)
若要将pf6配置为通用,要在第12,13位中写入01操作如下:
//pf6 通用推挽输出
GPIOF->MODER &=~ (3<<12); //清零
GPIOF->MODER |= (1<<12); //通用输出模式
GPIOF->OTYPER &=~ (1<<6); //输出推挽
GPIOF->OSPEEDR &=~ (3<<12); //速度清零
GPIOF->OSPEEDR |= (2<<12); //快速
GPIOF->ODR |= (1<<6); //led灭
这里因为GPIOF->ODR的复位值为0x0000 0000,而根据 原理图当该引脚输出0时led亮,所以在初始化中需要将该位置1,需要让led灭的时候把相应位置为0即可。
led是输出的体现,那么独立按键就是输入的体现了,下面让我们看一下怎么配置key的工作方式。
还是按上面的步骤:
1.查看原理图,确定引脚,以及工作方式
以key1为例,可以看出当按键没用按下的时候,该IO口检测到的(就是向IO口输入的)为低电平,按键按下时,就会检测到高电平。我们可以搜索他的标号(KEY1)来确定他的端口号,所以我么只要配置PA0,为输入模式就可以使用KEY1这个独立按键了
2.看该IO口是否有IO口的功能
通用功能是IO口的功能
3.打开对应的时钟
4.配置相应的工作模式
RCC->AHB1ENR &=~ (1<<0);
RCC->AHB1ENR |= (1<<0);
//pa0 浮空输入
GPIOA->MODER &=~ 3;
GPIOA->PUPDR &=~ 3;
这样就配置完成了,我们只要检测GPIOA->IDR这个输入数据寄存器就可以确定按键是否按下了。
完整代码如下:
1 #include "led.h" 2 #include "delay.h" 3 4 5 6 /* 7 函数名称:led_config() 8 函数功能:初始化led 9 函数参数:无 10 11 */ 12 void led_config() 13 { 14 //pf6 15 //开时钟 16 RCC->AHB1ENR |= ((1<<5)|(1<<2)); 17 //pf6 通用推挽输出 18 GPIOF->MODER &=~ ((3<<12)|(3<<18)|(3<<20)); //清零 19 GPIOF->MODER |= ((1<<12)|(1<<18)|(1<<20)); //通用输出模式 20 GPIOF->OTYPER &=~ ((1<<6)|(1<<9)|(1<<10)); //输出推挽 21 GPIOF->OSPEEDR &=~ ((3<<12)|(3<<18)|(3<<20)); //速度清零 22 GPIOF->OSPEEDR |= ((2<<12)|(2<<18)|(2<<20)); //快速 23 GPIOF->ODR |= ((1<<6)|(1<<9)|(1<<10)); //led灭 24 25 GPIOC->MODER &=~ (3<<0); 26 GPIOC->MODER |= (1<<0); 27 GPIOC->OTYPER &=~ (1<<0); 28 GPIOC->OSPEEDR &=~ (3<<0); 29 GPIOC->OSPEEDR |= (2<<0); 30 GPIOC->ODR |= (1<<0); 31 32 } 33 34 35 void led1_Flash() 36 { 37 38 LED1(1); 39 delay_nms(500); 40 LED1(0); 41 delay_nms(500); 42 } 43 44 //流水灯 45 void led_pipeline() 46 { 47 LED1(1); 48 delay_nms(500); 49 LED1(0); 50 LED2(1); 51 delay_nms(500); 52 LED2(0); 53 LED3(1); 54 delay_nms(500); 55 LED3(0); 56 LED4(1); 57 delay_nms(500); 58 LED4(0); 59 } 60 61 //呼吸灯 62 void breath_led() 63 { 64 uint32_t i; 65 for(i=0;i<1000;i++) 66 { 67 LED2(1); 68 delay_nus(i); 69 LED2(0); 70 delay_nus(1000-i); 71 } 72 for(i=0;i<1000;i++) 73 { 74 LED2(0); 75 delay_nus(1000-i); 76 LED2(1); 77 delay_nus(i); 78 } 79 80 }
#include "key.h" #include "delay.h" /* 函数功能:初始化key 函数名称:key_config() 函数参数:无 */ void key_config() { //开时钟 RCC->AHB1ENR &=~ (1|(1<<4)); RCC->AHB1ENR |= (1|(1<<4)); //pa0 浮空输入 GPIOA->MODER &=~ 3; GPIOA->PUPDR &=~ 3; GPIOE->MODER &=~ ((3<<4)|(3<<6)|(3<<8)); GPIOE->PUPDR &=~ ((3<<4)|(3<<6)|(3<<8)); } /* 函数功能:获取按键的值 函数名称:getKeyValue() 函数参数:无 */ uint8_t getKeyValue() { uint8_t value; if(key1) { delay_nms(10); if(key1) { value = 1; } } else if(!key2) { delay_nms(10); if(!key2) { value = 2; } } else if(!key3) { delay_nms(10); if(!key3) { value = 3; } } else if(!key4) { delay_nms(10); if(!key4) { value = 4; } } return value; }