【前言】
这几天在B站学习了基于stm32的面向对象驱动,我试着用GD32F527进行了实现。在此记录如下:
【基础工程】
我在这篇帖子【GD32F527】创建工程模版-电子产品世界论坛的础之上进行编写。
【LED的端口】
在原理图上,得知开发板有4个LED,高电平点亮。
【面向对象的程序实现】
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的状态、去初始化、操作函数的注册等。