0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HAL库GPIO在cubemx中的配置及注意事项

jf_L18yujSQ 来源:小飞哥玩嵌入式 作者:小飞哥玩嵌入式 2022-10-19 09:10 次阅读

本节内容介绍

1、HAL库GPIO在cubemx中的配置及注意事项;

2、HAL库GPIO操作详解与结构介绍;

3、rt-thread任务介绍与创建;

4、利用多任务点灯,实现rtos多任务创建于执行;

HAL库GPIO在cubemx中的配置

上节课程我们介绍了cubemx的界面、时钟配置以及如何新建工程等,本节咱们就继续进行程序员届的“hello world”-“点灯”。

GPIO选择与配置

嵌入式软件工程师拿到板子第一件事要做的一定是熟悉原理图,你可以不会设计,但一定要能看懂,软件工程师调试代码,一看原理图,二才是写代码、调试代码

先来看看开发板上的LED是哪个引脚,可以看到PB6、PE3、PD15都是LED控制引脚,采用的是灌电流的方式,低电平灯亮:

3f40004e-4f44-11ed-a3b6-dac502259ad0.png

接下来,咱们在cubemx对这些IO进行配置,小飞哥只选择了两个LED灯,名字命名和原理图保持一致或者是按照实际功能命名

3f7a31ce-4f44-11ed-a3b6-dac502259ad0.png

右击选择第一个选项,就可以修改label3fbfab64-4f44-11ed-a3b6-dac502259ad0.png

单击选中,会有很多功能,MCU的一个引脚是可以复用为许多功能的,我们根据自己的需要配置对应的模式即可,此处我们控制LED灯,低电平-灯亮,高电平-灯灭,显然是要配置为输出模式的,选择output即可,其他输出引脚同理

3ff62b76-4f44-11ed-a3b6-dac502259ad0.png

接下来我们来看下GPIO的一些模式配置

403c2374-4f44-11ed-a3b6-dac502259ad0.png

对于开发板上的LED控制引脚,我们可以按照如下配置,初始化输出高电平,LED不开启,这样初始化就可以设置GPIO输出电平,设置为需要的状态:

4086a9bc-4f44-11ed-a3b6-dac502259ad0.png

GPIO配置比较简单,就不再啰嗦了

HAL库GPIO操作详解与结构介绍

打开生成的代码,看看上面配置的GPIO初始化内容,上面cubemx的配置项可以看到已经生成对应的代码了,GPIO的配置顺序:使能GPIO时钟->配置相关采参数

voidMX_GPIO_Init(void)
{

GPIO_InitTypeDefGPIO_InitStruct={0};

/*GPIOPortsClockEnable*/
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(Y_LED_GPIO_Port,Y_LED_Pin,GPIO_PIN_RESET);

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(CP_LED_GPIO_Port,CP_LED_Pin,GPIO_PIN_RESET);

/*ConfigureGPIOpin:PtPin*/
GPIO_InitStruct.Pin=Y_LED_Pin;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(Y_LED_GPIO_Port,&GPIO_InitStruct);

/*ConfigureGPIOpin:PtPin*/
GPIO_InitStruct.Pin=CP_LED_Pin;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(CP_LED_GPIO_Port,&GPIO_InitStruct);

}

关于GPIO操作的API:

/*Initializationandde-initializationfunctions*****************************/
voidHAL_GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_Init);
voidHAL_GPIO_DeInit(GPIO_TypeDef*GPIOx,uint32_tGPIO_Pin);

/**
*@}
*/

/**@addtogroupGPIO_Exported_Functions_Group2IOoperationfunctions
*@{
*/

/*IOoperationfunctions*****************************************************/
GPIO_PinStateHAL_GPIO_ReadPin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);
voidHAL_GPIO_WritePin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin,GPIO_PinStatePinState);
voidHAL_GPIO_TogglePin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);
HAL_StatusTypeDefHAL_GPIO_LockPin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);
voidHAL_GPIO_EXTI_IRQHandler(uint16_tGPIO_Pin);
voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin);

本节由于是LED操作,我们只需要操作:

