Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
onenet
星火1号_spark_星火一号_开发板
【24嵌入式设计大赛】基于RT-Thread星火一号开发板的多功能智能家居系统
发布于 2024-09-09 18:24:26 浏览:594
订阅该版
#1、多功能智能家居系统简介 本系统主要使用外设情况如下: 1、SD卡挂载文件管理系统 2、AHT10温湿度传感器信息采集 3、AP3216C接近与光强传感器信息采集 4、RW007 wifi模块使用 5、RS485通讯 6、LED MATRIX矩阵灯使用 7、按键4个+LED小灯2个(分别模拟外置风机和电加热) 8、RTC时钟 9、LCD显示 本系统主要实现功能如下: RW007接入wifi后联接ONENET服务器,上报当前温度、湿度、光照强度、人感接近、手动控制情况、风机及电加热实际状态;实现ONENET云服务端的手动控制等内容。同时开发对应的微信小程序实现与ONENET相同的功能;RS485作为监控使用,可实现上述检测及控制功能;另外开发LCD+按键的简易菜单功能,实现人机交互;RTC实现LCD万年历显示,SD卡实现控制信息的记录功能,具体的示意图如下所示。 ![1.png](https://oss-club.rt-thread.org/uploads/20240909/6fa9ba1872155ac7ce7f40de28c49a3d.png.webp) 软件方面,共开启了10个线程,具体信息如下所示: ![2.png](https://oss-club.rt-thread.org/uploads/20240909/e94ac96cc10cf99985dd51455d1e8052.png.webp) #2、文件管理系统的使用 基于星火一号开发板建立标准工程后,使能文件管理系统,则自动开启SDIO等内容,具体配置如下图所示 ![3.jpg](https://oss-club.rt-thread.org/uploads/20240909/73dff5dd1c8e4097aa7fb0ccfa8a7cda.jpg.webp) ![4.png](https://oss-club.rt-thread.org/uploads/20240909/51c56c74b656a2cb0848ae21bcde4ac3.png) 本系统中,文件管理系统仅作为手动控制参数的存储作用,在main线程中进行数据的读取处理,读取完成后通过邮箱将参数传递到风机电加热控制线程中,具体代码如下: ```c int main(void) { fd = open("/sdcard/info.txt", O_RDWR | O_CREAT, 0); rt_thread_mdelay(1000); if (fd >= 0) { read(fd, &P_CTRL, 3); close(fd); } LOG_D("The last control content is : MANUAL:%d,FAN:%d,HEAT:%d", P_CTRL._MANUAL,P_CTRL._FAN,P_CTRL._HEAT); rt_mq_send(Ctrl_mq, /* 写入(发送)队列的 ID( 句柄) */ &P_CTRL, /* 写入(发送)的数据 */ sizeof(P_CTRL)); /* 数据的长度 */ return 0; } ``` #3、AHT10温湿度传感器的使用 使能AHT21功能后,RTTHREAD_STUDIO会自动打开软件包中的aht10功能,详细的配置内容如下: ![5.png](https://oss-club.rt-thread.org/uploads/20240909/c872ddbc43548eb885ce62f085e59961.png.webp) ![6.png](https://oss-club.rt-thread.org/uploads/20240909/0b15ab626d917d2dc54290fc7fd14cac.png.webp) 在TempHumGet_thread_entry线程中实现温度及湿度的采集,周期为1s,具体的代码如下: ```c void TempHumGet_thread_entry(void *parameter) { aht10_device_t dev; /* 等待传感器正常工作 */ rt_thread_mdelay(2000); /* 初始化 aht10 */ dev = aht10_init(i2c_bus_name); if (dev == RT_NULL) { LOG_E(" The sensor initializes failure"); return; } while (1) { /* 读取湿度 */ humidity = aht10_read_humidity(dev); /* 读取温度 */ temperature = aht10_read_temperature(dev); rt_thread_mdelay(1000); } } ``` #4、AP3216C接近与光强传感器的使用 同样的在硬件中使能AP3216C后,会自动开启相关的软件包,自这里之后不在过多赘述,详细的可以参照官方例程。Ap3216Read_thread_entry线程中的代码实现如下,周期同样为1s: ```c void Ap3216Read_thread_entry(void *parameter) { ap3216c_device_t dev; const char *i2c_bus_name = "i2c2"; /* 初始化 ap3216c */ dev = ap3216c_init(i2c_bus_name); if (dev == RT_NULL) { LOG_E("The sensor initializes failure."); return; } //创建邮箱 Ap_mail = rt_mb_create("mb", 2, RT_IPC_FLAG_FIFO); while (1) { /* 读接近感应值 */ ps_data = ap3216c_read_ps_data(dev); rt_mb_send(Ap_mail, ps_data); /* 读光照强度值 */ brightness = ap3216c_read_ambient_light(dev); rt_thread_mdelay(1000); } } ``` #5、RW007 wifi模块使用 在硬件中使能RW007后,会自动开启SPI2、SAL、lwip等功能。Wifi_Connect_thread线程中主要实现wifi的连接以及断线重联功能,详细的代码如下: ```c #define WLAN_SSID "自己的wifi账号" #define WLAN_PASSWORD "自己的wifi密码" #define NET_READY_TIME_OUT (rt_tick_from_millisecond(15 * 1000)) static int wifi_autoconnect(void); static struct rt_semaphore net_ready; void wlan_ready_handler(int event, struct rt_wlan_buff *buff, void *parameter) { rt_sem_release(&net_ready); } static void wlan_connect_handler(int event, struct rt_wlan_buff *buff, void *parameter) { rt_kprintf("%s\n", __FUNCTION__); if ((buff != RT_NULL) && (buff->len == sizeof(struct rt_wlan_info))) { rt_kprintf("ssid : %s \n", ((struct rt_wlan_info *)buff->data)->ssid.val); } } static void wlan_connect_fail_handler(int event, struct rt_wlan_buff *buff, void *parameter) { rt_kprintf("%s\n", __FUNCTION__); if ((buff != RT_NULL) && (buff->len == sizeof(struct rt_wlan_info))) { rt_kprintf("ssid : %s \n", ((struct rt_wlan_info *)buff->data)->ssid.val); } } void Wifi_Connect_thread(void *parameter) { int result = RT_EOK; struct rt_wlan_info info; /* 等待 500 ms 以便 wifi 完成初始化 */ rt_thread_mdelay(500); /* 热点连接 */ LOG_D("start to connect ap ..."); rt_sem_init(&net_ready, "net_ready", 0, RT_IPC_FLAG_FIFO); /* 注册 wlan ready 回调函数 */ rt_wlan_register_event_handler(RT_WLAN_EVT_READY, wlan_ready_handler, RT_NULL); /* 同步连接热点 */ result = rt_wlan_connect(WLAN_SSID, WLAN_PASSWORD); if (result == RT_EOK) { rt_memset(&info, 0, sizeof(struct rt_wlan_info)); /* 等待成功获取 IP */ result = rt_sem_take(&net_ready, NET_READY_TIME_OUT); if (result == RT_EOK) { LOG_D("networking ready!"); rt_thread_mdelay(50); ntp_sync_to_rtc(RT_NULL); } else { LOG_D("wait ip got timeout!"); } /* 回收资源 */ rt_wlan_unregister_event_handler(RT_WLAN_EVT_READY); rt_sem_detach(&net_ready); } else { LOG_E("The AP(%s) is connect failed!", WLAN_SSID); } while(1) { if(rt_wlan_is_connected() == RT_FALSE) { wifi_autoconnect(); } rt_thread_mdelay(5000); } } static int wifi_autoconnect(void) { /* Configuring WLAN device working mode */ rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION); /* Start automatic connection */ rt_wlan_config_autoreconnect(RT_TRUE); /* register event */ rt_wlan_register_event_handler(RT_WLAN_EVT_STA_CONNECTED, wlan_connect_handler, RT_NULL); rt_wlan_register_event_handler(RT_WLAN_EVT_STA_CONNECTED_FAIL, wlan_connect_fail_handler, RT_NULL); return 0; } ``` 注意这两个宏WLAN_SSID和WLAN_PASSWORD #6、RS485通信 RS485连接在开发板的UART6上(RX:PG9,TX:PG14),发送接收使能脚为PG8(端口号为104),具体的工程配置如下: ![8.jpg](https://oss-club.rt-thread.org/uploads/20240909/6c3f4af5776fa47140620d399f75a172.jpg.webp) 这里采用从机模式,只使用保持寄存器即可,详细的配置在程序内有注释说明,FREEMODBUS通讯需要开启两个线程,一个是mb_slave_poll即modbus通讯的主体函数,另外一个是打包函数send_thread_entry,详细的代码如下: ```c #define SLAVE_ADDR 0x01 #define PORT_NUM 6 #define PORT_BAUDRATE 115200 #define PORT_PARITY MB_PAR_EVEN #define MB_POLL_CYCLE_MS 200 extern USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS]; void MODBUS_CMD(USHORT * BUFCMD) { P_CTRL._MANUAL = BUFCMD[6]; P_CTRL._FAN = BUFCMD[7]; P_CTRL._HEAT = BUFCMD[8]; rt_mq_send(Ctrl_mq, /* 写入(发送)队列的 ID( 句柄) */ &P_CTRL, /* 写入(发送)的数据 */ sizeof(P_CTRL)); /* 数据的长度 */ } void send_thread_entry(void *parameter) { USHORT *usRegHoldingBuf; usRegHoldingBuf = usSRegHoldBuf; rt_base_t level; while (1) { /* Test Modbus Master */ level = rt_hw_interrupt_disable(); usRegHoldingBuf[0] = (USHORT)(temperature*10); //温度 精度0.1 usRegHoldingBuf[1] = (USHORT)(humidity*10); //湿度 精度0.1 usRegHoldingBuf[2] = (USHORT)brightness; //光照 精度1 usRegHoldingBuf[3] = (USHORT)((ps_data>342)?(1):(0));//有无人靠近 usRegHoldingBuf[4] = (USHORT)FAN; //风机状态 usRegHoldingBuf[5] = (USHORT)HEAT; //电加热状态 usRegHoldingBuf[6] = (USHORT)P_CTRL._MANUAL; //手动控制状态 usRegHoldingBuf[7] = (USHORT)P_CTRL._FAN; //手动风机状态 usRegHoldingBuf[8] = (USHORT)P_CTRL._HEAT; //手动电加热状态 rt_hw_interrupt_enable(level); rt_thread_mdelay(1000); } } void mb_slave_poll(void *parameter) { eMBInit(MB_RTU, SLAVE_ADDR, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); eMBEnable(); while (1) { eMBPoll(); rt_thread_mdelay(MB_POLL_CYCLE_MS); } } ``` 注意:FREEMODBUS默认为偶检验,如果需要更改,请自行替换相关宏定义,另外void MODBUS_CMD(USHORT * BUFCMD)函数为获取控制信息使用的函数,需要插入在eMBRegHoldingCB函数的写操作后,具体的代码内容如下: ```c eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode) { eMBErrorCode eStatus = MB_ENOERR; USHORT iRegIndex; USHORT * pusRegHoldingBuf; USHORT REG_HOLDING_START; USHORT REG_HOLDING_NREGS; USHORT usRegHoldStart; pusRegHoldingBuf = usSRegHoldBuf; REG_HOLDING_START = S_REG_HOLDING_START; REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; usRegHoldStart = usSRegHoldStart; /* it already plus one in modbus function method. */ usAddress--; if ((usAddress >= REG_HOLDING_START) && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) { iRegIndex = usAddress - usRegHoldStart; switch (eMode) { /* read current register values from the protocol stack. */ case MB_REG_READ: while (usNRegs > 0) { *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); iRegIndex++; usNRegs--; } break; /* write current register values with new values from the protocol stack. */ case MB_REG_WRITE: while (usNRegs > 0) { pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; iRegIndex++; usNRegs--; } MODBUS_CMD(pusRegHoldingBuf); break; } } else { eStatus = MB_ENOREG; } return eStatus; } ``` #7、LED MATRIX矩阵灯使用 在硬件配置中使能LED matrix后,会自动开启timer3的PWM3通道2,用来模拟数据使用,LED matrix采用19个SC6805RGB三色灯驱动,详细的驱动内容可以自动百度,这里不做赘述。本项目中,LED matrix仅用于显示接近传感器的检测强度即人感灯效功能,当距离传感器检测值小于150时,全部熄灭认为无人靠近;当距离传感器检测值大于150后,认为有人靠近;有人靠近时,检测值在342以下亮白色,检测值在683以下亮蓝色,其他为红色。具体代码实现如下: ```c void LedMatrix_entry(void *parameter) { rt_uint16_t PS_DATA = 0; pixel_rgb_t Light = WHITE; led_matrix_clear(); //等待AP3216初始化完成 rt_thread_mdelay(2000); while (1) { if (rt_mb_recv(Ap_mail, (rt_uint32_t *)&PS_DATA, RT_WAITING_FOREVER) == RT_EOK) { if (PS_DATA < 150) { Light = DARK; } else if(PS_DATA < 342){ Light = WHITE; } else if (PS_DATA < 683){ Light = BLUE; } else { Light = RED; } for (int i = EXTERN_LED_0; i <= EXTERN_LED_18; i++) { led_matrix_set_color(i, Light); } led_matrix_reflash(); } } } ``` #8、按键4个+LED小灯2个 基本的引脚输入输出检测,其中4个按键与LCD组合实现简单的菜单选择功能,绿色的小灯模拟外置风机,红色的小灯模拟外置电加热。在自动运行状态改下,当环境温度在25℃以上时,风机开启,直至温度降为10℃以下关闭风机;当环境温度在5℃以下,电加热开启,直至温度升温至20℃以上关闭电加热;在手动模式下,根据具体的控制内容实现,详细的代码实现内容如下: ```c /* 配置 LED 灯引脚 */ #define PIN_FAN GET_PIN(F, 11) // PF11 : LED_B --> FAN #define PIN_HEAT GET_PIN(F, 12) // PF12 : LED_R --> HEAT void FanHeatCtrl_entry(void *parameter) { CTRL_PARAM P_buf; rt_err_t res; static rt_uint8_t FanSts = 0,HeatSts = 0; /* 设置 RGB 灯引脚为输出模式 */ rt_pin_mode(PIN_FAN, PIN_MODE_OUTPUT); rt_pin_mode(PIN_HEAT, PIN_MODE_OUTPUT); rt_pin_write(PIN_FAN, 1); rt_pin_write(PIN_HEAT, 1); Ctrl_mq = rt_mq_create("test_mq", /* 消息队列名字 */ 3, /* 消息的最大长度 */ 5, /* 消息队列的最大容量 */ RT_IPC_FLAG_FIFO);/* 队列模式 FIFO(0x00)*/ /* 等待传感器正常工作 */ rt_thread_mdelay(3000); while(1) { res = rt_mq_recv(Ctrl_mq, &P_buf, sizeof(P_buf), 500); //云服务手动控制逻辑 if (res == RT_EOK) { if(P_buf._MANUAL == 0) { FAN = 0; HEAT = 0; } else { FAN = P_buf._FAN; HEAT = P_buf._HEAT; } fd = open("/sdcard/info.txt", O_WRONLY, 0); if (fd >= 0) { write(fd, &P_CTRL, 3); close(fd); } } //通常控制 else if ((res == -RT_ETIMEOUT)&&(P_buf._MANUAL == 0)){ //大于25摄氏度开风机 if(FanSts == 0) { if(temperature > 25) { FanSts = 1; } } else { //回差15度 if(temperature < 10) { FanSts = 0; } } FAN = FanSts; if(HeatSts == 0) { if(temperature < 5) { HeatSts = 1; } } else { //回差15度 if(temperature > 20) { HeatSts = 0; } } HEAT = HeatSts; } rt_pin_write(PIN_FAN, 1 - FAN); rt_pin_write(PIN_HEAT, 1 - HEAT); } } ``` 程序中,邮箱数据为控制参数内容,采用超时接收的形式实现自动(周期500ms)、手动控制。每接收到一次手动控制指令就存储一次SD卡数据。 #9、RTC时钟 在硬件中使能硬件RTC,时钟源选择LSE(外部低速),RTC作为LCD主界面的万年历使用,在wifi连接成功并获取IP地址后,获取网络时间,这里还需要开启netutils软件包,具体的配置见下图: ![10.png](https://oss-club.rt-thread.org/uploads/20240909/9182d292ccecfccd5dfb41c37fab6a05.png.webp) ntp_sync_to_rtc函数的调用在Wifi_Connect_thread线程中,详细内容如下: ![11.png](https://oss-club.rt-thread.org/uploads/20240909/45d7c65ea0f2e3927b2f49afaafe369b.png) #10、LCD使用 在硬件中使能LCD即可,不开启LVGL(开启WIFI功能后内存不大够用),采用与按键组合的形式实现基本的菜单功能,具体的代码如下: ```c /* 配置 KEY 输入引脚 */ #define KEY2 GET_PIN(C, 0) // PC0: KEY0 --> KEY_LEFT #define KEY1 GET_PIN(C, 1) // PC1 : KEY1 --> KEY_DOWN #define KEY3 GET_PIN(C, 4) // PC4 : KEY2 --> KEY_RIGHT #define KEY0 GET_PIN(C, 5) // PC5: WK_UP --> KEY_UP static void LCD_ORIGIN_SCREEN(void) { lcd_clear(WHITE); /* show RT-Thread logo */ lcd_show_image(0, 0, 240, 69, image_rttlogo); /* set the background color and foreground color */ lcd_set_color(WHITE, BLACK); /* show some string on lcd */ lcd_show_string(10, 69, 16, "Hello, RT-Thread!"); /* draw a line on lcd */ lcd_draw_line(0, 69 + 17, 240, 69 + 17); } void (*current_func_show)(); void LCDShow_thread_entry(void *parameter) { rt_uint8_t func = 0,funcbak = 0; rt_pin_mode(KEY0, PIN_MODE_INPUT_PULLUP); rt_pin_mode(KEY1, PIN_MODE_INPUT_PULLUP); rt_pin_mode(KEY2, PIN_MODE_INPUT_PULLUP); rt_pin_mode(KEY3, PIN_MODE_INPUT_PULLUP); LCD_ORIGIN_SCREEN(); /* 等待传感器正常工作 */ rt_thread_mdelay(3000); while(1) { if( (rt_pin_read(KEY0) == 0)||(rt_pin_read(KEY1) == 0) ||(rt_pin_read(KEY2) == 0)||(rt_pin_read(KEY3) == 0)) { rt_thread_mdelay(5); if(rt_pin_read(KEY0) == 0) { func = table[func].UpMenu; while(rt_pin_read(KEY0) == 0); } else if(rt_pin_read(KEY1) == 0) { func = table[func].DownMenu; while(rt_pin_read(KEY1) == 0); } else if(rt_pin_read(KEY2) == 0) { func = table[func].LastMenu; while(rt_pin_read(KEY2) == 0); } else if(rt_pin_read(KEY3) == 0) { func = table[func].EnterMenu; while(rt_pin_read(KEY3) == 0); } } if(funcbak != func) { //擦除显示区域 lcd_clear(WHITE); LCD_ORIGIN_SCREEN(); funcbak = func; } current_func_show = table[func].current_show; (*current_func_show)(); rt_thread_mdelay(50); } } ``` 按键UP为上一菜单、按键DOWN为下一菜单、按键左为返回上一级菜单、按键右为进入选择项。 主界面菜单显示万年历,二级菜单为功能选择,分别为: 1、温度、湿度、光照强度显示;进入菜单后可以查看当前环境温度、湿度以及光照强度,其中温度在低于0℃时会显示为红色字体,当湿度不在20%到90%之间时会显示红色字体,其他时刻为蓝色; 2、运行状态显示,进入菜单后可以查看当前手动控制状态以及实际部件运行状态; 3、控制状态设定,进入菜单后可以使能/失能手动控制、风机控制以及电加热控制; 详细的菜单功能见工程文件及视屏。 #11、onenet云平台 1、云平台配置 ![9.jpg](https://oss-club.rt-thread.org/uploads/20240909/d997d8ac26e8dfc0d3cdd5a1ce7546c2.jpg.webp) 这里注意,使能onenet云平台后,会自动关联pahomqtt、cjson包,还要自动开启组件下的旧版本兼容性支持。另外可能是onenet云平台升级的原因,现在last版本支持的是新onenet平台,我这里onenet用的多协议接入的老平台,需要选择软件包为V1.0.0,但是使能后缺少了两个重要的宏参数,一个是ONENET_INFO_APIKEY,一个是ONENET_MASTER_APIKEY,这两个需要自己在rtconfig中增加,详细的内容如下: ```c #define ONENET_INFO_DEVID "自己的设备ID" #define ONENET_INFO_AUTH "自己的设备密匙" #define ONENET_INFO_PROID "自己的产品ID" #define ONENET_INFO_APIKEY "自己的APIKEY" #define ONENET_MASTER_APIKEY "自己的MASTERKEY" ``` onenet的连接方式,论坛里一大堆,这里不过多赘述,大家跟着步骤走即可。 2、微信小程序实现 微信小程序采用java开发,采用HTTP的形式连接onenet实现相关参数的监听及控制,界面效果如下,这里不过多描述。 ![11.png](https://oss-club.rt-thread.org/uploads/20240909/0123f8826749850f4af12c162995af53.png) #12、软件工程及演示 工程:[点灯大师-24rtthread](https://gitee.com/werper/24rtthread.git "点灯大师-24rtthread") 演示: [上电初始化展示](https://www.bilibili.com/video/BV1qQpneMEo3/ "上电初始化展示") [LCD菜单展示](https://www.bilibili.com/video/BV1ZQpneMEwD/ "LCD菜单展示") [人感展示](https://www.bilibili.com/video/BV1qQpneMEpn/ "人感展示") [小程序控制展示](https://www.bilibili.com/video/BV1BQpneMEFe/ "小程序控制展示") [onenet网页查询控制展示](https://www.bilibili.com/video/BV1BQpneuE6j/?vd_source=3aa37c29db19183d6db0d3ce09c90e0e "onenet网页查询控制展示") [MODBUS监控及控制展示](https://www.bilibili.com/video/BV1wCpneyExn/?vd_source=3aa37c29db19183d6db0d3ce09c90e0e "MODBUS监控及控制展示") #13、注意事项 1、CubeMX_Config下的源码直接替换,有很多工程配置需要自己处理,文章中没有特别说明,本来对于引脚的配置就是一名嵌入式工程师的基本功,不做过多赘述。 2、rtconfig.h中缺少onenet配置信息宏,需要自己补齐,详见第11节 3、wifi账号密码需要填写实际值,详见第5节 4、微信小程序用的HTTP协议,里面的设备ID请根据实际情况填写。 #14、总结 该系统的底层程序基本上没有自己动手去编写,仅仅是通过官方例程或者论坛文章进行修改重组,足以说明RT-Thread Studio进行小项目的开发是十分便捷的,一如当年初见的感觉。唯一不足的地方是onenet软件包升级后缺少了两个宏定义纠结了一段时间,希望官方可以看到并整改。 因本人水平有限,文章内容及代码中可能会出现错误,还请谅解。
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
werper
叫我点灯大师
文章
9
回答
15
被采纳
1
关注TA
发私信
相关文章
1
studio中onenet包使能自动注册设备功能,编译缺少代码
2
rt-thread如何上传GPS的经纬度到onenet?
3
MQTT 在“ read 0:1, break “后断开重连
4
ONENET+esp8266连接报错
5
有哪位实现了ONENET包获取onenet数据源数据吗
6
请问一下使用BC26对接ONENET的步骤是什么呀
7
AT Client receive failed???
8
onenet示例程序运行异常
9
如何使用OneNet软件包上传2个以上数据流
10
OneNET 浮点数据上传,但小数部分却被截掉
推荐文章
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
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
3
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部