这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 【GD32F527】面向对象的LED驱动

共2条 1/1 1 跳转至

【GD32F527】面向对象的LED驱动

工程师
2025-10-08 21:34:09     打赏

【前言】

这几天在B站学习了基于stm32的面向对象驱动,我试着用GD32F527进行了实现。在此记录如下:

【基础工程】

我在这篇帖子【GD32F527】创建工程模版-电子产品世界论坛的础之上进行编写。

【LED的端口】

在原理图上,得知开发板有4个LED,高电平点亮。

image.png

【面向对象的程序实现】

1、作为面向对象,最好我们使用的是一个结构体指针,通过对这个结构体进行操作。首先创建一个led的描述头文件led_desc.h,在这个文件中把led需要操作的属性添加进去:

#ifndef __LED_DESC_H__
#define __LED_DESC_H__
#include "gd32f5xx.h"

struct led_desc{
	rcu_periph_enum periph;  //时钟
	uint32_t PORT;           //端口
	uint32_t mode;           //模式
	uint32_t pull_up_down;   //输出模式
	uint32_t pin;            
	FlagStatus Onbit;
	FlagStatus Offbit;
};

#endif /* end __LED_DESC_H__ */

2、添加led.h

#ifndef __LED_H__
#define __LED_H__
#include <stdint.h>
#include <stdbool.h>

struct led_desc;
typedef struct led_desc *led_desc_t;

void led_init(led_desc_t led);
void led_set(led_desc_t led, bool onoff);
void led_on(led_desc_t led);
void led_off(led_desc_t led);

#endif /*  end __LED_H__  */

在这个文件中,声明一个结构体,并声明一个led_desc_t的指针。同时声明一些led的初始化、设置电平,开、关的函数。

3、添加led.c

#include "led.h"
#include "led_desc.h"

void led_init(led_desc_t led)
{
	if(led == NULL)
	{
		return;
	}
    rcu_periph_clock_enable(led->periph);
    gpio_mode_set(led->PORT, led->mode, led->pull_up_down,led->pin);
    gpio_output_options_set(led->PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,led->pin);
    GPIO_BC(led->PORT) = led->pin;
}


void led_set(led_desc_t led, bool onoff)
{
	if(led == NULL)
	{
		return;
	}
	gpio_bit_write(led->PORT, led->pin, onoff ? led->Onbit : led->Offbit);
	
}
void led_on(led_desc_t led)
{
	if(led == NULL)
	{
		return;
	}
	GPIO_BOP(led->PORT) = (uint32_t)led->pin;
//	led_set(led,true);
	
}

void led_off(led_desc_t led)
{
	if(led == NULL)
	{
		return;
	}
	//led_set(led,false);
	GPIO_BC(led->PORT) = led->pin;
}

在led.c中,实现了led操作函数,操作均为led_desc_t 的结构体指针。

4、添加board.c

#include "board.h"
#include "led_desc.h"
#include "led.h"

static struct led_desc led1_desc = {RCU_GPIOF,GPIOF,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_7,SET,RESET};
static struct led_desc led2_desc = {RCU_GPIOF,GPIOF,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_8,SET,RESET};
static struct led_desc led3_desc = {RCU_GPIOE,GPIOE,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_3,SET,RESET};	
static struct led_desc led4_desc = {RCU_GPIOE,GPIOE,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_2,SET,RESET};

led_desc_t led1 = &led1_desc;
led_desc_t led2 = &led2_desc;
led_desc_t led3 = &led3_desc;
led_desc_t led4 = &led4_desc;

在这里主要声明4个小led的时钟、端口、PIN等。并将led1指向这四个led

5、添加board.h

#ifndef __BOARD_H__
#define __BOARD_H__
#include "led.h"
#include "systick.h"

extern led_desc_t led1;
extern led_desc_t led2 ;
extern led_desc_t led3 ;
extern led_desc_t led4 ;

#endif /* end __LED_H__ */

在这里主要把4个led进行extern ,开放给相关的程序进行调用。

到些led的面向对象的就实现了。

【使用】

在main.c中,首先对Led进行初始化,然后编写一个闪灯的程序

#include "board.h"

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    systick_config();
    led_init(led1);
    led_init(led2);
    led_init(led3);
    led_init(led4);

    while(1) {
        /* turn on led1, turn off led4 */
			led_on(led1);
			led_on(led2);
			led_on(led3);
			led_on(led4);
			delay_1ms(500);
			led_off(led1);
			led_off(led2);
			led_off(led3);
			led_off(led4);
			delay_1ms(500);
    }
}

【总结】

在GD32F527的例程中,其实也有官方的的led初始化程序。但是通过这次面向对象的重构,实现驱动,与应用的分离,使得主程序中可阅读性提高,同时也实现比较好的解耦。

【思考】

通过阅读,其实面向对象还是不是很完整,比如只有初始化,但是没有去初始化,还有就是还是没有完全的解耦,移植到其他的平台上,还需要修改led.c这里的程序。

后期我准备进行进一步的修改,比如添加led的状态、去初始化、操作函数的注册等。




关键词: GD32F527     对象     驱动    

高工
2025-10-09 09:15:45     打赏
2楼

我更倾向于led里面只管闪烁,呼吸,亮灭之类的逻辑,参数和依赖的底层接口都丢给初始化函数去传递。这样才能做到可移植,几乎不需要更改内部实现逻辑。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]