Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread Nano
packages_软件包
PIN_GPIO通用驱动
RT-Thread Nano PIN设备接口及对接RTT软件包
发布于 2021-08-24 10:15:35 浏览:3217
订阅该版
[tocm] # RT-Thread Nano PIN设备接口及对接RTT软件包 本文介绍了如何在 RT-Thread Studio 上使用 RT-Thread Nano,并基于BearPI-IOT STM32L431RCT6的基础工程进行讲解如何使用PIN设备接口及相关软件包使用。 ![bearpi.png](https://oss-club.rt-thread.org/uploads/20210824/0d7a0df7edd99addcb402af41c70235f.png.webp) ## 为什么需要设备接口 1. RT-Thread 分为标准版本和 Nano 版本,其特点如下: - RT-Thread 标准版:拥有设备驱动框架,软件包等组件,软件包都是基于设备驱动接口来实现。 - RT-Thread Nano:仅仅只是一个 RTOS 内核。没有任何组件。 2. Nano 是无法直接使用 RT-Thread 丰富软件包功能。 3. Nano 是一个面向低资源的 MCU 等芯片,不可能增加如同标准版的设备驱动框架。 4. Nano 需要一套统一设备驱动 API ,屏蔽不同芯片的 HAL 层的区别。方便移植工程到不同的平台。 4. Nano 需要一套设备驱动 API ,可以方便使用丰富软件包组件。 ## 准备工作 1. 使用 RT-Thread Studio 建立一个 STM32L431RCT6 的 RT-Thread Nano 基础工程。 2. 基础工程创建可参考:[在 RT-Thread Studio 上使用 RT-Thread Nano](../../nano-port-studio/an0047-nano-port-studio.md) ## PIN 设备接口 1. 在 RT-Thread 标准版中,[PIN设备](../../../rt-thread-standard/programming-manual/device/pin/pin.md)设备提供了一套设备管理接口来访问 GPIO,用户程序可以直接使用该 API 操作 GPIO 的功能,设备管理接口如下: | **函数** | **描述** | | ---------------- | ---------------------- | | rt_pin_get() | 获取引脚编号 | | rt_pin_mode() | 设置引脚模式 | | rt_pin_write() | 设置引脚电平 | | rt_pin_read() | 读取引脚电平 | | rt_pin_attach_irq() | 绑定引脚中断回调函数 | | rt_pin_irq_enable() | 使能引脚中断 | | rt_pin_detach_irq() | 脱离引脚中断回调函数 | 2. RT-Thread 丰富软件包都是基于这套 API 进行开发适配,所以 Nano 也需要一套这样子的 API。在 PIN 设备接口,可以完全沿用标准版的这套API。 ## 适配 PIN 设备接口 1. 复制 RT-Thread 完整版工程中的 pin.h 文件(路径:rt-thread\components\drivers\include\drivers\pin.h)到我们准备好的 STM32L431RCT6 的 RT-Thread Nano 基础工程中。 2. 由于 RT-Thread Nano 没有驱动框架,所以我们要把 pin.h 中有关完整版的内容去掉。整理完之后的 pin.h 文件如下: ```C /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-08-21 RiceChen the first version */ #ifndef PIN_H__ #define PIN_H__ #include
#ifdef __cplusplus extern "C" { #endif #define PIN_LOW 0x00 #define PIN_HIGH 0x01 #define PIN_MODE_OUTPUT 0x00 #define PIN_MODE_INPUT 0x01 #define PIN_MODE_INPUT_PULLUP 0x02 #define PIN_MODE_INPUT_PULLDOWN 0x03 #define PIN_MODE_OUTPUT_OD 0x04 #define PIN_IRQ_MODE_RISING 0x00 #define PIN_IRQ_MODE_FALLING 0x01 #define PIN_IRQ_MODE_RISING_FALLING 0x02 #define PIN_IRQ_MODE_HIGH_LEVEL 0x03 #define PIN_IRQ_MODE_LOW_LEVEL 0x04 #define PIN_IRQ_DISABLE 0x00 #define PIN_IRQ_ENABLE 0x01 #define PIN_IRQ_PIN_NONE -1 struct rt_device_pin_mode { rt_uint16_t pin; rt_uint16_t mode; }; struct rt_device_pin_status { rt_uint16_t pin; rt_uint16_t status; }; struct rt_pin_irq_hdr { rt_int16_t pin; rt_uint16_t mode; void (*hdr)(void *args); void *args; }; void rt_pin_mode(rt_base_t pin, rt_base_t mode); void rt_pin_write(rt_base_t pin, rt_base_t value); int rt_pin_read(rt_base_t pin); rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args); rt_err_t rt_pin_detach_irq(rt_int32_t pin); rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled); /* Get pin number by name,such as PA.0,P0.12 */ rt_base_t rt_pin_get(const char *name); #ifdef __cplusplus } #endif #endif ``` 3. 我们需要适配如上7个 PIN 设备 API ,参考实例: - drv_gpio.c: ```C /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-08-21 RiceChen the first version */ #include
#include "pin.h" #include "drv_gpio.h" #ifdef RT_USING_PIN #define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu))) #define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu)) #define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) #define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin)))) #define PIN_STPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) #define __STM32_PORT_MAX 8u #define PIN_STPORT_MAX __STM32_PORT_MAX static const struct pin_irq_map pin_irq_map[] = { {GPIO_PIN_0, EXTI0_IRQn}, {GPIO_PIN_1, EXTI1_IRQn}, {GPIO_PIN_2, EXTI2_IRQn}, {GPIO_PIN_3, EXTI3_IRQn}, {GPIO_PIN_4, EXTI4_IRQn}, {GPIO_PIN_5, EXTI9_5_IRQn}, {GPIO_PIN_6, EXTI9_5_IRQn}, {GPIO_PIN_7, EXTI9_5_IRQn}, {GPIO_PIN_8, EXTI9_5_IRQn}, {GPIO_PIN_9, EXTI9_5_IRQn}, {GPIO_PIN_10, EXTI15_10_IRQn}, {GPIO_PIN_11, EXTI15_10_IRQn}, {GPIO_PIN_12, EXTI15_10_IRQn}, {GPIO_PIN_13, EXTI15_10_IRQn}, {GPIO_PIN_14, EXTI15_10_IRQn}, {GPIO_PIN_15, EXTI15_10_IRQn}, }; static struct rt_pin_irq_hdr pin_irq_hdr_tab[] = { {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, }; static uint32_t pin_irq_enable_mask = 0; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) rt_base_t stm32_pin_get(const char *name) { rt_base_t pin = 0; int hw_port_num, hw_pin_num = 0; int i, name_len; name_len = rt_strlen(name); if ((name_len < 4) || (name_len >= 6)) { return -RT_EINVAL; } if ((name[0] != 'P') || (name[2] != '.')) { return -RT_EINVAL; } if ((name[1] >= 'A') && (name[1] <= 'Z')) { hw_port_num = (int)(name[1] - 'A'); } else { return -RT_EINVAL; } for (i = 3; i < name_len; i++) { hw_pin_num *= 10; hw_pin_num += name[i] - '0'; } pin = PIN_NUM(hw_port_num, hw_pin_num); return pin; } void rt_pin_write(rt_base_t pin, rt_base_t value) { GPIO_TypeDef *gpio_port; uint16_t gpio_pin; if (PIN_PORT(pin) < PIN_STPORT_MAX) { gpio_port = PIN_STPORT(pin); gpio_pin = PIN_STPIN(pin); HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value); } } int rt_pin_read(rt_base_t pin) { GPIO_TypeDef *gpio_port; uint16_t gpio_pin; int value = PIN_LOW; if (PIN_PORT(pin) < PIN_STPORT_MAX) { gpio_port = PIN_STPORT(pin); gpio_pin = PIN_STPIN(pin); value = HAL_GPIO_ReadPin(gpio_port, gpio_pin); } return value; } void rt_pin_mode(rt_base_t pin, rt_base_t mode) { GPIO_InitTypeDef GPIO_InitStruct; if (PIN_PORT(pin) >= PIN_STPORT_MAX) { return; } /* Configure GPIO_InitStructure */ GPIO_InitStruct.Pin = PIN_STPIN(pin); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; if (mode == PIN_MODE_OUTPUT) { /* output setting */ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; } else if (mode == PIN_MODE_INPUT) { /* input setting: not pull. */ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; } else if (mode == PIN_MODE_INPUT_PULLUP) { /* input setting: pull up. */ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; } else if (mode == PIN_MODE_INPUT_PULLDOWN) { /* input setting: pull down. */ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; } else if (mode == PIN_MODE_OUTPUT_OD) { /* output setting: od. */ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; } HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct); } rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) { int i; for (i = 0; i < 32; i++) { if ((0x01 << i) == bit) { return i; } } return -1; } rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) { rt_int32_t mapindex = bit2bitno(pinbit); if (mapindex < 0 || mapindex >= ITEM_NUM(pin_irq_map)) { return RT_NULL; } return &pin_irq_map[mapindex]; }; rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) { rt_base_t level; rt_int32_t irqindex = -1; if (PIN_PORT(pin) >= PIN_STPORT_MAX) { return -RT_ENOSYS; } irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; } level = rt_hw_interrupt_disable(); if (pin_irq_hdr_tab[irqindex].pin == pin && pin_irq_hdr_tab[irqindex].hdr == hdr && pin_irq_hdr_tab[irqindex].mode == mode && pin_irq_hdr_tab[irqindex].args == args) { rt_hw_interrupt_enable(level); return RT_EOK; } if (pin_irq_hdr_tab[irqindex].pin != -1) { rt_hw_interrupt_enable(level); return RT_EBUSY; } pin_irq_hdr_tab[irqindex].pin = pin; pin_irq_hdr_tab[irqindex].hdr = hdr; pin_irq_hdr_tab[irqindex].mode = mode; pin_irq_hdr_tab[irqindex].args = args; rt_hw_interrupt_enable(level); return RT_EOK; } rt_err_t rt_pin_detach_irq(rt_int32_t pin) { rt_base_t level; rt_int32_t irqindex = -1; if (PIN_PORT(pin) >= PIN_STPORT_MAX) { return -RT_ENOSYS; } irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; } level = rt_hw_interrupt_disable(); if (pin_irq_hdr_tab[irqindex].pin == -1) { rt_hw_interrupt_enable(level); return RT_EOK; } pin_irq_hdr_tab[irqindex].pin = -1; pin_irq_hdr_tab[irqindex].hdr = RT_NULL; pin_irq_hdr_tab[irqindex].mode = 0; pin_irq_hdr_tab[irqindex].args = RT_NULL; rt_hw_interrupt_enable(level); return RT_EOK; } rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) { const struct pin_irq_map *irqmap; rt_base_t level; rt_int32_t irqindex = -1; GPIO_InitTypeDef GPIO_InitStruct; if (PIN_PORT(pin) >= PIN_STPORT_MAX) { return -RT_ENOSYS; } if (enabled == PIN_IRQ_ENABLE) { irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; } level = rt_hw_interrupt_disable(); if (pin_irq_hdr_tab[irqindex].pin == -1) { rt_hw_interrupt_enable(level); return RT_ENOSYS; } irqmap = &pin_irq_map[irqindex]; /* Configure GPIO_InitStructure */ GPIO_InitStruct.Pin = PIN_STPIN(pin); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; switch (pin_irq_hdr_tab[irqindex].mode) { case PIN_IRQ_MODE_RISING: GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; break; case PIN_IRQ_MODE_FALLING: GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; break; case PIN_IRQ_MODE_RISING_FALLING: GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; break; } HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct); HAL_NVIC_SetPriority(irqmap->irqno, 5, 0); HAL_NVIC_EnableIRQ(irqmap->irqno); pin_irq_enable_mask |= irqmap->pinbit; rt_hw_interrupt_enable(level); } else if (enabled == PIN_IRQ_DISABLE) { irqmap = get_pin_irq_map(PIN_STPIN(pin)); if (irqmap == RT_NULL) { return RT_ENOSYS; } level = rt_hw_interrupt_disable(); HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin)); pin_irq_enable_mask &= ~irqmap->pinbit; if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9)) { if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9))) { HAL_NVIC_DisableIRQ(irqmap->irqno); } } else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15)) { if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) { HAL_NVIC_DisableIRQ(irqmap->irqno); } } else { HAL_NVIC_DisableIRQ(irqmap->irqno); } rt_hw_interrupt_enable(level); } else { return -RT_ENOSYS; } return RT_EOK; } rt_inline void pin_irq_hdr(int irqno) { if (pin_irq_hdr_tab[irqno].hdr) { pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); } } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { pin_irq_hdr(bit2bitno(GPIO_Pin)); } void EXTI0_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); rt_interrupt_leave(); } void EXTI1_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); rt_interrupt_leave(); } void EXTI2_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); rt_interrupt_leave(); } void EXTI3_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); rt_interrupt_leave(); } void EXTI4_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); rt_interrupt_leave(); } void EXTI9_5_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); rt_interrupt_leave(); } void EXTI15_10_IRQHandler(void) { rt_interrupt_enter(); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); rt_interrupt_leave(); } int rt_hw_pin_init(void) { #if defined(__HAL_RCC_GPIOA_CLK_ENABLE) __HAL_RCC_GPIOA_CLK_ENABLE(); #endif #if defined(__HAL_RCC_GPIOB_CLK_ENABLE) __HAL_RCC_GPIOB_CLK_ENABLE(); #endif #if defined(__HAL_RCC_GPIOC_CLK_ENABLE) __HAL_RCC_GPIOC_CLK_ENABLE(); #endif #if defined(__HAL_RCC_GPIOE_CLK_ENABLE) __HAL_RCC_GPIOE_CLK_ENABLE(); #endif return RT_EOK; } #endif /* RT_USING_PIN */ ``` - drv_gpio.h: ```C /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-08-21 RiceChen the first version */ #ifndef __DRV_GPIO_H__ #define __DRV_GPIO_H__ #include
#include
#include "pin.h" #ifdef __cplusplus extern "C" { #endif #define __STM32_PORT(port) GPIO##port##_BASE #define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) struct pin_irq_map { rt_uint16_t pinbit; IRQn_Type irqno; }; #ifdef __cplusplus } #endif #endif /* __DRV_GPIO_H__ */ ``` ## 编写 PIN 设备使用示例 ```C * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-08-21 RT-Thread first version */ #include
#define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
#include "drv_gpio.h" #define LED0_PIN GET_PIN(C, 13) int main(void) { LOG_D("Hello RT-Thread!"); rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); for(;;) { rt_pin_write(LED0_PIN, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(500); } return RT_EOK; } ``` - 实例代码运行现象:板载的 LED 进行周期性闪烁。 ## PIN 设备相关软件包使用 1. 我们使用[LedBlink软件包](http://packages.rt-thread.org/detail.html?package=LedBlink)来验证PIN设备接口。 2. 首先克隆 LedBlink 软件包到 STM32L431RCT6 的 RT-Thread Nano 工程。LedBlink 软件包链接:https://github.com/aeo123/LedBlink.git 3. 使用 LedBlink 软件包实例: ```C #include
#define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
#include "drv_gpio.h" #include "ledblink.h" #define LED0_PIN GET_PIN(C, 13) int main(void) { int count = 1; LOG_D("Hello RT-Thread!"); led_add_device(LED0_PIN); while (count++) { led_on(1); rt_thread_mdelay(500); led_off(1); rt_thread_mdelay(500); } return RT_EOK; } ``` 4. LedBlink 软件包无需任何修改便可在 RT-Thread Nano 工程中使用。 5. 实例代码运行现象:板载的 LED 进行周期性闪烁。 ## 总结 - 通过适配PIN设备接口,我们可以无缝对接到软件包的使用。 - 对于低资源的芯片使用 Nano 并且能够使用 RT-THREAD 丰富的软件,无疑是一个非常完美的做法。也没有庞大的驱动框架。 - 通过这样的方式,学习完 RT-THREAD Nano 在转移到 RT-THREAD 标准版的学习,更加简单方便。 关注微信公众号『Rice嵌入式开发技术分享』,后台回复“微信”添加作者微信,备注”入群“,便可邀请进入技术交流群。 ![logo_.png](https://oss-club.rt-thread.org/uploads/20210824/83e4cc15725eb9ae5a53123db6441291.png.webp)
8
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
RiceChen
内核/软件架构/开源
文章
4
回答
27
被采纳
4
关注TA
发私信
相关文章
1
求高手指点,RTThread下nanosleep()函数功能如何实现?在线等啊
2
RTT1.2.2在新塘Nano130KE3BN的移植中始终出现栈溢出的问题
3
官方能否出一个nano在mdk下移植finsh到stm32的教程
4
从裸机开始,创建一个RT-Thread Nano系统工程
5
Nano版如何启用shell
6
项目从RTT 2.x NANO移植到 RTT 3.x ENV 环境
7
nano 版本有没有集成到 IAR 中啊?
8
关于MDK5的RT-THREAD NANO中添加MSH组件的例程
9
rtt_nano版本,源代码在哪里下载啊?
10
RTT Nano 在keil 使用C++11 的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
12
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
7
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部