voidHAL_GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_Init);
voidHAL_GPIO_WritePin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin,GPIO_PinStatePinState);
voidHAL_GPIO_TogglePin(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);

如何使用呢?

参数GPIO_TypeDef *GPIOx可以是GPIO组的地址:

#defineGPIOA((GPIO_TypeDef*)GPIOA_BASE)
#defineGPIOB((GPIO_TypeDef*)GPIOB_BASE)
#defineGPIOC((GPIO_TypeDef*)GPIOC_BASE)
#defineGPIOD((GPIO_TypeDef*)GPIOD_BASE)
#defineGPIOE((GPIO_TypeDef*)GPIOE_BASE)
#defineGPIOF((GPIO_TypeDef*)GPIOF_BASE)
#defineGPIOG((GPIO_TypeDef*)GPIOG_BASE)
#defineGPIOH((GPIO_TypeDef*)GPIOH_BASE)
#defineGPIOI((GPIO_TypeDef*)GPIOI_BASE)
参数GPIO_Pin可以是GPIO的引脚号:

#defineGPIO_PIN_0((uint16_t)0x0001)/*Pin0selected*/
#defineGPIO_PIN_1((uint16_t)0x0002)/*Pin1selected*/
#defineGPIO_PIN_2((uint16_t)0x0004)/*Pin2selected*/
#defineGPIO_PIN_3((uint16_t)0x0008)/*Pin3selected*/
#defineGPIO_PIN_4((uint16_t)0x0010)/*Pin4selected*/
#defineGPIO_PIN_5((uint16_t)0x0020)/*Pin5selected*/
#defineGPIO_PIN_6((uint16_t)0x0040)/*Pin6selected*/
#defineGPIO_PIN_7((uint16_t)0x0080)/*Pin7selected*/
#defineGPIO_PIN_8((uint16_t)0x0100)/*Pin8selected*/
#defineGPIO_PIN_9((uint16_t)0x0200)/*Pin9selected*/
#defineGPIO_PIN_10((uint16_t)0x0400)/*Pin10selected*/
#defineGPIO_PIN_11((uint16_t)0x0800)/*Pin11selected*/
#defineGPIO_PIN_12((uint16_t)0x1000)/*Pin12selected*/
#defineGPIO_PIN_13((uint16_t)0x2000)/*Pin13selected*/
#defineGPIO_PIN_14((uint16_t)0x4000)/*Pin14selected*/
#defineGPIO_PIN_15((uint16_t)0x8000)/*Pin15selected*/
#defineGPIO_PIN_All((uint16_t)0xFFFF)/*Allpinsselected*/
参数GPIO_PinState PinState可以是:
/**
*@briefGPIOBitSETandBitRESETenumeration
*/
typedefenum
{
GPIO_PIN_RESET=0U,
GPIO_PIN_SET
}GPIO_PinState;

输出低电平:

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(Y_LED_GPIO_Port,Y_LED_Pin,GPIO_PIN_RESET);

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(CP_LED_GPIO_Port,CP_LED_Pin,GPIO_PIN_RESET);

输出高电平:

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(Y_LED_GPIO_Port,Y_LED_Pin,GPIO_PIN_SET);

/*ConfigureGPIOpinOutputLevel*/
HAL_GPIO_WritePin(CP_LED_GPIO_Port,CP_LED_Pin,GPIO_PIN_SET);

翻转电平:

HAL_GPIO_TogglePin(Y_LED_GPIO_Port,Y_LED_Pin);
HAL_GPIO_TogglePin(CP_LED_GPIO_Port,CP_LED_Pin);

关于GPIO输出不外乎这几个API,掌握如何使用就可以了

rt-thread任务介绍与创建

主要摘取一些比较关键的信息,也可参见RT-Thread官网介绍

线程管理

嵌入式系统执行这样的任务,系统通过传感器采集数据,并通过显示屏将数据显示出来,在多线程实时系统中,可以将这个任务分解成两个子任务,如下图所示,一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。40b5042e-4f44-11ed-a3b6-dac502259ad0.png

在 RT-Thread 中,与上述子任务对应的程序实体就是线程,线程是实现任务的载体,它是 RT-Thread 中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。

