uC/OS-III系统移植STM32F103C8
本实验是将嵌入式实时操作系统移植入STM32系列开发板,并完成一些基础的指令任务。此次实验采用的芯片为STM32F103C8
目录
一.使用STM32CUBEMX建立STM HEL 库工程
二.准备uC/OS-III源码
三.移植uC/OS-III系统
四.添加、修改文件内容
1.bsp.h和bsp.c
2.启动文件starup_stm32f103xb.s
3.app_cfg.h
4.includes.h
5.lib_cfg.h
6.usart.c
7.参数配置
五.运行
一.使用STM32CUBEMX建立STM HEL 库工程
打开stm32cubemx后新建工程搜索自己的芯片,进入芯片配置界面进行相应配置
以及芯片的输出端口
配置完成后配置工程文件
配置完成后右上角GENERATE CODE生成工程文件并在keil中打开
我们可以先对生成的工程文件尝试调试烧录一下能否正常运行
while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);HAL_Delay(500);}/* USER CODE END 3 */
将代码复制到main.c文件中
编译、烧录能使LED灯正常运行即可进行下一步。
二.准备uC/OS-III源码
获取源码可以去官网:http://micrium.com/downloadcenter/ 注册账号后下载
或者通过百度网盘链接:https://pan.baidu.com/s/10RqsDRecbmVteWmDv2oUNQ
提取码:1234
三.移植uC/OS-III系统
打开下载好的文件,将文件中的uc开头的文件复制
粘贴到我们的工程文件的MDK-ARM文件中
然后打开我们的keil工程文件,开始添加工程项目
在打开的窗口中建立六个文件并命名
命名完成后开始给刚才创建的文件添加工程文件
点击CPU 然后点击Add Files,在对应的文件名中找寻工程文件
添加完这三个之后打开ARM-Cortex-M3中的RealView中继续添加文件
完成后关闭
可以看到右侧文件添加成功
然后添加LIB的文件,同样打开对应名称的的下载文件,这里除了Ports文件夹不添加,下列的文件都需要添加
添加完成后打开Ports文件中的RealView中继续添加文件
完成后关闭
接下来是PORT文件 ,按照下列路径打开文件
然后将文件夹里的文件全部添加
添加完成后关闭
然后到SOURCE文件,按照下列路径打开文件
将文件夹里的文件全部添加
完成后关闭
然后是CONFIG文件,打开对应名称文件夹,添加文件夹中的全部文件
完成后关闭
最后是BSP文件,同样是打开对应名称的文件夹添加里面的全部文件
完成之后关闭
最后一步,检查每个文件是否添加有误,确认无误后点击ok保存
可以看到工程项目文件已经添加
完成之后我们还要更改头文件路径
在弹出的界面中点击右上角添加,然后点击省略号,找到对应的文件并选择
添加完成之后ok保存
四.添加、修改文件内容
1.bsp.h和bsp.c
找到BSP文件,在bsp.h和bsp.c文件中添加代码
bsp.h
// bsp.h
#ifndef __BSP_H__
#define __BSP_H__#include "stm32f1xx_hal.h"void BSP_Init(void);#endif
bsp.c
// bsp.c
#include "includes.h"#define DWT_CR *(CPU_REG32 *)0xE0001000
#define DWT_CYCCNT *(CPU_REG32 *)0xE0001004
#define DEM_CR *(CPU_REG32 *)0xE000EDFC
#define DBGMCU_CR *(CPU_REG32 *)0xE0042004#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)CPU_INT32U BSP_CPU_ClkFreq (void)
{return HAL_RCC_GetHCLKFreq();
}void BSP_Tick_Init(void)
{CPU_INT32U cpu_clk_freq;CPU_INT32U cnts;cpu_clk_freq = BSP_CPU_ClkFreq();#if(OS_VERSION>=3000u)cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;#elsecnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;#endifOS_CPU_SysTickInit(cnts);
}void BSP_Init(void)
{BSP_Tick_Init();MX_GPIO_Init();
}#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void CPU_TS_TmrInit (void)
{CPU_INT32U cpu_clk_freq_hz;DEM_CR |= (CPU_INT32U)DEM_CR_TRCENA; /* Enable Cortex-M3's DWT CYCCNT reg. */DWT_CYCCNT = (CPU_INT32U)0u;DWT_CR |= (CPU_INT32U)DWT_CR_CYCCNTENA;cpu_clk_freq_hz = BSP_CPU_ClkFreq();CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR CPU_TS_TmrRd (void)
{return ((CPU_TS_TMR)DWT_CYCCNT);
}
#endif#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts)
{CPU_INT64U ts_us;CPU_INT64U fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us);
}
#endif#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts)
{CPU_INT64U ts_us;CPU_INT64U fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us);
}
#endif
2.启动文件starup_stm32f103xb.s
打开starup_stm32f103xb.s文件,找到PendSV_Handler和和SysTick_Handler,将其中的“_”删除并增加前缀“OS_CPU_”,如下图
3.app_cfg.h
修改文件夹中的内容为
#define APP_CFG_SERIAL_EN DEF_DISABLED
和
#define APP_TRACE(void)
4.includes.h
修改内容成
#include <bsp.h>
#include"gpio.h"
#include"app_cfg.h"
和
#include "stm32f1xx_hal.h"
5.lib_cfg.h
打开lib_cfg.h文件修改堆栈大小,因为我的stm32f103c8芯片RAM只有20K,所以改小一点
6.usart.c
由于我们的main函数中使用了printf函数,所以要在usart.c文件中完成对printf重定向
/* USER CODE BEGIN 1 */
int fputc(int ch,FILE *f){HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);return ch;
}
/* USER CODE END 1 */
别忘了加上头文件stdio.h不然识别不了file。
7.参数配置
五.运行
我们要完成几个任务来试试其运行可行性
任务一:间隔两秒发送hello uc/OS! 欢迎来到RTOS多任务环境
任务二:控制led灯间隔三秒切换状态
修改main.c内容
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* 任务优先级 */
#define START_TASK_PRIO 3
#define LED0_TASK_PRIO 4
#define MSG_TASK_PRIO 5
#define LED1_TASK_PRIO 6/* 任务堆栈大小 */
#define START_STK_SIZE 96
#define LED0_STK_SIZE 64
#define MSG_STK_SIZE 64
#define LED1_STK_SIZE 64/* 任务栈 */
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
CPU_STK MSG_TASK_STK[MSG_STK_SIZE];
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];/* 任务控制块 */
OS_TCB StartTaskTCB;
OS_TCB Led0TaskTCB;
OS_TCB MsgTaskTCB;
OS_TCB Led1TaskTCB;/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* 任务函数定义 */
void start_task(void *p_arg);
static void AppTaskCreate(void);
static void AppObjCreate(void);
static void led_pc13(void *p_arg);
static void send_msg(void *p_arg);
static void led_pa3(void *p_arg);
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/**Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/**Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{OS_ERR err;OSInit(&err);HAL_Init();SystemClock_Config();//MX_GPIO_Init(); 这个在BSP的初始化里也会初始化MX_USART1_UART_Init(); /* 创建任务 */OSTaskCreate((OS_TCB *)&StartTaskTCB, /* Create the start task */(CPU_CHAR *)"start task",(OS_TASK_PTR ) start_task,(void *) 0,(OS_PRIO ) START_TASK_PRIO,(CPU_STK *)&START_TASK_STK[0],(CPU_STK_SIZE) START_STK_SIZE/10,(CPU_STK_SIZE) START_STK_SIZE,(OS_MSG_QTY ) 0,(OS_TICK ) 0,(void *) 0,(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR *)&err);/* 启动多任务系统,控制权交给uC/OS-III */OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */}void start_task(void *p_arg)
{OS_ERR err;CPU_SR_ALLOC();p_arg = p_arg;/* YangJie add 2021.05.20*/BSP_Init(); /* Initialize BSP functions *///CPU_Init();//Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); //统计任务
#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();
#endif#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif OS_CRITICAL_ENTER(); //进入临界区/* 创建LED0任务 */OSTaskCreate((OS_TCB * )&Led0TaskTCB, (CPU_CHAR * )"led_pc13", (OS_TASK_PTR )led_pc13, (void * )0, (OS_PRIO )LED0_TASK_PRIO, (CPU_STK * )&LED0_TASK_STK[0], (CPU_STK_SIZE)LED0_STK_SIZE/10, (CPU_STK_SIZE)LED0_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR * )&err); /* 创建LED1任务 */OSTaskCreate((OS_TCB * )&Led1TaskTCB, (CPU_CHAR * )"led_pa3", (OS_TASK_PTR )led_pa3, (void * )0, (OS_PRIO )LED1_TASK_PRIO, (CPU_STK * )&LED1_TASK_STK[0], (CPU_STK_SIZE)LED1_STK_SIZE/10, (CPU_STK_SIZE)LED1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR * )&err); /* 创建MSG任务 */OSTaskCreate((OS_TCB * )&MsgTaskTCB, (CPU_CHAR * )"send_msg", (OS_TASK_PTR )send_msg, (void * )0, (OS_PRIO )MSG_TASK_PRIO, (CPU_STK * )&MSG_TASK_STK[0], (CPU_STK_SIZE)MSG_STK_SIZE/10, (CPU_STK_SIZE)MSG_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err);OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务 OS_CRITICAL_EXIT(); //进入临界区
}
/*** 函数功能: 启动任务函数体。* 输入参数: p_arg 是在创建该任务时传递的形参* 返 回 值: 无* 说 明:无*/
static void led_pc13 (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}static void led_pa3 (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}static void send_msg (void *p_arg)
{OS_ERR err;(void)p_arg;BSP_Init(); /* Initialize BSP functions */CPU_Init();Mem_Init(); /* Initialize Memory Management Module */#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endifCPU_IntDisMeasMaxCurReset();AppTaskCreate(); /* Create Application Tasks */AppObjCreate(); /* Create Application Objects */while (DEF_TRUE){printf("hello uc/OS! 欢迎来到RTOS多任务环境(天外来戊) \r\n");OSTimeDlyHMSM(0, 0, 2, 0,OS_OPT_TIME_HMSM_STRICT,&err);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/* USER CODE BEGIN 4 */
/*** 函数功能: 创建应用任务* 输入参数: p_arg 是在创建该任务时传递的形参* 返 回 值: 无* 说 明:无*/
static void AppTaskCreate (void)
{}/*** 函数功能: uCOSIII内核对象创建* 输入参数: 无* 返 回 值: 无* 说 明:无*/
static void AppObjCreate (void)
{}/* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{ /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
修改gpio.c中的代码,使用添加初始化pa3
void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);/*Configure GPIO pin : PC13|PA3 */GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}
完成后烧录运行即可
uC/OS-III系统移植STM32F103C8相关推荐
- UC/OS III操作系统学习笔记
UCOS操作系统学习笔记 1.UCOSIII任务 1.1任务管理 1.2 任务创建和删除.挂起和恢复 1.3 系统内部任务 2.UCOSIII中断和时间管理 2.1 中断管理 2.2 时间管理 3.U ...
- uC/OS iii(三)任务管理之任务状态
博客已转移至https://www.cnblogs.com/heart-flying/p/10148254.html
- 嵌入式系统 操作系统 uC/OS uClinux
摘要:嵌入式操作系统是嵌入式系统应用的核心软件.本文通过对两种典型的开源嵌入式操作系统的对比,分析和总结嵌入式操作系统应用中的若干问题,归纳嵌入式操作系统的选型依据. 关键词:嵌入式系统 操作系统 u ...
- -uc/OS系统移植(基于STM32F103C8T6,超详细讲解)
完成STM32F103C8基于HAL库的-uc/OS系统移植 一.创建HAL库 二.下载uc/OSIII源码及移植准备 1.下载uc/OSIII源码 2.将uc/OS源码文件复制到工程 三.将uc/O ...
- 基于STM32的uc/OS系统移植及用Saleae Logic 16抓取分析波形
文章目录 一.关于uc/OS系统 1.操作系统与裸机的区别 2.uc/OS运行流程 二.详细移植过程 1.STM32Cubex创建工程 2.为工程添加源码 3.添加头文件路径 4.添加代码 1)bsp ...
- 基于STM32F103RC移植uc/OS系统
目录 一.获取uc/OS-III源码 二.使用CubeMX创建基础stm32框架 三.文件准备 四.路径添加 五.代码修改 六.成功展示 七.使用Keil仿真逻辑仪观察引脚电平变化 八.参考资料 本文 ...
- 嵌入式系统开发16——嵌入式实时操作系统uC/OS的简介及简单应用
本文主要介绍嵌入式实时操作系统(RTOS),并且以uc/OS为例,将其移植到stm32F103C8T6上,构建3个任务:其中两个task分别以1s和3s周期对LED灯进行点亮-熄灭的控制:另外一个ta ...
- 0 uC/OS 系统精讲索引
uC/OS-II与uC/OS-III放在一起讲,每个例程同时提供两个版本的源代码. 本系列教程主要涉及如下内容: [原理部分] 1-操作系统简介:基本概念 2-目录结构与测试环境搭建:uC/OS-II ...
- STM32F103C8T6移植uc/OS
STM32F103C8T6移植uc/OS STM32F103C8T6移植uc/OS STM32F103C8T6移植uc/OS 一.题目要求 二.使用STM32CubeMX建立HAL库 三.准备uCOS ...
最新文章
- windows cannot ftp_免费自动FTP同步软件,6步掌握免费自动FTP同步软件的安装方法...
- Keep the Customer Satisfied
- 第13章 Kotlin 集成 SpringBoot 服务端开发(1)
- 虚拟机种mysql的安装_RedHat7.0虚拟机下mysql安装
- 洛谷 P2818 天使的起誓
- 命令行实现SMTP和IMAP
- java中GUI的awt和Swing的知识点
- vue指令-单向和双向绑定
- 华为tsm_台积电:如果不能向华为销售芯片,其他订单可快速取代华为空缺
- java 方法 示例_Java语言环境getISOCountries()方法与示例
- linux 文件格式压缩
- 贪心法——LeetCode Assign Cookies分饼干
- Great Song
- chrome浏览pdf 字体变了
- 【学术分享】40个科研学术网站,收藏必备,予取予求!
- Docker安装mysql5.7
- 惠普服务器故障代码_HP服务器常见代码
- vue项目如何打包以及如何变成android、ios应用程序
- 小米手机刷android one,小米手机(Mi One)刷机教程详解完整版 (刷MIUI官方刷机包)...
- iphonex 序列号_iPhoneX如何查看手机序列号?三种查看方法全教给你!
热门文章
- android 开发帮助书籍pdf
- IPv6设备配置选项
- SOLID原理的详细信息。
- win10打开蓝牙_双系统共用蓝牙键鼠(win10+macOS)
- amixer alsa
- 上百本中文书籍中对《人月神话》的引用(1)
- python修改表格居中_Python使用openpyxl对xlsx表格合并单元格、设置单元格样式的操作...
- Case Study _均值方差模型 MatLab
- AR Foundation
- 第13期微生物组-宏基因组分析(线上/线下同时开课,2021.11)