【STM32入门学习】学习嵌入式实时操作系统(RTOS)移植uc/OS到stm32F103上

目录

一、建立STM32HAL库工程

1.1实时操作系统

1.2基于HAL库创建工程

二、获取uC/OS-III源码

三、移植准备

3.1复制uC/OS-III文件到工程文件夹

3.2添加工程组件和头文件路径

四、移植修改代码

4.1.启动文件修改:

4.2.app_cfg.h

4.3.includes.h

4.4.bsp.c和bsp.h

4.5. app.c和app.h

4.6. main.c

7. lib_cfg.h

五、任务实现

六、心得体会


一、建立STM32HAL库工程

1.1实时操作系统

实时操作系统(Real-Time Operating System,RTOS)是一种专门设计用于处理实时数据流和实时任务的操作系统。

实时性: RTOS能够保证任务在特定的时间约束内完成,包括硬实时(hard real-time)和软实时(soft real-time)。硬实时要求任务在严格的时间戳内完成,软实时则有一定的宽松度。

快速响应: RTOS能够快速响应外部事件和中断请求,以满足系统对即时性的需求。

确定性: RTOS能够提供高度的确定性,即任务的执行时间是可预测的和可控制的。这对于需要时间保证的应用非常重要,如航空航天、医疗设备、工业控制等。

任务调度: RTOS具有灵活的任务调度机制,能够按照优先级或其他调度策略有效地管理和调度任务。

资源管理: RTOS能够有效地管理系统资源,如处理器时间、内存、设备等,以最大化系统的效率和可靠性。

可嵌入性: RTOS通常设计为小巧、高效的系统,非常适合嵌入式系统和资源受限的环境。

通信和同步: RTOS提供了多种通信和同步机制,如消息队列、信号量、事件标志等,以便任务之间的协作和数据交换。

1.2基于HAL库创建工程

操作步骤

1.选择芯片

打开stm32 cubeMX,选择芯片stm32f103c8,配置系统时钟为72M,作为移植测试,将与LED相连的两个端口PB0,PB1配置为GPIO_Output,可根据LED现象作为我们是否移植成功的依据。

二、获取uC/OS-III源码

链接: https://pan.baidu.com/s/17dFc7RyjQ7e4pWlpmZe9og 提取码: 1234 复制这段内容后打开百度网盘手机App,操作更方便哦

三、移植准备

3.1复制uC/OS-III文件到工程文件夹

1.在生成的keil工程文件夹中新建一个 UCOSIII 的文件夹,将我们下载的源代码中的文件夹:复制到我们新建的文件夹UCOSIII中:

2.在Src文件夹下新建一个OS文件夹

3.

将刚才下载源码打开,将路径:uCOS-CONFIG中的文件:


app.c 、 app_cfg.h 、 cpu_cfg.h 、 includes.h 、 lib_cfg.h 、 os_app_hooks.c 、os_app_hook.h、os_cfg.h、os_cfg_app.h复制到上一步建立的OS文件夹中,同时新建三个空白文件: bsp.c、bsp.h、app.h

3.2添加工程组件和头文件路径

1.添加工程

bsp:    Src中/OS,将其中 bsp.c 和 bsp.h文件添加至 bsp 组中

将 app.c 添加进 Application/User 组中

uCOSIII_CPU 组件, 点击 Add Files…按钮,将文件目录跳转至: UCOSIII/uC-CPU, 选择 ALL files 文件类型,将其中的三个文件点击 Add 添加, 然后再打开: ARM-Cortex-M3\RealView, 同样选择 ALL files 文件类型,将三个文件添加进 uCOSIII_CPU 组

添加 uCOSIII_LIB 组件文件:选择 uCOSIII_LIB 组,点击 Add Files…按钮, 将文件目录跳转至: UCOSIII/uCLIB,选择 ALL files 文件类型,将其中的九个文件添加进 uCOSIII_LIB 组;然后继续打开: Ports/ARM-Cortex-M3/Realview, 添加 lib_mem_a.asm 文件

