当前位置: 首页 > news >正文

GD 32 流水灯

前言:


通过后面的学习掌握了一些逻辑架构的知识,通过复习的方式将学到的裸机任务架构的知识运用起来,同时巩固前面学到的知识,GPIO的配置等。


 开发板上LED引脚使用示意图

 注:此次LED灯的点亮凡是是高电平点亮,因为电流是从外部向内部进行流动,GND会引脚的店电平拉低,如果给低电平的话无法形成电势差,电流是无法流动的,给一个高电平,电流在电压的作用下点亮LED灯

第一种实现方式

这种方式类似于STM32的库函数编程,不使用结构体使用直接编写的方式进行配置,可以作为参考对比学习


1.0 初始化LED

void LED_Init(void)
{// 开启RCC时钟rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_GPIOE);rcu_periph_clock_enable(RCU_GPIOF);// 初始化gpiogpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_8);gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);gpio_init(GPIOF,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);// 引脚默认电平为低电平gpio_bit_reset(GPIOA, GPIO_PIN_8);gpio_bit_reset(GPIOE, GPIO_PIN_6);gpio_bit_reset(GPIOF, GPIO_PIN_6);
}

 2.0 LED点亮熄灭

// 高电平的方式点亮
void LED1_On(void)
{gpio_bit_set(GPIOA, GPIO_PIN_8);
}void LED2_On(void)
{gpio_bit_set(GPIOE, GPIO_PIN_6);
}void LED3_On(void)
{gpio_bit_set(GPIOF, GPIO_PIN_6);
}// 低电平的方式熄灭
void LED1_Off(void)
{gpio_bit_reset(GPIOA, GPIO_PIN_8);
}void LED2_Off(void)
{gpio_bit_reset(GPIOE, GPIO_PIN_6);
}void LED3_Off(void)
{gpio_bit_reset(GPIOF, GPIO_PIN_6);
}

3.0 LED 流水灯函数

// LED 灯流水效果函数
void LED_Run(void)
{LED1_On();DelayNms(1000);LED2_On();DelayNms(1000);LED3_On();DelayNms(1000);LED1_Off();LED2_Off();LED3_Off();DelayNms(1000);
}

4.0 LED灯初始化头文件

#ifndef  _LED_DRV_H_
#define  _LED_DRV_H_
#include <stdint.h>void LED_Init(void);
void LED1_On(void);
void LED2_On(void);
void LED3_On(void);
void LED1_Off(void);
void LED2_Off(void);
void LED3_Off(void);
void LED_Run(void);#endif

5.0 在主函数中调用

使用面向对象的编码方式,可以使程序看起来更为的简洁,方便程序的后续移植。

#include <stdint.h>
#include "gd32f30x.h"
#include "led_drv.h"
#include "delay.h"int main(void)
{DelayInit();LED_Init();while(1){LED_Run();}
}

** 方式 2 **

第二种实现方式

这种实现方式是配合结构体与for循环的方式进行实现,可以方便后续程序的编码与维护,让程序可移植性更强。


1.0 创建结构体