线程状态

线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。在 RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。RT-Thread 中线程的五种状态,如下表所示:

状态 描述
初始状态 当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在 RT-Thread 中的宏定义为 RT_THREAD_INIT
就绪状态 在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在 RT-Thread 中的宏定义为 RT_THREAD_READY
运行状态 线程当前正在运行。在单核系统中,只有 rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在 RT-Thread 中的宏定义为 RT_THREAD_RUNNING
挂起状态 也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在 RT-Thread 中的宏定义为 RT_THREAD_SUSPEND
关闭状态 当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在 RT-Thread 中的宏定义为 RT_THREAD_CLOSE

线程状态切换

RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示:

40c6425c-4f44-11ed-a3b6-dac502259ad0.png

线程优先级

RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。

RT-Thread 最大支持 256 个线程优先级 (0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持 8 个或 32 个优先级的系统配置;对于 ARM Cortex-M 系列,普遍采用 32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。

时间片

每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick),详见《时钟管理》章节。假设有 2 个优先级相同的就绪态线程 A 与 B,A 线程的时间片设置为 10,B 线程的时间片设置为 5,那么当系统中不存在比 A 优先级高的就绪态线程时,系统会在 A、B 线程间来回切换执行,并且每次对 A 线程执行 10 个节拍的时长,对 B 线程执行 5 个节拍的时长,如下图。

41087154-4f44-11ed-a3b6-dac502259ad0.png

线程通过调用函数 rt_thread_create/init() 进入到初始状态(RT_THREAD_INIT);

初始状态的线程通过调用函数 rt_thread_startup() 进入到就绪状态(RT_THREAD_READY);

就绪状态的线程被调度器调度后进入运行状态(RT_THREAD_RUNNING);当处于运行状态的线程调用 rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时,将进入到挂起状态(RT_THREAD_SUSPEND);

处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。挂起状态的线程,如果调用 rt_thread_delete/detach() 函数,将更改为关闭状态(RT_THREAD_CLOSE);

而运行状态的线程,如果运行结束,就会在线程的最后部分执行 rt_thread_exit() 函数,将状态更改为关闭状态。

线程相关的API

创建和删除线程

一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:

rt_thread_trt_thread_create(constchar*name,
void(*entry)(void*parameter),
void*parameter,
rt_uint32_tstack_size,
rt_uint8_tpriority,
rt_uint32_ttick);

调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照 rtconfig.h 中配置的 RT_ALIGN_SIZE 方式对齐。线程创建 rt_thread_create() 的参数和返回值见下图:

41173c8e-4f44-11ed-a3b6-dac502259ad0.png

对于一些使用 rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:

rt_err_trt_thread_delete(rt_thread_tthread);
4163103c-4f44-11ed-a3b6-dac502259ad0.png

初始化和脱离线程

线程的初始化可以使用下面的函数接口完成,来初始化静态线程对象:

rt_err_trt_thread_init(structrt_thread*thread,
constchar*name,
void(*entry)(void*parameter),void*parameter,
void*stack_start,rt_uint32_tstack_size,
rt_uint8_tpriority,rt_uint32_ttick);

静态线程的线程句柄(或者说线程控制块指针)、线程栈由用户提供。静态线程是指线程控制块、线程运行栈一般都设置为全局变量,在编译时就被确定、被分配处理,内核不负责动态分配内存空间。需要注意的是,用户提供的栈首地址需做系统对齐(例如 ARM 上需要做 4 字节对齐)。线程初始化接口 rt_thread_init() 的参数和返回值见下表:

417ab426-4f44-11ed-a3b6-dac502259ad0.png

对于用 rt_thread_init() 初始化的线程,使用 rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:

rt_err_trt_thread_detach(rt_thread_tthread);
41b0b6b6-4f44-11ed-a3b6-dac502259ad0.png

启动线程

创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化 / 创建成功后调用下面的函数接口让该线程进入就绪态:

rt_err_trt_thread_startup(rt_thread_tthread);
41e9f552-4f44-11ed-a3b6-dac502259ad0.png

...还有其他一些线程API,就不再一一赘述了,可以在RT-Thread官网查看