选择 uCOSIII_Ports 组,点击 Add Files…按钮, 将文件目录调整至: UCOSIII/UcosIII/Ports/RAM-Cortex-M4/Generic/RealView。选择 ALL files 文件类型, 将其中三个文件添加进 uCOSIII_Ports 组

选择uCOSIII_Sourc组,点击Add Files…按钮, 将文件目录调整至: UCOSIII/UcosIII/Source。选择 ALL files 文件类型, 将其中二十个文件添加进 uCOSIII_Sourc 组。

选择 OS_cfg 组,点击 Add Files…按钮, 将文件目录调整至: Src/OS。选择 ALLfiles 文件类型, 将图中的八个文件添加进 uCOSIII_Sourc 组

全部组件文件添加完成以后的工程文件结构:

3. 添加头文件路径

依次去找一下,添加以下路径

四、移植修改代码

开始修改代码了:

4.1.启动文件修改:

4.2.app_cfg.h

#define APP_CFG_SERIAL_EN DEF_ENABLED

修改为:

#define APP_CFG_SERIAL_EN DEF_DISABLED

#define APP_TRACE BSP_Ser_Printf

修改为:

#define APP_TRACE (void)

4.3.includes.h

把:#include <bsp.h>

修改为:

#include <bsp.h>
#include "gpio.h"
#include "app_cfg.h"
#include "app.h"

把:#include <stm32f10x_lib.h>

修改为:

#include "stm32f1xx_hal.h"

4.4.bsp.c和bsp.h

修改代码:

// 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
// bsp.h
#ifndef  __BSP_H__
#define  __BSP_H__#include "stm32f1xx_hal.h"void BSP_Init(void);#endif

4.5. app.c和app.h

app.c我们实际是用main.c代替,所以app.c中没有什么实际的代码,这里将其保留,也可选择删除,注意头文件包含即可。

// app.c
#include <includes.h>
// app.h
#ifndef  __APP_H__
#define  __APP_H__#include <includes.h>#endif /* __APP_H__ */