// 创建结构体
typedef struct
{// rcu时钟rcu_periph_enum rcu;// gpio口uint32_t gpio;// 对应引脚uint32_t pin;}LED_GPIO_t;

 2.0 创建结构体数组

// 计算数组大小
#define  LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0]))//创建结构体数组
static LED_GPIO_t g_gpioList[] = 
{{RCU_GPIOA, GPIOA, GPIO_PIN_8},{RCU_GPIOE, GPIOE, GPIO_PIN_6},{RCU_GPIOF, GPIOF, GPIO_PIN_6}
};

3.0 初始化GPIO

这里使用for循环遍历,然后将值一个个的赋值给结构体成员变量完成时钟的初始化

void LED_DrvInit(void)
{uint8_t i = 0;for(i = 0; i < LED_NUM_MAX; i++){// 开启rcu时钟rcu_periph_clock_enable(g_gpioList[i].rcu);// 初始化gpio端口gpio_init(g_gpioList[i].gpio, GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ, g_gpioList[i].pin);// 引脚默认值gpio_bit_reset(g_gpioList[i].gpio, g_gpioList[i].pin);}}

4.0 点亮LED函数,带参数

// LED_ON 点亮
void LED_No(uint8_t ledNo)
{// 判断led编号的值是否大于最大数组长度if(ledNo > LED_NUM_MAX){return; // 返回值无效}// 点亮gpio_bit_set(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}

5.0 熄灭LED灯函数,带参数

// LED_OFF熄灭
void LED_Off(uint8_t ledNo)
{if (ledNo >= LED_NUM_MAX){return;}gpio_bit_reset(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}

6.0 流水灯程序代码实现

void LED_StructRun(void)
{LED_No(LED1);DelayNms(1000);LED_No(LED2);DelayNms(1000);LED_No(LED3);DelayNms(1000);LED_Off(LED1);LED_Off(LED2);LED_Off(LED3);DelayNms(1000);
}

8.0 #define 定义LED编号

#define  LED1  0
#define  LED2  1
#define  LED3  2

9.0 函数头文件代码

#ifndef  _LED_STRUCTDRV_H_
#define  _LED_STRUCTDRV_H_#include "stdint.h"void LED_DrvInit(void);
// LED_ON 点亮
void LED_No(uint8_t ledNo);
// LED_OFF熄灭
void LED_Off(uint8_t ledNo);
// 流水灯
void LED_StructRun(void);#endif

10.0 主函数调用程序

#include <stdint.h>
#include "gd32f30x.h"
#include "led_drv.h"
#include "delay.h"
#include "led_struct_drv.h"int main(void)
{DelayInit();//	LED_Init();LED_DrvInit();while(1){//		LED_Run();LED_StructRun();}
}

11.0 完整代码展示

第一种方式完整C函数代码

#include "gd32f30x.h"                   // Device header
#include <stdint.h>
#include "led_drv.h"
#include "delay.h"void LED_Init(void)
{// 开启RCC时钟rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_GPIOE);rcu_periph_clock_enable(RCU_GPIOF);// 初始化gpiogpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_8);gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);gpio_init(GPIOF,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);// 引脚默认电平为低电平gpio_bit_reset(GPIOA, GPIO_PIN_8);gpio_bit_reset(GPIOE, GPIO_PIN_6);gpio_bit_reset(GPIOF, GPIO_PIN_6);
}// 高电平的方式点亮
void LED1_On(void)
{gpio_bit_set(GPIOA, GPIO_PIN_8);
}void LED2_On(void)
{gpio_bit_set(GPIOE, GPIO_PIN_6);
}void LED3_On(void)
{gpio_bit_set(GPIOF, GPIO_PIN_6);
}// 低电平的方式熄灭
void LED1_Off(void)
{gpio_bit_reset(GPIOA, GPIO_PIN_8);
}void LED2_Off(void)
{gpio_bit_reset(GPIOE, GPIO_PIN_6);
}void LED3_Off(void)
{gpio_bit_reset(GPIOF, GPIO_PIN_6);
}// LED 灯流水效果函数
void LED_Run(void)
{LED1_On();DelayNms(1000);LED2_On();DelayNms(1000);LED3_On();DelayNms(1000);LED1_Off();LED2_Off();LED3_Off();DelayNms(1000);
}

第二种方式完整C函数代码

#include "gd32f30x.h"                   // Device header
#include "stdint.h"
#include "delay.h"#define  LED1  0
#define  LED2  1
#define  LED3  2// 创建结构体
typedef struct
{// rcu时钟rcu_periph_enum rcu;// gpio口uint32_t gpio;// 对应引脚uint32_t pin;}LED_GPIO_t;// 计算数组大小
#define  LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0]))//创建结构体数组
static LED_GPIO_t g_gpioList[] = 
{{RCU_GPIOA, GPIOA, GPIO_PIN_8},{RCU_GPIOE, GPIOE, GPIO_PIN_6},{RCU_GPIOF, GPIOF, GPIO_PIN_6}
};void LED_DrvInit(void)
{uint8_t i = 0;for(i = 0; i < LED_NUM_MAX; i++){// 开启rcu时钟rcu_periph_clock_enable(g_gpioList[i].rcu);// 初始化gpio端口gpio_init(g_gpioList[i].gpio, GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ, g_gpioList[i].pin);// 引脚默认值gpio_bit_reset(g_gpioList[i].gpio, g_gpioList[i].pin);}}// LED_ON 点亮
void LED_No(uint8_t ledNo)
{// 判断led编号的值是否大于最大数组长度if(ledNo > LED_NUM_MAX){return; // 返回值无效}// 点亮gpio_bit_set(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}// LED_OFF熄灭
void LED_Off(uint8_t ledNo)
{if (ledNo >= LED_NUM_MAX){return;}gpio_bit_reset(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}void LED_StructRun(void)
{LED_No(LED1);DelayNms(1000);LED_No(LED2);DelayNms(1000);LED_No(LED3);DelayNms(1000);LED_Off(LED1);LED_Off(LED2);LED_Off(LED3);DelayNms(1000);
}

12.0 回调函数基础知识补充

定义:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调

函数 F1 调用函数 F2 的时候,函数 F1 通过参数给 函数 F2 传递了另外一个函数 F3 的指针,在函数 F2 执行的过程中,函数F2 调用了函数 F3,这个动作就叫做回调(Callback),而先被当做指针传入、后面又被回调的函数 F3 就是回调函数。

以上定义参考自菜鸟教程

#define _CRT_SECURE_NO_WARNINGS
#include <easyx.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>int Sum(int x, int y) 
{return x + y;
}// 创建一个函数,参数是函数指针
void Handle(int (*pSum)(int a, int b)) 
{int sum = (*pSum)(1, 2);printf("%d\n", sum);
}int main() {Handle(Sum);return 0;}

函数的执行结果是3

typedef 可以对函数进行重定义,注意这个时候的写法是表示的含义还是不同的比如以下的案例

typedef unsigned char uchar; 给变量进行从命名,如unsigned char 命名为uchar,

#define _CRT_SECURE_NO_WARNINGS
#include <easyx.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>// 这个时候函数指针变量的名字是 PFUNC
typedef int (*PFUNC)(int a, int b);int Sum(int x, int y) 
{return x + y;
}// 创建一个函数,参数是函数指针
void Handle(PFUNC pSum)
{int sum = (*pSum)(1, 2);printf("%d\n", sum);
}int main() {Handle(Sum);return 0;}

以上程序的执行结果也是三


 ...


结尾


目的是通过本次代码的编写巩固之前的知识,同时使用想把裸机程序任务调度的方式,以及回调函数的知识运用在本次的代码当中,方便理解后续的代码知识,以上内容仅供学习参考,后续后继续更细裸机任务调度方案以及回调函数相关的运用。

相关文章:

GD 32 流水灯

前言&#xff1a; 通过后面的学习掌握了一些逻辑架构的知识&#xff0c;通过复习的方式将学到的裸机任务架构的知识运用起来&#xff0c;同时巩固前面学到的知识&#xff0c;GPIO的配置等。 开发板上LED引脚使用示意图 注&#xff1a;此次LED灯的点亮凡是是高电平点亮&#xff…...

数据结构之栈详解

1. 栈的概念以及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈…...

算法:BFS解决 FloodFill 算法

目录 FloodFill 算法 题目一&#xff1a;图像渲染 题目二&#xff1a;岛屿数量 题目三&#xff1a;岛屿的最大面积 题目四&#xff1a;被围绕的区域 FloodFill 算法 在递归搜索回溯中已经说到过 FloodFill 算法了&#xff0c;但是那里是用 dfs 解决的&#xff0c;这里会使…...

Python 中文双引号 “”

Python 中文双引号 “” 1. SyntaxError: invalid character in identifier2. CorrectionReferences 1. SyntaxError: invalid character in identifier print(Albert Einstein once said, “A person who never made a mistake never tried anything new.”) print(Albert Ei…...

以太网(Ethernet)

目录 1. What is Internet?1.1. What is Ethernet?2. TCP/IP3. Physical Layer(PHY)4. Data Link Layer4.1. MAC Sublayer5. Network Layer5.1. IP5.2. ARP6. Transport Layer6.1. UDP6.2. TCP7. Application LayerFPGA实现以太网(一)——以太网简介 网络与路由交换 菜鸟FP…...

Scrcpy adb server version (41) doesn‘t match this client (39); killing...

通过Snap 在Ubuntu上安装 scrcpy之后&#xff0c;启动会导致无法同时 scrcpy和adb logcat 过滤日志 目前最新的安装的platforms-tools下面的adb 版本最新都是 adb 41版本 解决办法&#xff1a; 在这里链接里面 下载 adb 1.0.39 版本&#xff0c;替换 /home/host/Android/Sdk/…...

微服务实战系列之玩转Docker(四)

前言 幸福&#xff0c;就是继续追寻已经拥有的东西。 ——圣奥古斯丁 什么算已经拥有的&#xff1f;比如爱你的人在等你&#xff0c;比如每日热腾腾的三餐&#xff0c;比如身边可爱的同事&#xff0c;又比如此刻的你&#xff0c;看见了这篇博文&#xff08;&#x1f601;&#…...

微信小程序-自定义组件生命周期

一.created 组件实例创建完毕调用。定义在lifetimes对象里。 不能在方法里面更改data对象里面的值&#xff0c;但是可以定义属性值。 lifetimes:{//不能给data设置值created(){this.testaaconsole.log("created") }}二. attached 模板解析完成挂载到页面。 可以更…...

2024年7月23日(samba DNS)

​ 回顾 1、关闭防火墙&#xff0c;关闭selinux systemctl stop firewalld systemctl disable firewalld setenforce 0 2、修改静态IP地址 vim /etc/sysconfig/network-scripts/ifcfg-ens33 #修改uuid的目的是为了保证网络的唯一性 3、重启网络服务 systemctl restart netwo…...

Hyperledger顶级项目特点和介绍

Hyperledger的顶级项目 Hyperledger是Linux基金会主持的开源区块链项目&#xff0c;其目的是推动跨行业的区块链技术的开发和应用。以下是Hyperledger的顶级项目&#xff1a; 1. Hyperledger Fabric 描述&#xff1a;Hyperledger Fabric是一个可扩展的企业级区块链平台&…...

操作系统——笔记(1)

操作系统是管理计算机硬件资源&#xff0c;控制其他程序运行并为用户提供交互操作界面的系统软件的集合&#xff0c;控制和管理着整个计算机系统的硬件和软件资源&#xff0c;是最基本的系统软件。 常见的操作系统&#xff1a;ios、windows、Linux。 计算机系统的结构层次&am…...

isEmpty() 和 isBlank()的区别

isEmpty() 和 isBlank()的区别 平时自己开发的时候没有注意到这个地方,直到实习的时候代码审查的时候发现其用法上两者的不同. isEmpty() public static boolean isEmpty(String str) {return str null || str.length() 0; }isBlank() public static boolean isBlank(Strin…...

scrapy生成爬虫数据为excel

scrapy生成爬虫数据为excel 使用openpyxl&#xff08;推荐&#xff09;安装openpyxl库建一个新的Item Pipeline类在settings.py中启用ExcelPipeline说明 使用scrapy-xlsx首先&#xff0c;安装scrapy-xlsx&#xff1a;然后在Scrapy爬虫中使用管道&#xff1a;说明 要使用Scrapy生…...

vscode debug C++无法输入问题

研究了半天vscode debug c无法输入的问题&#xff0c;原来vscode的文档里面已经记录了。issue都是2020年提的了&#xff0c;还没解决。。。 不过人家也确实给了一个解法&#xff1a;用外部的terminal。 不过怎么看都还不是很方便&#xff0c;所以还是推荐直接使用CodeLLDB插件来…...

MODBUS tcp学习总结

MODBUS TCP协议实例数据帧详细分析_modbus 帧结构-CSDN博客...

【第一天】计算机网络 TCP/IP模型和OSI模型,从输入URL到页面显示发生了什么

TCP/IP模型和OSI模型 这两个模型属于计算机网络的体系结构。 OSI模型是七层模型&#xff0c;从上到下包括&#xff1a; 应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;物理层 TCP/IP模型是四层模型&…...

发现FionaAI:免费体验最新的GPT-4o Mini模型!

你现在可以在FionaAI上免费体验OpenAI刚刚发布的GPT-4o Mini模型&#xff01;作为您在Google Chrome中的ChatGPT驱动助手&#xff0c;FionaAI可以随时随地与您对话&#xff0c;帮助您轻松创作和处理文本。 为什么选择GPT-4o Mini&#xff1f; 最新技术&#xff1a;GPT-4o Mini是…...

Linux Gui 窗口对话和窗口操作

zenity 可以实现窗口对话 eg: zenity --error --width 300 --text "Permission denied. Cannot write to the file." ChosenDate$(zenity --calendar --text "Choose a date" --title "How-To Geek Rota" --day 1 --month 9 --year 2019); …...

人工智能驾驶技术:引领未来道路

随着科技的不断进步&#xff0c;人工智能驾驶技术正以惊人的速度改变着我们的交通方式和生活方式。这项技术不仅令人兴奋&#xff0c;还引发了许多关于安全性、道德和法律等方面的深思。本文将探讨人工智能自动驾驶技术的发展现状、应用前景以及对社会的影响。 技术背景与发展…...

管理的核心是管人,管人的核心就是这3条,看懂的是高手

管理的核心是管人&#xff0c;管人的核心就是这3条&#xff0c;看懂的是高手 一&#xff1a;管欲 每个人都有欲望&#xff0c;无可厚非。管理者的任务就是利用欲望&#xff0c;管理欲望&#xff0c;通过欲望来达到管人的目的。 最需要管理的就是以下两种&#xff1a; 1、金…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...