GD 32点亮流水灯

1. 0 软件架构设置

2.0 API 接口以及数据结构定义

3.0 程序代码实现

程序项目的结构如下所示:

第一步:编写LED驱动,初始化驱动程序

 创建结构体:第一个参数表示GPIO使能,第二个参数表示单片机的IO口,第三个参数表示需要草操作的单片机引脚,typedef在C语言中可以用于结构体的从命名,结构体的名称是LED_GPIO_T.

创建一个结构体数组,用于存放结构体变量的参数

宏定义数组大小:使用动态的方式进行计算SIZEOF可以计算数组的长度

初始化GPIO驱动,调用结构体变量进行赋值

LED灯开启和熄灭代码


LED.C程序代码

#include "gd32f30x.h"                   // Device header
#include "Delay.h"
#include <stdint.h>



// 初始化结构体结构体数据类型
typedef struct Led_gpio_t{
    rcu_periph_enum rcu;
	uint32_t gpio;
	uint32_t pin;
}LED_GPIO_T;


// 定义一个静态全局变量保存GPIO口的资源信息
static LED_GPIO_T Gpio_List[] = {
     {RCU_GPIOA,GPIOA,GPIO_PIN_8},
	 {RCU_GPIOE,GPIOE,GPIO_PIN_6},
	 {RCU_GPIOF,GPIOF,GPIO_PIN_6}
};

// 宏定义确定数组的大小
#define LED_NUM_MAX (sizeof(Gpio_List) / sizeof(Gpio_List[0]))

void LED_Init_Drive(void){
	for(uint8_t i = 0; i < LED_NUM_MAX; i++){
		// 开启GPIO时钟
		rcu_periph_clock_enable(Gpio_List[i].rcu);
        // 初始化GPIO
		gpio_init(
		        Gpio_List[i].gpio,
				GPIO_MODE_OUT_PP,
				GPIO_OSPEED_10MHZ,
				Gpio_List[i].pin);
		// GPIO 初始化调用的方式
		gpio_bit_reset(Gpio_List[i].gpio,Gpio_List[i].pin);
	}
}

void Turn_LedOn(uint8_t LedNo){
		if(LedNo >= LED_NUM_MAX){
			return;
		}else{
			gpio_bit_set(Gpio_List[LedNo].gpio,Gpio_List[LedNo].pin);
		}

}

void Turn_OffLed(uint8_t LedOff){
		if(LedOff >= LED_NUM_MAX){
			return;
		}else{
			gpio_bit_reset(Gpio_List[LedOff].gpio,Gpio_List[LedOff].pin);
		}
}