4.6. main.c

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.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 *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
//任务控制块
static  OS_TCB   AppTaskStartTCB;//任务堆栈
static  CPU_STK  AppTaskStartStk[APP_TASK_START_STK_SIZE];/* 私有函数原形 --------------------------------------------------------------*/
static  void  AppTaskCreate(void);
static  void  AppObjCreate(void);
static  void  AppTaskStart(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)
{/* USER CODE BEGIN 1 */OS_ERR  err;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */
//  HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */
//  SystemClock_Config();/* USER CODE BEGIN SysInit */OSInit(&err);    /* USER CODE END SysInit *//* Initialize all configured peripherals */
//  MX_GPIO_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE *//* 创建任务 */OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                /* Create the start task                                */(CPU_CHAR   *)"App Task Start",(OS_TASK_PTR ) AppTaskStart,(void       *) 0,(OS_PRIO     ) APP_TASK_START_PRIO,(CPU_STK    *)&AppTaskStartStk[0],(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,(CPU_STK_SIZE) APP_TASK_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). */}/*** 函数功能: 启动任务函数体。* 输入参数: p_arg 是在创建该任务时传递的形参* 返 回 值: 无* 说    明:无*/
static  void  AppTaskStart (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_TogglePin(LED0_GPIO_Port,LED0_Pin);HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin, GPIO_PIN_SET);OSTimeDlyHMSM(0, 0, 0, 500,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****/

7. lib_cfg.h

#define  LIB_MEM_CFG_HEAP_SIZE          27u * 1024u

五、任务实现

1.学习嵌入式实时操作系统(RTOS),以uc/OS为例,将其移植到stm32F103上,构建至少3个任务(task)其中两个task分别以1s和3s周期对LED等进行点亮-熄灭的控制;

代码:在生成任务之前,我们还要进行一些必要的声明,用来声明µC/OS-III的任务函数。

/* 任务优先级 */
#define APP_TASK_START_PRIO		2
#define MyTask_LED1_PRIO		3
#define MyTask_LED2_PRIO		3/* 任务堆栈大小	*/
#define APP_TASK_START_STK_SIZE 128
#define MyTask_LED1_STK_SIZE 	512
#define MyTask_LED2_STK_SIZE	512/* 任务控制块 */
static OS_TCB AppTaskStartTCB;
static OS_TCB MyTask_LED1TCB;
static OS_TCB MyTask_LED2TCB;/* 任务栈 */	
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
static CPU_STK TASK_LED1STK[MyTask_LED1_STK_SIZE];
static CPU_STK TASK_LED2STK[MyTask_LED2_STK_SIZE];/* 声明用户任务 */	
static void AppTaskStart  (void *p_arg);
static void MyTask_LED1  (void *p_arg);
static void MyTask_LED2  (void *p_arg);

多任务编程时,一般在main()函数中创建一个初始任务AppTaskStart。

//main()中部分代码OS_ERR  err;OSInit(&err);/* 创建任务 */OSTaskCreate((OS_TCB *)&AppTaskStartTCB,                /* Create the start task                                */(CPU_CHAR   *)"App Task Start",(OS_TASK_PTR ) AppTaskStart,(void       *) 0,(OS_PRIO     ) APP_TASK_START_PRIO,(CPU_STK    *)&AppTaskStartStk[0],(CPU_STK_SIZE) APP_TASK_START_STK_SIZE/10,(CPU_STK_SIZE) APP_TASK_START_STK_SIZE,(OS_MSG_QTY  ) 5u,(OS_TICK     ) 0u,(void       *) 0,(OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),(OS_ERR     *)&err);/* 启动多任务系统,控制权交给uC/OS-III */OSStart(&err);

再通过AppTaskStart创建其它用户任务MyTask1、MyTask2等

static void AppTaskStart (void *p_arg)
{CPU_INT32U cpu_clk_freq;CPU_INT32U cnts;OS_ERR  err;(void)p_arg;BSP_Init();CPU_Init();cpu_clk_freq=BSP_CPU_ClkFreq();cnts=cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;OS_CPU_SysTickInit(cnts);Mem_Init();#if OS_CFG_STAT_TASK_EN>0uOSStatTaskCPUUsageInit(&err);#endifCPU_IntDisMeasMaxCurReset();OSTaskCreate((OS_TCB *)&MyTask_LED1TCB,                /* Create the start task                                */(CPU_CHAR   *)"LED1",(OS_TASK_PTR ) MyTask_LED1,(void       *) 0,(OS_PRIO     ) MyTask_LED1_PRIO,(CPU_STK    *)&TASK_LED1STK[0],(CPU_STK_SIZE) MyTask_LED1_STK_SIZE/10,(CPU_STK_SIZE) MyTask_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);OSTaskCreate((OS_TCB *)&MyTask_LED2TCB,                /* Create the start task                                */(CPU_CHAR   *)"LED2",(OS_TASK_PTR ) MyTask_LED2,(void       *) 0,(OS_PRIO     ) MyTask_LED2_PRIO,(CPU_STK    *)&TASK_LED2STK[0],(CPU_STK_SIZE) MyTask_LED2_STK_SIZE/10,(CPU_STK_SIZE) MyTask_LED2_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的周期是1s,因此是每500ms翻转一次电平。

static void MyTask_LED1(void *p_arg)
{OS_ERR err;(void)p_arg;while(1){OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);}
}
static void MyTask_LED2(void *p_arg)
{OS_ERR err;(void)p_arg;while(1){OSTimeDlyHMSM(0,0,1,500,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);}
}

多个LED灯效果视频:

2.另外一个task以2s周期通过串口发送“hello uc/OS! 欢迎来到RTOS多任务环境!”。

相关代码:

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "usart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
#include "stm32f1xx_hal.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_pb8(void *p_arg);
static  void  send_msg(void *p_arg);
static  void  led_pb9(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_pb8", 		(OS_TASK_PTR )led_pb8, 			(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_pb9", 		(OS_TASK_PTR )led_pb9, 			(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_pb8 (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){OSTimeDlyHMSM(0, 0, 1, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}static  void  led_pb9 (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){OSTimeDlyHMSM(0, 0, 3, 0,OS_OPT_TIME_HMSM_STRICT,&err);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);/* 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 \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****/

效果视频:

六、心得体会

总的来说,这次试验强度最大,需要花费的时间更多,看了网上的很多教程,再KEIL里面跑的时候总是出错,再移植文件时候细心是非常重要的,一定要正确的找到相关文件的位置,同时,本次学习也加强了我对嵌入式的理解。

本人才疏学浅,如有不正确的地方,还望海涵。感谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/34065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Scanner 类

Java Scanner 类 java.util.Scanner 是 Java5 的新特征&#xff0c;我们可以通过 Scanner 类来获取用户的输入。 下面是创建 Scanner 对象的基本语法&#xff1a; Scanner s new Scanner(System.in);接下来我们演示一个最简单的数据输入&#xff0c;并通过 Scanner 类的 nex…

关于FPGA对 DDR4 (MT40A256M16)的读写控制 4

关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 4 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado、Quartus II 关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 4一、引言二、DDR4 SDRAM设备中模式寄存器重要的模式寄存…

数组中的逆序对

描述&#xff1a; https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/description/ 思路&#xff1a; 在进行归并排序时&#xff0c;会分成有序的左右两部分&#xff0c;如果左部分出现了大于右部分的数时&#xff08;nums[cur1] > nums[cur2]&#xff09;&…

Javaweb配置tomcat

Tomcat 9版本链接 链接&#xff1a;https://pan.baidu.com/s/1u-eDur5KlqlXM_IM50Ahtg?pwd1njm 提取码&#xff1a;1njm 1、打开idea&#xff0c;创建maven项目 2023版IDEA 2、 目录结构 ps: 如果结果不完整,选中main右键 新建对应的文件夹 3、 web项目设置Tomcat(部署项目…

特征工程与数据预处理全解析:基础技术和代码示例

在机器学习和数据科学的世界里&#xff0c;数据的质量是建模成功与否的关键所在。这就是特征工程和数据预处理发挥作用的地方。本文总结的这些关键步骤可以显著提高模型的性能&#xff0c;获得更准确的预测&#xff0c;我们将深入研究处理异常值、缺失值、编码、特征缩放和特征…

我是如何从功能测试转成自动化测试的!

大家好&#xff0c;我是测试君。&#xff08;六哥也行&#xff09; 时间过得好快&#xff0c;不知不觉已经在这个行业摸爬滚打10年多了&#xff0c;也算是测试圈的一枚老兵了。 回想自己在自动化求知路上的种种&#xff0c;依然历历在目&#xff0c;看着自己一步步的走来&#…

剪画小程序:视频文案提取神器:制作爆款视频的第一步!

在这个信息爆炸的时代&#xff0c;视频成为了我们获取知识和娱乐的重要途径。 但有时候&#xff0c;我们想要的不仅仅是观看视频&#xff0c;而是能够将其中精彩的文案提取出来&#xff0c;为自己的创作添砖加瓦。 现在&#xff0c;有一款神奇的工具应运而生&#xff0c;为您…

Linux-笔记 高级I/O操作

前言 I/O&#xff08;Input/Output&#xff0c;输入/输出&#xff09;是计算机系统中的一个重要组成部分&#xff0c;它是指计算机与 外部世界之间的信息交流过程。I/O 操作是计算机系统中的一种基本操作&#xff0c;用于向外部设备&#xff08;如 硬盘、键盘、鼠标、网络等&am…

https基础概念

目录 1.什么是https 1.1.https概念 1.2.一些术语 2.https如何加密 2.1.使用对称加密 2.2.使用非对称加密 1.什么是https 首先&#xff0c;https不是http的复数形式 1.1.https概念 &#xff08;1&#xff09;产生背景 为什么会出现https&#xff0c;是因为http协议在传…

小白学python(第二天)

哈喽&#xff0c;各位小伙伴们我们又见面了&#xff0c;昨天的文章吸收得如何&#xff1f;可有不懂否&#xff1f;如有不懂可以在品论区留言哦&#xff0c;废话不多说&#xff0c;开始今天的内容。 字符及字符串的续讲 字符&#xff1a;英文字母&#xff0c;阿拉伯数字&#x…

Keil汇编相关知识

一、汇编的组成 1.汇编指令&#xff1a;在内存中占用内存&#xff0c;执行一条汇编指令会让处理器进行相关运算 分类&#xff1a;数据处理指令&#xff0c;跳转指令&#xff0c;内存读写指令&#xff0c;状态寄存器传送指令&#xff0c;软中断产生指令&#xff0c;协助处理器…

AcWing算法基础课笔记——状态压缩DP:蒙德里安的梦想

状态压缩DP 状态是整数&#xff0c;但把它看成二进制数&#xff0c;二进制中每一位是0或1表示不同的情况。 蒙德里安的梦想 291. 蒙德里安的梦想 - AcWing题库 题目 求把 NM&#x1d441;&#x1d440; 的棋盘分割成若干个 1212 的长方形&#xff0c;有多少种方案。 例如…

electron-builder 打包过慢解决

报错内容如下 > 6-241.0.0 build > electron-builder • electron-builder version24.13.3 os10.0.22631 • loaded configuration filepackage.json ("build" field) • writing effective config filedist\builder-effective-config.yaml • pack…

地下管线管网三维建模系统MagicPipe3D

地下管网是保障城市运行的基础设施和“生命线”。随着实景三维中国建设的推进&#xff0c;构建地下管网三维模型与地上融合的数字孪生场景&#xff0c;对于提升智慧城市管理至关重要&#xff01;针对现有三维管线建模数据差异大、建模交互弱、模型效果差、缺乏语义信息等缺陷&a…

清科ZF引导基金数据(1990-2023年)

清科ZF引导基金数据&#xff0c;参考经济学家吴超鹏和严泽浩在《经济研究》2023年的研究&#xff0c;通过清科私募通数据库&#xff0c;获取ZF引导基金的管理机构信息。数据涵盖了ZF引导基金的关键信息&#xff0c;如基金名称、管理机构详情、所属层级、发展阶段、地域分布、初…

数据集MNIST手写体识别 pyqt5+Pytorch/TensorFlow

GitHub - LINHYYY/Real-time-handwritten-digit-recognition: VGG16和PyQt5的实时手写数字识别/Real-time handwritten digit recognition for VGG16 and PyQt5 pyqt5Pytorch内容已进行开源&#xff0c;链接如上&#xff0c;请遵守开源协议维护开源环境&#xff0c;如果觉得内…

redis集群简单介绍及其搭建过程

Redis集群 1、哨兵模式 哨兵可以有多个&#xff0c;从服务器也可以有多个&#xff0c;从服务器也可以有多个&#xff0c;在Redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态&#xff0c;如果master节点异常&#xff0c;则会实现主从切换&#x…

百度大模型安全荣获2024世界智能产业博览会“Find智能科技创新应用典型案例”

6月20日&#xff0c;2024世界智能产业博览会在天津开幕。会议聚焦人工智能、智能网联汽车、智能制造等年度热点议题&#xff0c;由世界智能产业博览会组委会指导&#xff0c;世界智能产业博览会组委会秘书处、中国新一代人工智能战略发展研究院、中国软件行业协会、中国网络空间…

极客之夜 | XCTF国际网络攻防联赛十周年庆典圆满落幕

在数字化浪潮的推动下&#xff0c;网络安全已成为全球关注的焦点。十年磨一剑&#xff0c;XCTF国际网络攻防联赛以其卓越的赛事品质和深远的影响力&#xff0c;成为网络安全领域的一面旗帜。极客之夜&#xff0c;我们齐聚一堂&#xff0c;共同庆祝XCTF的十年辉煌&#xff0c;展…

sheng的学习笔记-AI-高斯混合模型(GMM)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 sheng的学习笔记-AI-聚类(Clustering)-CSDN博客需要学习前置知识&#xff1a; 聚类&#xff0c;可参考 sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 EM算法&#xff0c;可参考 sheng的学习笔记-AI-EM算法-CSDN博客 贝…