Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
PM电源管理
PM组件适配STM32F0/F1/F2/F3/F4/F7/G0/G4/L0/L1/L4/H7
发布于 2020-03-26 16:48:03 浏览:4394
订阅该版
PM组件适配`STM32F0/F1/F2/F3/F4/F7/G0/G4/L0/L1/L4/H7` 现在还只测试了部分系列(因为有些没有开发板),希望大家下载测试,完美后再提交PR。 项目地址:https://gitee.com/sunwancn/rt-thread/tree/pm-for-stm32/ 修改了下面的一些文件:`bsp/stm32/libraries/HAL_Drivers/drv_pm.c` ``` bsp/stm32/libraries/HAL_Drivers/drv_lptim.c bsp/stm32/libraries/HAL_Drivers/drv_lptim.h bsp/stm32/libraries/HAL_Drivers/SConscript bsp/stm32/libraries/STM32F0xx_HAL/SConscript bsp/stm32/libraries/STM32F1xx_HAL/SConscript bsp/stm32/libraries/STM32F2xx_HAL/SConscript bsp/stm32/libraries/STM32F4xx_HAL/SConscript bsp/stm32/libraries/STM32F7xx_HAL/SConscript bsp/stm32/libraries/STM32G0xx_HAL/SConscript bsp/stm32/libraries/STM32G4xx_HAL/SConscript bsp/stm32/libraries/STM32H7xx_HAL/SConscript bsp/stm32/libraries/STM32L0xx_HAL/SConscript bsp/stm32/libraries/STM32L1xx_HAL/SConscript ``` PM组件能在CPU的空闲任务段随时进入睡眠模式,从而能够最大限度的实现节电,并且不影响用户的一般操作,对用户就是个透明黑盒。它和用户自己操作的睡眠有点不同,在OS系统中,用户自己定义的睡眠可能会影响系统的tick,造成各种定时不准。PM组件的睡眠就不会影响系统的OS,但要实现,就必须要有低功耗的MS级的定时器,在睡眠期间不掉电,并能随时唤醒。对STM32系列来说,`STM32L0/L4/G0/G4/F4(部分)/F7/H7`系列自带 LPTIM,睡眠时使用 LPTIM,其它系统没有LPTIM,使用了RTC,但要实现ms级的定时精度,修改了异步和同步分频比。 F0系列中有周期唤醒定时器的,使用周期唤醒定时器唤醒,但由于周期唤醒定时器不能读出当前的计数值,增大同步分频比到1023,同时减小异步分频比到31,实现秒级时基的不变,利用读取亚秒(精度扩大到1/1024秒),来实现ms级读取。F0系列中没有周期唤醒定时器的,使用闹钟来唤醒,同样亚秒精度要达到ms级。 F1系列没有周期唤醒定时器,也没有亚秒,只能使用闹钟来唤醒,也要改变预分频比,减少到只有原来的1/1024。这样有2个缺点:RTC的功耗会稍微增加;秒时基不准了,要使用硬件RTC读取时间(HAL_RTC_GetTime())是不准的,不过可以修改 `bsp\stm32\libraries\STM32F1xx_HAL\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rtc.c` 的代码,我这里的是修改后的文件,是STM32Cube_FW_F1_V1.8.0库的,修改后的使用`HAL_RTC_GetTime()`和设置时间都正常,当然闹钟是不允许用的。 F2系列和部分的L1系列中有周期唤醒定时器的,可以使用周期唤醒定时器唤醒,但没有亚秒,也只能减小时基来实现毫秒级的精度。硬件时钟不准了,一定要使用实时时钟的话,提供一种思路:先读取时间及日期(是原来的1024倍),转换成统一的秒数,除以1024,再转换成time和date。 其它系列有周期唤醒定时器,也有亚秒,同F0。 有LPTIM的,先用STM32CubeMX使能LPTIM,要用RTC唤醒的,用STM32CubeMX使能RTC,中断和参数都不用配置。 还要再修改文件:board.c 和 board.h board.h在SystemClock_Config后面添加如下: ``` void SystemClock_Config(void); #ifdef RT_USING_PM void SystemClock_MSI_ON(void); void SystemClock_MSI_OFF(void); void SystemClock_RunModeHigh(void); void SystemClock_RunModeNormal(void); void SystemClock_RunModeMedium(void); void SystemClock_RunModeLow(void); void SystemClock_ReConfig(uint8_t mode); #endif /* RT_USING_PM */ ``` board.c中要添加以下代码: ```c #ifdef RT_USING_PM /* * 根据自己的BSP运行频率设置,有4组频率,请修改第一个频率值,以适合自己的芯片 */ uint8_t run_speed[PM_RUN_MODE_MAX][2] = { {48, 0}, /* 高频 */ {48, 1}, /* 普通默认 */ {20, 2}, /* 中频 */ {8, 3}, /* 低频 */ }; void SystemClock_MSI_ON(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Initializes the CPU, AHB and APB busses clocks */ #if defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.MSIState = RCC_MSI_ON; #else RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; #endif /* defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) */ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; /* No update on PLL */ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; #if defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; #else RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; #endif /* defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } void SystemClock_MSI_OFF(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; #if defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.MSIState = RCC_MSI_OFF; #else RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_OFF; #endif /* defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32L1) || defined(SOC_SERIES_STM32L4) */ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; /* No update on PLL */ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } } /* 高频或超频时系统时钟配置,请根据自己的芯片配置 */ void SystemClock_RunModeHigh(void) { SystemClock_RunModeNormal(); } /* 普通的默认频率时系统时钟配置,请根据自己的芯片配置 */ void SystemClock_RunModeNormal(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; /* Activate PLL with HSE as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Reconfigure the SYSCLK clocks dividers */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; /* 注意:FLASH LATENCY 要和自己配置的系统总线时钟及核心电压相匹配,可查看手册 */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } } /* 中等频率时系统时钟配置,请根据自己的芯片配置 */ void SystemClock_RunModeMedium(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; /* Activate PLL with HSE as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL5; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Reconfigure the SYSCLK clocks dividers */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; /* 注意:FLASH LATENCY 要和自己配置的系统总线时钟及核心电压相匹配,可查看手册 */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /* 低频时系统时钟配置,请根据自己的芯片配置 */ void SystemClock_RunModeLow(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; /* Activate HSE as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Reconfigure the SYSCLK clocks dividers */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; /* 注意:FLASH LATENCY 要和自己配置的系统总线时钟及核心电压相匹配,可查看手册 */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief Configures system clock after wake-up from STOP: enable MSI or HSI, PLL * and select PLL as system clock source. * @param None * @retval None */ void SystemClock_ReConfig(uint8_t mode) { SystemClock_MSI_ON(); switch (mode) { case PM_RUN_MODE_HIGH_SPEED: SystemClock_RunModeHigh(); break; case PM_RUN_MODE_NORMAL_SPEED: SystemClock_RunModeNormal(); break; case PM_RUN_MODE_MEDIUM_SPEED: SystemClock_RunModeMedium(); break; case PM_RUN_MODE_LOW_SPEED: SystemClock_RunModeLow(); break; default: break; } } //#if !defined(LPTIM1) //extern RTC_HandleTypeDef RtcHandle; //#if defined(STM32F030x4) || defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F070x6) //extern RTC_AlarmTypeDef RtcAlarm; //#endif /* defined(STM32F030x4) || defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F070x6) */ //#endif /* !defined(LPTIM1) */ /* * 这里可以直接计算STOP模式下低功耗定时器或RTC的时钟频率 * 若配置为低功耗定时器或RTC的周期唤醒定时器,为Fosc/(初始化时的预分频数+1) * 若配置为RTC的ALARM唤醒,为Fosc/(异步预分频数+1) * 不清楚的可以直接注释这个,在drv_lptim.c中有一默认的__weak同名函数,只是计算步骤会多点 */ //rt_uint32_t HAL_PM_GetCounterFreq(void) //{ // return 32768 / 16; //} /* * 可以在这里修改自定义配置PM中使用的定时器的参数,以修改定时精度,建议至少要ms级别的 * 此函数为F030CC,即非LPTIM,有亚秒计时、周期唤醒定时器的RTC初始化 * 不清楚的可以直接注释这个,在drv_lptim.c中有一默认的__weak同名函数 */ //int HAL_PM_CounterInit(void) //{ // RtcHandle.Instance = RTC; // /* AsynchPrediv和SynchPrediv要满足 Fosc/((AsynchPrediv+1)*(SynchPrediv+1)) = 1 Hz */ // RtcHandle.Init.AsynchPrediv = 31; // /* 下面这个同步预分频系数大小影响STOP模式下的定时精度,越大精度越高,但功耗可能会稍高,1000左右比较合适 */ // RtcHandle.Init.SynchPrediv = 1023; // RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; // RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; // RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; // RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; // if (HAL_RTC_Init(&RtcHandle) != HAL_OK) // { // return -1; // } // /* 开启自己芯片的RTC唤醒中断,每种型号的中断号可能不同,自己修改 */ // NVIC_ClearPendingIRQ(RTC_IRQn); // NVIC_SetPriority(RTC_IRQn, 0); // NVIC_EnableIRQ(RTC_IRQn); // return 0; //} #endif /* RT_USING_PM */ ``` `SystemClock_MSI_ON()`和`SystemClock_MSI_OFF()`基本不用改。 `uint8_t run_speed[PM_RUN_MODE_MAX][2]` 根据自己芯片,设置4组运行频率 ``` SystemClock_RunModeHigh() SystemClock_RunModeNormal() SystemClock_RunModeMedium() SystemClock_RunModeLow() ``` 分别配置高频、普通默认、中频及低频的时钟配置,要修改成适合自己芯片的。 `SystemClock_ReConfig()`实现唤醒后恢复时钟的:
查看更多
42
个回答
默认排序
按发布时间排序
sunwan
2020-03-26
这家伙很懒,什么也没写!
下面这个是 F1系列的main,测试睡眠时间和变频稳定性的: ```c #include
#include
#include
#include
/* 定义自己的LED引脚 */ #define LED_PIN GET_PIN(A, 8) static RTC_HandleTypeDef hrtc; //static rt_uint8_t pm_mode = PM_SLEEP_MODE_LIGHT; static rt_uint8_t pm_mode = PM_SLEEP_MODE_DEEP; static uint32_t last_seconds = 0; static rt_uint8_t run_mode; static rt_uint8_t mode = 1; static uint32_t get_interval(void); static void RTC_TimeShow(void); static rt_uint8_t mode_loop(void); int main(void) { rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); rt_pin_write(LED_PIN, PIN_LOW); rt_thread_mdelay(10 * 1000); #ifdef RT_USING_PM rt_pm_request(pm_mode); #endif hrtc.Instance = RTC; RTC_TimeShow(); last_seconds = LL_RTC_TIME_Get(hrtc.Instance); while (1) { rt_pin_write(LED_PIN, PIN_HIGH); rt_thread_mdelay(10000); rt_kprintf("Sleep %d ms\n", get_interval()); RTC_TimeShow(); /* 为了测试变频的稳定性,把下面的这句注释取消,则每10秒改变一次频率 */ //rt_pm_run_enter(mode_loop()); #ifdef RT_USING_PM rt_pm_request(PM_SLEEP_MODE_LIGHT); #endif rt_pin_write(LED_PIN, PIN_LOW); rt_thread_mdelay(10000); rt_kprintf("Wakeup %d ms\n", get_interval()); RTC_TimeShow(); /* 为了测试变频的稳定性,把下面的这句注释取消,则每10秒改变一次频率 */ //rt_pm_run_enter(mode_loop()); #ifdef RT_USING_PM rt_pm_release(PM_SLEEP_MODE_LIGHT); #endif } return RT_EOK; } uint32_t get_interval(void) { rt_uint32_t period, seconds; seconds = LL_RTC_TIME_Get(hrtc.Instance); period = seconds - last_seconds; last_seconds = seconds; return (period) * 1000 / 1024; } /** * @brief Display the current time. * @param showtime : pointer to buffer * @retval None */ static void RTC_TimeShow(void) { RTC_DateTypeDef sdatestructureget; RTC_TimeTypeDef stimestructureget; /* Get the RTC current Time */ HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN); /* Get the RTC current Date */ HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN); /* Display time Format : hh:mm:ss */ rt_kprintf("%02d:%02d:%02d\n",stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds); } rt_uint8_t mode_loop(void) { mode++; switch (mode) { case 1: case 2: case 3: run_mode = mode; break; case 4: run_mode = 2; break; case 5: run_mode = 1; mode = 1; break; } return run_mode; } ```
sunwan
2020-03-26
这家伙很懒,什么也没写!
这个是其它系列使用RTC有亚秒时钟的测试main: ```c #include
#include
#include
/* 定义自己的LED引脚 */ #define LED_PIN GET_PIN(A, 8) static RTC_HandleTypeDef hrtc; //static rt_uint8_t pm_mode = PM_SLEEP_MODE_LIGHT; static rt_uint8_t pm_mode = PM_SLEEP_MODE_DEEP; static RTC_TimeTypeDef rtctime = {0}; static uint32_t datetmpreg; static rt_uint8_t run_mode; static rt_uint8_t mode = 1; static uint32_t get_interval(void); static void RTC_TimeShow(void); static rt_uint8_t mode_loop(void); int main(void) { rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); rt_pin_write(LED_PIN, PIN_LOW); rt_thread_mdelay(10 * 1000); #ifdef RT_USING_PM rt_pm_request(pm_mode); #endif hrtc.Instance = RTC; HAL_RTC_GetTime(&hrtc, &rtctime, RTC_FORMAT_BIN); datetmpreg = hrtc.Instance->DR; (void)datetmpreg; while (1) { rt_pin_write(LED_PIN, PIN_HIGH); rt_thread_mdelay(10000); rt_kprintf("Sleep %d ms\n", get_interval()); /* 为了测试变频的稳定性,把下面的这句注释取消,则每10秒改变一次频率 */ //rt_pm_run_enter(mode_loop()); #ifdef RT_USING_PM rt_pm_request(PM_SLEEP_MODE_LIGHT); #endif rt_pin_write(LED_PIN, PIN_LOW); rt_thread_mdelay(10000); rt_kprintf("Wakeup %d ms\n", get_interval()); /* 为了测试变频的稳定性,把下面的这句注释取消,则每10秒改变一次频率 */ //rt_pm_run_enter(mode_loop()); #ifdef RT_USING_PM rt_pm_release(PM_SLEEP_MODE_LIGHT); #endif } return RT_EOK; } uint32_t get_interval(void) { rt_uint32_t seconds; rt_uint32_t last_seconds = rtctime.Seconds; rt_uint32_t last_subseconds = rtctime.SubSeconds; HAL_RTC_GetTime(&hrtc, &rtctime, RTC_FORMAT_BIN); datetmpreg = hrtc.Instance->DR; (void)datetmpreg; if (rtctime.Seconds < last_seconds) seconds = 60 + rtctime.Seconds - last_seconds; else seconds = rtctime.Seconds - last_seconds; return (uint32_t)((int32_t)seconds * 1000 + ((int32_t)last_subseconds - (int32_t)rtctime.SubSeconds) * 1000 / (int32_t)(rtctime.SecondFraction + 1)); } rt_uint8_t mode_loop(void) { mode++; switch (mode) { case 1: case 2: case 3: run_mode = mode; break; case 4: run_mode = 2; break; case 5: run_mode = 1; mode = 1; break; } return run_mode; } ```
sunwan
2020-03-26
这家伙很懒,什么也没写!
现存的问题: drv_pm.c代码不够优美,是不是应该弄个文件夹,每个系列有对应的文件,使用SConscript配置,再把board.c中相关的部分也弄进去?
andychen
2020-03-26
这家伙很懒,什么也没写!
楼主,我是rtt andy 麻烦加下我微信13924608367哈,交流下这部分代码pr
aozima
2020-03-26
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
给楼主点赞
sunwan
2020-03-26
这家伙很懒,什么也没写!
`bsp/stm32/libraries/STM32F4xx_HAL/SConscript` 更新, 仔细看了下,发现F4系列只有`STM32F410xx/413xx/423xx` 有LPTIM。
sync
2020-03-26
这家伙很懒,什么也没写!
楼主威武 支持下
goodwell
2020-03-26
这家伙很懒,什么也没写!
支持下,感谢分享
yc985055
2020-03-28
这家伙很懒,什么也没写!
因为电源管理低功耗问题下载了楼主码云上rt-thread工程,跟rt-thread4.0.2相比,发动好多啊。:)
sunwan
2020-03-28
这家伙很懒,什么也没写!
嗯,我这个是前个星期Fork的RT-Thread官方4.0.3的,github上的。
撰写答案
登录
注册新账号
关注者
0
被浏览
4.4k
关于作者
sunwan
这家伙很懒,什么也没写!
提问
10
回答
91
被采纳
0
关注TA
发私信
相关问题
1
STM32F103的低功耗
2
最近用rtthread系统下AD采样并低功耗,中断响应不及时
3
rt-thread低功耗休眠应用问题请教
4
关于RTT对低功耗的支持
5
RT-Thread怎么休眠实现低功耗。
6
RT-Thread V3.0支持的低功耗,OS会自行进入吗?
7
关于RTThread3.0低功耗休眠模式
8
RTT3.0的bsp包中哪些MCU自带低功耗定时器?
9
关于低功耗上次说针对L4出个BSP的,怎么迟迟不见呀
10
低功耗问题。
推荐文章
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组件
最新文章
1
RT-Thread项目助手v0.2.0 - 支持Env Windows
2
RttreadV5.10上,GD32F450Z RTC时间显示问题
3
rt-smart启动流程分析
4
EtherKit快速上手PROFINET
5
RTThread USB转串口无法接收数据
热门标签
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
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部