// 初始化LED灯
void LED_Init(void){
    // 使能RCU时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	// 配置引脚输出频率
	gpio_init( GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
    
	// 初始化GPIOE的引脚
	rcu_periph_clock_enable(RCU_GPIOE);
	// 配置引脚输出频率
	gpio_init( GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_6);
	
	// 初始化GPIOE的引脚
	rcu_periph_clock_enable(RCU_GPIOF);
	// 配置引脚输出频率
	gpio_init( GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_6);
}





// 实现循环流水灯的功能
void LED_Cycle(void){
	        DelayInit();
	        while(1){
				gpio_bit_set(GPIOA, GPIO_PIN_8); 
				DelayNms(1000);
				gpio_bit_reset(GPIOA, GPIO_PIN_8);
				DelayNms(1000);
				
				gpio_bit_set(GPIOE, GPIO_PIN_6); 
				DelayNms(1000);
				gpio_bit_reset(GPIOE, GPIO_PIN_6);
				DelayNms(1000);
				
				gpio_bit_set(GPIOF, GPIO_PIN_6); 
				DelayNms(1000);
				gpio_bit_reset(GPIOF, GPIO_PIN_6);
				DelayNms(1000);
			}


}



LED.H 程序代码

#ifndef _LED_H_
#define _LED_H_
#include <stdint.h>

//宏定义LED灯的引脚
#define LED1   0
#define LED2   1
#define LED3   2


void LED_Init(void);

void LED_Cycle(void);

void LED_Init_Drive(void);

void Turn_LedOn(uint8_t LedNo);

void Turn_OffLed(uint8_t LedOff);

#endif

硬件延时代码参考(GD32)

DELAY.C

#include <stdint.h>
#include "gd32f30x.h"

/**
***********************************************************
* @brief DWT初始化配置
* @param
* @return 
***********************************************************
*/
void DelayInit(void) 
{
	/* 关闭 TRC */
	CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
	/* 打开 TRC */
	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;

	/* 关闭计数功能 */
	DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
	/* 打开计数功能 */
	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

	/* 计数清零 */
	DWT->CYCCNT = 0;
}

/**
***********************************************************
* @brief 微秒级延时函数
* @param nUs,最大延时时间( 2^32 / 内核主频 ) * 10^6 us 
* @return 
***********************************************************
*/
void DelayNus(uint32_t nUs)
{
	uint32_t tickStart = DWT->CYCCNT;

	/* 转换为nUs对应的时钟跳动次数rcu_clock_freq_get获取系统的时钟频率*/
	nUs *= (rcu_clock_freq_get(CK_AHB) / 1000000);

	/* 延时等待 */
	while ((DWT->CYCCNT - tickStart) < nUs);
}

/**
***********************************************************
* @brief 毫秒级延时函数
* @param nMs,延时时间n毫秒
* @return 
***********************************************************
*/
void DelayNms(uint32_t nMs)
{
	for (uint32_t i = 0; i < nMs; i++)
	{
		DelayNus(1000);
	}
}

DELAY.H

#ifndef _DELAY_H_
#define _DELAY_H_
#include <stdint.h>


void DelayInit(void);
void DelayNus(uint32_t nUs);
void DelayNms(uint32_t nMs);

#endif

main 函数代码实现

#include <stdio.h>
#include "gd32f30x.h"
#include "Delay.h"
#include "LED.h"



/*
	硬件延时的方法:比较准确
*/
int main(void)
{    
	// 初始化LED
	DelayInit();
	// 初始化LED
	LED_Init_Drive();
	
     
	while(1){
	   	Turn_LedOn(LED1);
    	DelayNms(1000);	
		Turn_LedOn(LED2);
    	DelayNms(1000);	
		Turn_LedOn(LED3);
    	DelayNms(1000);	
		Turn_OffLed(LED1);
		Turn_OffLed(LED2);
		Turn_OffLed(LED3);
		DelayNms(1000);
	} 
	
}





以上是LED实现流水灯代码案例


4.0 STM32 单片机类比学习

.....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/782835.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html+css+js贪吃蛇游戏

贪吃蛇游戏&#x1f579;四个按钮控制方向&#x1f3ae; 源代码在图片后面 点赞❤️关注&#x1f64f;收藏⭐️ 互粉必回&#x1f64f;&#x1f64f;&#x1f60d;&#x1f60d;&#x1f60d; 源代码&#x1f4df; <!DOCTYPE html> <html lang"en"&…

idea删除分支并同步到gitLab以及gitLab上的分支删除

目录 idea删除分支并同步到gitLab 方法一&#xff08;推荐&#xff09; 方法二&#xff08;命令行&#xff09; gitLab上的分支删除 前言-与正文无关 ​ 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&…

Tell Me Why:利用大型语言模型进行可解释的公共健康事实核查

Tell Me Why: Explainable Public Health Fact-Checking with Large Language Models 论文地址:https://arxiv.org/abs/2405.09454https://arxiv.org/abs/2405.09454 1.概述 最近的COVID-19大流行突显了公共健康领域事实核查的关键需求。在信息通过社交媒体平台迅速传播的时…

GPU 张量核心(Tensor Core)技术解读

一文理解 GPU 张量核心&#xff08;Tensor Core&#xff09; 引言 最新一代Nvidia GPU搭载Tensor Core技术&#xff0c;本指南深度解读其卓越性能&#xff0c;为您带来极致体验。 Nvidia最新GPU微架构中的核心技术——Tensor Core&#xff0c;自Volta起每代均获突破&#xf…

【漏洞复现】Emlog Pro 2.3.4——任意用户登入、会话持久化(CVE-2024-5044)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现 漏洞描述 漏洞编号&#xff1a;CVE-2024-5044 漏洞成因&#xff1a; 在Emlog Pro …

加密与安全_ 解读非对称密钥解决密钥配送问题的四个方案

文章目录 Pre对称密钥的死穴 - 经典的密钥配送问题什么是非对称密钥非对称密钥解决密钥配送问题的四个方案共享密钥密钥分配中心&#xff08;KDC&#xff09;Diffie-Hellman 密钥交换体系公钥密码体系RSA算法 Pre 对称密钥的死穴 - 经典的密钥配送问题 假设 Alice 和 Bob 两个人…

阻塞赋值与非阻塞赋值

文章目录 一、何为“阻塞”&#xff1f;二、阻塞赋值与非阻塞赋值1. 阻塞式赋值“”2.非阻塞式赋值“<” 三、什么时候用阻塞赋值或非阻塞赋值&#xff1f; 一、何为“阻塞”&#xff1f; 所谓“阻塞”&#xff0c;可以理解为阻止顺序语句块中其他语句的执行。例如&#xf…

ASP.NET Core----基础学习04----Model模型的创建 服务的注入

文章目录 1. 创建Models文件夹&#xff0c;3个文件的内容如下&#xff1a;&#xff08;1&#xff09;模型的创建&#xff08;2&#xff09;服务的注入 1. 创建Models文件夹&#xff0c;3个文件的内容如下&#xff1a; &#xff08;1&#xff09;模型的创建 模型的基础类Student…

阿里云 Ubuntu 开启允许 ssh 密码方式登录

以前用的 centos&#xff0c;重置系统为 ubuntu 后在ssh 远程连接时遇到了点问题&#xff1a; 在阿里云控制台重置实例密码后无法使用密码进行 SSH 连接登录 原因&#xff1a;阿里云 Ubuntu 默认禁用密码登录方式 解决办法&#xff1a; 先使用其他用户登录到服务器 这里进来…

Java中多线程经典案例

案例一单例模式 只有一个对象,只实例化一个对象 饿汉模式 在程序开始初期的实例化一个对象 static成员初始化时机是在类加载的时候,static修饰的instance只有唯一一个,初始化也是只执行一次,static修饰的是类属性,就是在类对象上的,每个类对象在JVM中只有一份,里面的静态成员…

下载安装JavaFX及解决报错:缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序|Eclipse

目录 1.下载并解压 2.Eclipse配置 3.报错问题 解决方法1&#xff1a;将javaSE更改到9以下 解决方法2&#xff1a; 使用module-info.java配置解决 1.下载并解压 JavaFX下载地址&#xff1a;JavaFX - Gluon 选择合适自己电脑配置的sdk版本下载 打不开网页的参考这个博客&…

Demeditec Diagnostics — AMH ELISA试剂盒

抗缪勒氏管激素(AMH)&#xff0c;是一种二聚体分子量为140 KDa的糖蛋白&#xff0c;是转化生长因子-β (TGF-β)细胞因子家族&#xff0c;在生殖结构正常分化中起重要作用。AMH已被被确定为卵巢储备的可靠标志&#xff0c;有助于预测早期卵泡丢失和更年期开始。AMH水平也反映了…

【Python画图-seaborn驯化】一文学会seaborn画因子变量图catplot函数使用技巧

【Python画图-seaborn驯化】一文学会seaborn画因子变量图catplot函数使用技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内…

【运营版】公众号接口回调出租用出售微信公众号多域名无限回调授权系统+接口文档

此系统用于微信无限回调单个用户授权&#xff0c;如你的无限回调借给他人使用&#xff0c;怕他人泛滥您的无限回调&#xff0c;导致您的域名或者公众号经常封&#xff0c;那么你们可以用此系统给他们设置一个授权使用权限&#xff0c;如给指定域名添加授权登录&#xff0c;那么…

【Linux】目录的相关命令——cd,pwd,mkdir,rmdir

1.相对路径与绝对路径 在开始目录的切换之前&#xff0c;你必须要先了解一下所谓的路径&#xff08;PATH)&#xff0c;有趣的是&#xff1a;什么是相对路 与绝对路径&#xff1f; 绝对路径&#xff1a;路径的写法“一定由根目录/写起”&#xff0c;例如&#xff1a;/usr/shar…

间接平差——以水准网平差为例 (matlab详细过程版)

目录 一、原理概述二、案例分析三、代码实现四、结果展示本文由CSDN点云侠原创,间接平差——以水准网平差为例 (matlab详细过程版),爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT生成的文章。 一、原理概述 间接平差的函数模型和随机模型…

深入分析 Android BroadcastReceiver (十)(完)

文章目录 深入分析 Android BroadcastReceiver (十)1. 深入理解 Android 广播机制的高级应用与实践1.1 高级应用1.1.1 示例&#xff1a;广播启动服务1.1.2 示例&#xff1a;数据变化通知1.1.3 示例&#xff1a;下载完成通知 1.2 实践建议1.2.1 设置权限1.2.2 动态注册和注销广播…

零基础STM32单片机编程入门(十) 28BYJ-48步进电机的控制实战含源码视频

文章目录 一.概要二.28BYJ-48步进电机介绍三.步进电机的主要特性四.步进电机驱动1.驱动硬件介绍2.四相八拍程序控制介绍 五.STM32单片机驱动步进电机正转反转实验六.CubeMX工程源代码下载七.讲解视频链接地址八.小结 一.概要 步进电机是将电脉冲信号转变为角位移或线位移的开环…

102.二叉树的层序遍历——二叉树专题复习

迭代方式&#xff1a; class Solution {// 定义一个成员变量res来存储层序遍历的结果List<List<Integer>> res new ArrayList<>();// levelOrder方法是层序遍历的接口&#xff0c;它接受一个二叉树的根节点rootpublic List<List<Integer>> lev…

开展新版FMEA培训如何避免陷入形式主义?

在企业中开展新版FMEA培训&#xff0c;旨在提升员工对产品潜在故障及其影响的识别、评估和控制能力&#xff0c;从而增强产品质量和可靠性。然而&#xff0c;不少企业在开展新版FMEA培训时往往容易陷入形式主义&#xff0c;导致培训效果不佳。为了避免这种情况&#xff0c;我们…