【STM32】编写程序控制开发板的RGB LED灯

1、原理图

在这里插入图片描述
如图知,拉低为点亮

  • LED

    引脚状态
    D3红PB5输出, 拉低为亮
    D3绿PB0输出, 拉低为亮
    D3蓝PB1输出, 拉低为亮

2、文件结构

在这里插入图片描述

3、使用寄存器模式点亮

3.1、什么是寄存器

寄存器是微控制器(MCU)内部的一种特殊存储器,用于存储配置参数、状态信息或控制信号。每个寄存器通常有固定的地址,并且每一位或一组位对应特定的功能。

3.2、寄存器开发的本质

寄存器开发的本质是直接与硬件交互,绕过高级库(如 HAL 库或标准库)的封装,直接操作底层硬件。
STM32 的寄存器开发是通过直接读写寄存器来实现对外设的控制。

3.3、寄存器开发步骤

(1) 查找寄存器地址

  • 根据 STM32 的参考手册(Reference Manual),找到目标外设的寄存器地址。
  • 每个外设(如 GPIO、TIMER、USART 等)都有一组寄存器,用于配置和控制其行为。

(2) 配置寄存器

  • 通过指针操作或直接访问寄存器地址,向寄存器写入特定的值,以配置外设的工作模式、中断、时钟等。

(3) 读取寄存器

  • 通过读取寄存器的值,获取外设的状态信息(如标志位、数据等)。

3.4、主要源码

3.4.1、main.c
#include "drv_gpio.h"

// SysTick 初始化
void SysTick_Init(void)
{
	SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延时
	SysTick->VAL = 0;					 // 清空当前值
	SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}

// 精确延时函数(单位:ms)
void Delay_ms(uint32_t ms)
{
	for (uint32_t i = 0; i < ms; i++)
	{
		while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
			;
	}
}

int main()
{
	// 初始化 SysTick
	SysTick_Init();
	
	// 初始化 RGB LED
	RGB_Init();


	while (1)
	{
		RGB_RedOn();
		Delay_ms(500);  // 延时 500ms
		RGB_RedOff();

		RGB_GreenOn();
		Delay_ms(500);  // 延时 500ms
		RGB_GreenOff();

		RGB_BlueOn();
		Delay_ms(500);  // 延时 500ms
		RGB_BlueOff();
	}
}

3.4.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_

//ARM提供的,有所有外设寄存器的信息
#include "stm32f10x.h"

void RGB_Init(void);

void RGB_RedOn(void);

void RGB_RedOff(void);

void RGB_GreenOn(void);

void RGB_GreenOff(void);

void RGB_BlueOn(void);

void RGB_BlueOff(void);

#endif

3.4.3、drv_gpio.c
#include "drv_gpio.h"

void RGB_Init(void)
{

	// 1.配置RCC
	RCC->APB2ENR |= (1 << 3);

	// 2.配置PB5的功能
	// bit 20~23 全部置为0
	//  bit 20 置为1
	//pb5
	GPIOB->CRL &= (uint32_t)(~(0xF << 20));
	GPIOB->CRL |= (uint32_t)(1 << 20);  //配置为通用推挽输出模式(0b0001)
	//pb0
	GPIOB->CRL &= (uint32_t)(~(0xF));
	GPIOB->CRL |= (uint32_t)(1);
	//pb1
	GPIOB->CRL &= (uint32_t)(~(0xF << 4));
	GPIOB->CRL |= (uint32_t)(1 << 4);  

	// 3.将pb5、pb0、pb1的初始值改为1,防止配置完就亮灯
	GPIOB->ODR |= (1 << 5);
	GPIOB->ODR |= 1;
	GPIOB->ODR |= (1 << 1);


}


void RGB_RedOn(void)
{
	// 3.拉低PB5对应的ODR寄存器地址
	GPIOB->ODR &= ~(1 << 5);
}


void RGB_RedOff(void)
{
	GPIOB->ODR |= (1 << 5);
}

void RGB_GreenOn(void)
{
	GPIOB->ODR &= ~(1);
}

void RGB_GreenOff(void)
{
	GPIOB->ODR |= 1;
}

void RGB_BlueOn(void)
{
	GPIOB->ODR &= ~(1 << 1);
}

void RGB_BlueOff(void)
{
	GPIOB->ODR |= (1 << 1);
}

3.4.4、使用BSRR和BRR影子寄存器优化drv_gpio.c

由于对ODR直接操作, 可能有意无意修改到其他引脚的状态

#include "drv_gpio.h"

