stm32专题一:GPIO输出—点亮LED

新建led文件夹和bsp_led.c和bsp_led.h的板级支持包。

在bsp_led.c中,函数LED_GPIO_Config(void)提供了gpio的初始化过程:

  1. 定义GPIO初始化结构体;
  2. 开启RCC时钟,这一步非常重要,要找到对应的总线和外设时钟;
  3. 给初始化结构体成员赋值,由于和硬件相关,都在bsp_led.h中定义成宏,提高可移植性。

bsp_led.c

// bsp: board support package 板级支持包

#include "bsp_led.h"

void LED_GPIO_Config(void)
{
    // 定义GPIO初始化结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	
	// 开启RCC时钟,非常关键
	RCC_APB2PeriphClockCmd(LED_R_GPIO_CLK | LED_G_GPIO_CLK | LED_B_GPIO_CLK, ENABLE);

    // 配置初始化结构体,传入具体参数
	GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	
	// 初始化3个LED灯的GPIO
	GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = LED_R_GPIO_PIN;
	GPIO_Init(LED_R_GPIO_PORT, &GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = LED_B_GPIO_PIN;
	GPIO_Init(LED_B_GPIO_PORT, &GPIO_InitStruct);
	
	// 初始状态关闭所有LED灯
	GPIO_SetBits(LED_R_GPIO_PORT, LED_R_GPIO_PIN);
	GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
	GPIO_SetBits(LED_B_GPIO_PORT, LED_B_GPIO_PIN);
}


在bsp_led.h中,大量使用了宏定义,来封装硬件相关的函数

bsp_led.h

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "stm32f10x.h"

// 硬件封装宏
#define LED_R_GPIO_PIN		GPIO_Pin_5
#define LED_R_GPIO_PORT		GPIOB
#define LED_R_GPIO_CLK		RCC_APB2Periph_GPIOB

#define LED_G_GPIO_PIN		GPIO_Pin_0
#define LED_G_GPIO_PORT		GPIOB
#define LED_G_GPIO_CLK		RCC_APB2Periph_GPIOB

#define LED_B_GPIO_PIN		GPIO_Pin_1
#define LED_B_GPIO_PORT		GPIOB
#define LED_B_GPIO_CLK		RCC_APB2Periph_GPIOB

// 直接操作寄存器的方法控制IO
#define digitalHi(port, pin)		do {port->BSRR |= pin;} while (0)	// 置位
#define digitalLo(port, pin)		do {port->BRR |= pin;} while (0)	// 复位
#define digitalToggle(port, pin)	do {port->ODR ^= pin;} while (0)	// 反转

// 定义控制IO的宏
#define LED_R_TOGGLE			digitalToggle(LED_R_GPIO_PORT, LED_R_GPIO_PIN)
#define LED_R_ON				digitalLo(LED_R_GPIO_PORT, LED_R_GPIO_PIN)
#define LED_R_OFF				digitalHi(LED_R_GPIO_PORT, LED_R_GPIO_PIN)

#define LED_G_TOGGLE			digitalToggle(LED_G_GPIO_PORT, LED_G_GPIO_PIN)
#define LED_G_ON				digitalLo(LED_G_GPIO_PORT, LED_G_GPIO_PIN)
#define LED_G_OFF				digitalHi(LED_G_GPIO_PORT, LED_G_GPIO_PIN)

#define LED_B_TOGGLE			digitalToggle(LED_B_GPIO_PORT, LED_B_GPIO_PIN)
#define LED_B_ON				digitalLo(LED_B_GPIO_PORT, LED_B_GPIO_PIN)
#define LED_B_OFF				digitalHi(LED_B_GPIO_PORT, LED_B_GPIO_PIN)

// 颜色设置
#define LED_RED			do {LED_R_ON; LED_G_OFF; LED_B_OFF;} while (0)
#define LED_GREEN		do {LED_R_OFF; LED_G_ON; LED_B_OFF;} while (0)
#define LED_BLUE		do {LED_R_OFF; LED_G_OFF; LED_B_ON;} while (0)
#define LED_YELLOW		do {LED_R_ON; LED_G_ON; LED_B_OFF;} while (0)
#define LED_PURPLE		do {LED_R_ON; LED_G_OFF; LED_B_ON;} while (0)
#define LED_CYAN		do {LED_R_OFF; LED_G_ON; LED_B_ON;} while (0)

#define LED_ALL_ON		do {LED_R_ON; LED_G_ON; LED_B_ON;} while (0)
#define LED_ALL_OFF		do {LED_R_OFF; LED_G_OFF; LED_B_OFF;} while (0)

void LED_GPIO_Config(void);

#endif /* __BSP_LED_H */

然后在主函数中进行调用

main.c

#include "stm32f10x.h"
#include "bsp_led.h"

void delay(uint32_t count);

int main(void)
{
	LED_GPIO_Config();

	while (1)
	{
		LED_CYAN;
		delay(0XFFFFF);
		LED_ALL_OFF;
		delay(0XFFFFF);
	}
}

void delay(uint32_t count)
{
	for (; count != 0; count--);
}

GPIO具有锁定机制,可以冻结该GPIO的配置,即在下次复位前,不能更改GPIO的配置。

锁定操作的寄存器为GPIOx_LCKR,具体描述如下

上面的说明起始我感觉挺难理解的,于是找到了标准库里面的源码,发现写的非常清晰,具体如下

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  uint32_t tmp = 0x00010000;
  
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  tmp |= GPIO_Pin;
  /* Set LCKK bit */
  GPIOx->LCKR = tmp;
  /* Reset LCKK bit */
  GPIOx->LCKR =  GPIO_Pin;
  /* Set LCKK bit */
  GPIOx->LCKR = tmp;
  /* Read LCKK bit*/
  tmp = GPIOx->LCKR;
  /* Read LCKK bit*/
  tmp = GPIOx->LCKR;
}

tmp为LCCK位置1,然后把GPIO_Pin的相应值也置1。接下来就是对相应的位执行写入序列操作。

首先是写1,即写入带LCCK和GPIO_Pin的位;

然后写0,写只带GPIO_Pin的位;

然后重复写1;

接下来读GPIOx_LCKR的值到tmp,连续读取两次,完成操作。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值