创建任务

上面对线程的介绍,罗里吧嗦的说了一大堆,接下来一起实战来看看,如何创建并运行任务

创建任务实现多任务点灯

根据创建任务的API

rt_thread_trt_thread_create(constchar*name,
void(*entry)(void*parameter),
void*parameter,
rt_uint32_tstack_size,
rt_uint8_tpriority,
rt_uint32_ttick);

来创建我们的2个任务:

/**
******************************************************************************
*@filert_user_task.c
*@brief用户任务文件
*
******************************************************************************
*@attention
*
* Copyright (c) 2022 公众号:小飞哥玩嵌入式.
*Allrightsreserved.
* Author:小飞哥
*
*****************************************************************************/

/*Includes------------------------------------------------------------------*/
#include"main.h"
#include
#include"rt_user_task.h"
/*Privatetypedef-----------------------------------------------------------*/

/*Privatedefine------------------------------------------------------------*/
#defineTHREAD1_PRIORITY27//线程
#defineTHREAD_STACK_SIZE512//线程栈深度
#defineTHREAD_TIMESLICE5//线程的时间片


#defineTHREAD2_PRIORITY26//线程
/*Privatemacro-------------------------------------------------------------*/

/*Privatevariables---------------------------------------------------------*/

/*Privatefunctionprototypes-----------------------------------------------*/

/*Privateusercode---------------------------------------------------------*/