void RGB_Init(void)
{

	// 1.配置RCC
	RCC->APB2ENR |= (1 << 3);

	// 2.配置PB5的功能
	// bit 20~23 全部置为0
	//  bit 20 置为1
	//pb5
	GPIOB->CRL &= (uint32_t)(~(0xF << 20));
	GPIOB->CRL |= (uint32_t)(1 << 20);  //配置为通用推挽输出模式(0b0001)
	//pb0
	GPIOB->CRL &= (uint32_t)(~(0xF));
	GPIOB->CRL |= (uint32_t)(1);
	//pb1
	GPIOB->CRL &= (uint32_t)(~(0xF << 4));
	GPIOB->CRL |= (uint32_t)(1 << 4);  

	// 3.将pb5、pb0、pb1的初始值改为1,防止配置完就亮灯
	GPIOB->ODR |= (1 << 5);
	GPIOB->ODR |= 1;
	GPIOB->ODR |= (1 << 1);


}


void RGB_RedOn(void)
{
	// 3.拉低PB5对应的ODR寄存器地址
	//GPIOB->ODR &= ~(1 << 5); 
	GPIOB->BRR &= (1 << 5);// 直接将PB5拉低,同时不影响其他位
}


void RGB_RedOff(void)
{
	//GPIOB->ODR |= (1 << 5);
	GPIOB->BSRR |= (1 << 5); //直接拉高,并不影响
}

void RGB_GreenOn(void)
{
	//GPIOB->ODR &= ~(1);
	GPIOB->BRR &= (1);
}

void RGB_GreenOff(void)
{
	//GPIOB->ODR |= 1;
	GPIOB->BSRR |= (1);
}

void RGB_BlueOn(void)
{
	//GPIOB->ODR &= ~(1 << 1);
	GPIOB->BRR &= (1 << 1);
}

void RGB_BlueOff(void)
{
	//GPIOB->ODR |= (1 << 1);
	GPIOB->BSRR |= (1 << 1);
}

3.4.5、效果演示

在这里插入图片描述

4、使用标准库模式点亮

4.1、使用标准库模式的好处

标准库封装了底层寄存器的操作,提供了易于理解的API函数,开发者无需直接读写寄存器。

4.2、主要源码

4.2.1、main.c
#include "drv_gpio.h"

// SysTick 初始化
void SysTick_Init(void)
{
	SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延时
	SysTick->VAL = 0;					 // 清空当前值
	SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}

// 精确延时函数(单位:ms)
void Delay_ms(uint32_t ms)
{
	for (uint32_t i = 0; i < ms; i++)
	{
		while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
			;
	}
}

int main()
{
	// 初始化 SysTick
	SysTick_Init();
	
	// 初始化 RGB LED
	RGB_Init();


	while (1)
	{
		 RGB_RedOn();
		 Delay_ms(500);  // 延时 500ms
		 RGB_RedOff();

		 RGB_GreenOn();
		 Delay_ms(500);  // 延时 500ms
		 RGB_GreenOff();

		 RGB_BlueOn();
		 Delay_ms(500);  // 延时 500ms
		 RGB_BlueOff();

		 RGB_WriteOn();
		 Delay_ms(500);  // 延时 500ms
		 RGB_WriteOff();

	
	}
}

4.2.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_

//使用gpio标准库
#include "stm32f10x_gpio.h"

#define RGB_Port GPIOB
#define RGB_Pin_R GPIO_Pin_5
#define RGB_Pin_G GPIO_Pin_0
#define RGB_Pin_B GPIO_Pin_1


void RGB_Init(void);

void RGB_RedOn(void);

void RGB_RedOff(void);

void RGB_GreenOn(void);

void RGB_GreenOff(void);

void RGB_BlueOn(void);

void RGB_BlueOff(void);

void RGB_WriteOn(void);

void RGB_WriteOff(void);


#endif

4.2.3、drv_gpio.c
#include "drv_gpio.h"

void RGB_Init(void)
{

	// 1.RCC配置
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	// 2、配置红、绿、蓝灯输出
	GPIO_InitTypeDef gpio_initStruct = {0};
	gpio_initStruct.GPIO_Pin = RGB_Pin_R | RGB_Pin_G | RGB_Pin_B;
	gpio_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
	gpio_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(RGB_Port, &gpio_initStruct);

	GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}


void RGB_RedOn(void)
{
	// 3.拉低PB5对应的ODR寄存器地址
	GPIO_ResetBits(RGB_Port, RGB_Pin_R);
}

void RGB_RedOff(void)
{
	GPIO_SetBits(RGB_Port, RGB_Pin_R);
}

void RGB_GreenOn(void)
{
	GPIO_ResetBits(RGB_Port, RGB_Pin_G);
}

void RGB_GreenOff(void)
{
	GPIO_SetBits(RGB_Port, RGB_Pin_G);
}

void RGB_BlueOn(void)
{
	GPIO_ResetBits(RGB_Port, RGB_Pin_B);
}

void RGB_BlueOff(void)
{
	GPIO_SetBits(RGB_Port, RGB_Pin_B);
}

void RGB_WriteOn(void)
{
	GPIO_ResetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}

void RGB_WriteOff(void)
{
	GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}

4.2.4、效果演示多了白灯

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不被定义的~wolf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值