第5章 GPIO-LED灯
5.1 GPIO简介
GPIO(General purpose input output)即通用输入输出口。STM32的输入输出口主要具有2个功能,即通用功能和复用的功能。STM32芯片的GPIO被分成A、B、C、D、E等组,每组有16个引脚(Px0 ~ Px15,x分别表示A、B、C、D、E)。通过操作STM32的配置寄存器GPIOx_CRL,GPIOx_CRH)、数据寄存器(GPIOx_IDR, GPIOx_ODR)、复位置位寄存器(GPIOx_BSRR)、复位寄存器(GPIOx_BRR)和锁定寄存器(GPIOx_LCKR)可以实现如下功能:
输入模式 浮空输入、上拉输入、下拉输入、模拟输入
输出模式 开漏输出、推挽输出
复用模式 推挽复用、开漏复用
5.2 GPIO工作原理
下图是STM32 GPIO管脚的硬件电路图,从图中可以看到各部分硬件的连接方式。虚线框上图是输入驱动部分电路图,虚线框下图是输出驱动部分电路图。通过配置CNF1、CNFO、MODE1、MODEO就可以实现输入模式、输出模式和复用模式。其中,CNF1、CNFO、MODE1、MODEO
5.3 硬件电路设计
新天STM32开发板的LED电路如下图所示,D4、D5、D6分别与STM32的PB5、PB0、PB1连接,通过配置STM32内部相关的寄存器,让PB5、PB0、PB1输出“低电平”,就可以点亮LED灯了。
5.4 软件编程设计
注意:该部分针对核心部分的代码进行讲解,完整的代码请参考本章配套的工程。
在工程应用方面,为了缩短产品的开发周期,相关的单片机程序一般都会使用以前开发过的相关程序或者参考别人的程序,因此需要进行相关的程序移植工作。作为一个有经验的单片机开发工程师,一般会使用宏定义相关外设,方便移植。同时根据C语言的特点采用“结构化、模块化”的编程思想,将每一个硬件的驱动程序以及应用程序分开,每一个硬件都对应一个.c文件和.h文件。
1 LED引脚的宏定义
LED引脚的宏定义见代码清单5-1。
代码清单 5-1 LED控制引脚相关的宏
/* 定义LED连接的GPIO端口, 用户只需要修改下面的代码即可改变控制的LED引脚 */
#define LED1_GPIO_PORT GPIOB /* GPIO端口 */
#define LED1_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define LED1_GPIO_PIN GPIO_Pin_5 /* LED引脚号 */
#define LED2_GPIO_PORT GPIOB /* GPIO端口 */
#define LED2_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define LED2_GPIO_PIN GPIO_Pin_0 /* LED引脚号 */
#define LED3_GPIO_PORT GPIOB /* GPIO端口 */
#define LED3_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define LED3_GPIO_PIN GPIO_Pin_1 /* LED引脚号 */
以上代码将STM32与LED连接引脚的GPIO端口、GPIO时钟、GPIO引脚号分别用宏封装起来,在实际的工程应用中编写程序的时候,直接使用宏,方便代码移植。
2控制LED灯亮灭状态的宏定义
通过对ODR、BSRR、BRR寄存器进行封装,直接操作寄存器,控制LED反转、灭以及亮。控制LED灯亮灭状态的宏定义见代码清单5-2。
代码清单 5-2 控制LED灯亮灭状态的宏定义
/* 定义控制IO的宏 */
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define LED3_TOGGLE digitalToggle(LED2_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_OFF digitalHi(LED2_GPIO_PORT,LED3_GPIO_PIN)
#define LED3_ON digitalLo(LED2_GPIO_PORT,LED3_GPIO_PIN)
3 LED GPIO初始化函数
使用STM32的GPIO时,需要使能GPIO的时钟,然后初始化GPIO_InitTypeDef结构体就完成对GPIO的初始化,见代码清单5-3。
代码清单 5-3 LED GPIO初始化函数
/**
* @brief 初始化控制LED的GPIO
* @param 无
* @retval 无
*/
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启GPIOB的外设时钟*/
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK, ENABLE);
/*选择要控制的GPIOB引脚*/
GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOB0*/
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
/* 关闭所有led灯 */
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
4 main函数
在main函数中,首先调用LED_GPIO_Config()函数对LED进行初始化,然后进入while(1),对LED进行控制。
注意:USART1_Config()函数、USART1_NVIC_Config()函数用于程序调试,初始化串口USART1,输出调试信息,下面章节介绍USART串口时,再详细解说。
代码清单 5-4 main()函数
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
USART1_Config();
USART1_NVIC_Config();
printf("\r\n ND STM32 Board TEST - LED \r\n");
//LED初始化
LED_GPIO_Config();
while (1)
{
LED1_ON; // 点亮LED1
Delay(0x0FFFFF);
LED1_OFF; // 灭LED1
LED2_ON; // 亮
Delay(0x0FFFFF);
LED2_OFF; // 灭
LED3_ON; // 亮
Delay(0x0FFFFF);
LED3_OFF; // 灭
}
}
|