/**
*@functionrt_ledflash_entry
*@author:小飞哥玩嵌入式-小飞哥
*@TODO:LED控制线程
*@param:
*@return:NULL
*/
staticvoidrt_led1_flash_entry(void*parameter)
{
for(;;)
{
HAL_GPIO_TogglePin(Y_LED_GPIO_Port,Y_LED_Pin);
rt_kprintf("LED1TaskisRunning!
");
rt_thread_mdelay(500);
}
}
/**
*@functionrt_led2flash_entry
*@author:小飞哥玩嵌入式-小飞哥
*@TODO:LED控制线程
*@param:
*@return:NULL
*/
staticvoidrt_led2_flash_entry(void*parameter)
{
for(;;)
{
HAL_GPIO_TogglePin(CP_LED_GPIO_Port,CP_LED_Pin);
rt_kprintf("LED2TaskisRunning!
");
rt_thread_mdelay(500);
}
}
/**
*@functionrt_user_thread_entry
*@author:小飞哥玩嵌入式-小飞哥
*@TODO:创建线程
*@param:
*@return:NULL
*/

intrt_user_thread_entry(void)
{
staticrt_thread_tresult=RT_NULL;
/*创建一个线程,名称是rt_ledflash,入口是rt_ledflash_entry*/
result=rt_thread_create("rt_led1flash",rt_led1_flash_entry,
NULL,
THREAD_STACK_SIZE,
THREAD1_PRIORITY,
THREAD_TIMESLICE);
if(result!=RT_NULL)//线程创建成功
{
rt_thread_startup(result);
}
else
{
rt_kprintf("
rt_led1flashthreadcreatefailed
");
}
/*创建一个线程,名称是rt_ledflash,入口是rt_ledflash_entry*/
result=rt_thread_create("rt_led2flash",rt_led2_flash_entry,
NULL,
THREAD_STACK_SIZE,
THREAD2_PRIORITY,
THREAD_TIMESLICE);
if(result!=RT_NULL)//线程创建成功
{
rt_thread_startup(result);
}
else
{
rt_kprintf("
rt_led2flashthreadcreatefailed
");
}
return0;
}

上面创建了两个任务,rt-thread任务的数值越小优先级是越高的,我们设置任务1的优先级为27,任务2的优先级为26,按照优先级设置规则,任务2的优先级是比较高的,接下来我们通过打印的方式(LED就不展示啦)来看看是不是按照我们的优先级去执行,可以看到,任务2的优先级是比较任务1高的

4203e6b0-4f44-11ed-a3b6-dac502259ad0.png

然后我们测试下同一个优先级情况下会发生什么,不出意外的话,应该是先执行先创建的任务,下图也可以看到,确实如此

423ad0da-4f44-11ed-a3b6-dac502259ad0.png

至此,本节教程就完了,讲的还是比较粗略的,LED就不展示啦,希望对小伙们有所帮助哈!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    237

    文章

    22450

    浏览量

    645890
  • RT-Thread
    +关注

    关注

    31

    文章

    1149

    浏览量

    38896
  • HAL
    HAL
    +关注

    关注

    2

    文章

    68

    浏览量

    12472
  • CubeMx
    +关注

    关注

    0

    文章

    28

    浏览量

    1212

原文标题:02-rt-thread 任务创建与HAL库点灯

文章出处:【微信号:小飞哥玩嵌入式,微信公众号:小飞哥玩嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    转:STM32CubeMX的安装及其首次使用注意事项

    和STM32CubeMX软件及其相关所有文档百度云下载地址:链接。1.1STM32CubeMX的安装1.2STM32CubeMX首次使用方法及其注意事项
    发表于 09-09 11:23

    HALGPIO使用注意事项

    [tr=transparent]stm32资料 STM32l05x HAL使用注意事项 主讲人:成冲 一、STM32L0xx_HAL_GPIO (一)、引脚初始化函数
    发表于 07-02 07:05

    示波器测量注意事项是是什么?

    上升时间的定义是什么?示波器测量注意事项是是什么?
    发表于 05-07 06:06

    讲解GPIO的API使用和注意事项

    第17章 STM32F429之GPIOHALAPI本章教程为大家讲解GPIO(General-purpose I/Os)的API使用和注意事项
    发表于 08-10 06:19

    Simulink开发STM32环境配置注意事项

    的是2018bSTM32MATJavaSTM32CubeMX,我下载的是5.3版本STM32F1注意是用于STM32CubeMX,不是Keil,可以
    发表于 08-17 06:07

    基于CubeMX HAL的CAN该如何去配置

    基于CubeMX HAL的CAN该如何去配置呢?使用时有哪些注意事项
    发表于 10-22 06:58

    GPIO口的配置过程是怎样的?有哪些注意事项

    GPIO口具有哪些特性功能?GPIO口的配置过程是怎样的?有哪些注意事项
    发表于 11-18 07:52

    请问使用stm32cubemx时有哪些注意事项

    请问使用stm32cubemx时有哪些注意事项
    发表于 11-25 06:06

    GPIO的API该如何去使用呢?有哪些注意事项

    GPIO的API该如何去使用呢?有哪些注意事项?如何使用HALGPIO驱动呢?
    发表于 11-29 06:41

    STM32CubeMXHAL对F103和F411的GPIO配置和使用方法

    文章目录STM32CubeMX第一章GPIO前言一、GPIO的工作模式二、使用步骤1.引入库2.读入数据总结前言  本文使用STM32CubeMX
    发表于 01-26 06:28

    STM32CubeMX图形化配置软件怎么使用?有哪些注意事项

    STM32CubeMX图形化配置软件怎么使用?有哪些注意事项
    发表于 02-14 06:13

    请问GPIO使用注意事项有哪些?

    GPIO使用注意事项
    发表于 06-21 06:03

    MCU的SWD端口复用为GPIO端口功能的配置方法及注意事项详细说明

    本篇应用笔记主要介绍华大半导体 MCU*的 SWD 端口复用为 GPIO 端口功能的配置方法及注意事项
    发表于 11-12 08:00 14次下载
    MCU的SWD端口复用为<b class='flag-5'>GPIO</b>端口功能的<b class='flag-5'>配置</b>方法及<b class='flag-5'>注意事项</b>详细说明

    AN092GD32MCU GPIO结构与使用注意事项

    AN092 GD32 MCU GPIO结构与使用注意事项
    发表于 03-01 18:48 0次下载
    AN092GD32MCU <b class='flag-5'>GPIO</b>结构与使用<b class='flag-5'>注意事项</b>

    SysTick与HAL_Delay的关系与注意事项

    本文将介绍SysTick与HAL_Delay()函数之间的关系,以及使用HAL_Delay()函数的注意事项
    的头像 发表于 04-21 11:32 1095次阅读