uc/os3多任务与实时日历
- 一、STM32F103C8T6移植uCOS
- 二、简单多任务实现
- 三、RTC实时时钟
- 四、逻辑分析仪使用
一、STM32F103C8T6移植uCOS
1.uCOS下载
STM32F107uCOS样例下载
下载完成后文件如下:

2.文件导入
1)项目创建
使用STM32CUBEMX创建空项目
2)项目管理
1、在新建项目中新建文件夹UCOSIII
2、将官网样例文件中的uC-CPU、uC-LIB、uCOS-III移动到新建的文件夹UCOSIII中,并新建文件夹uCOS-BSP、uCOS-CONFIG文件
3,文件添加

新建Groups:uCOS-BSP、uCOS-CPU、uCOS-LIB、uCOS-Core、uCOS-Port、uCOS-Config
1、uCOS-BSP中添加文件

2、uCOS-CPU中添加文件

3、uCOS-LIB中添加文件

4、uCOS-Core中添加文件

5、uCOS-Port中添加文件


6、uCOS-Config中添加文件

4,头文件路径添加

3.文件修改

改
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
为

改
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
为

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)
3、includes.h
第一处修改:
添加相关头文件
#include <bsp.h>
修改为
#include <bsp.h>
#include “gpio.h”
#include “app_cfg.h”
#include "app.h"
第二处修改:
添加HAL 库
#include <stm32f10x_lib.h>
修改为
#include "stm32f1xx_hal.h"
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;
#else
cnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;
#endif
OS_CPU_SysTickInit(cnts);
}
void BSP_Init(void)
{
BSP_Tick_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 /* End of module include.
5、lib_cfg.h
这个头文件中有一个宏定义:
#define LIB_MEM_CFG_HEAP_SIZE 27u * 1024u
表示把堆的空间设置为27KB,但是我使用的stm32f103c8t6的RAM总共才20K,所以这里需要将堆空间改小一点,我改成了10K
#define LIB_MEM_CFG_HEAP_SIZE 10u * 1024u
此处的修改若是对于RAM空间较大的单片机是没有必要的,但是对于小容量的单片机则是必须的。
二、简单多任务实现
1、main.c
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <includes.h>
#include <stdio.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 */
//重写printf函数
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
//等待发送结束
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET){
}
return ch;
}
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//任务控制块
static OS_TCB AppTaskStartTCB;
OS_TCB LEDPB6TaskTCB;//LEDPB6
OS_TCB LEDPB7TaskTCB;//LEDPB7
OS_TCB USART1TaskTCB;//串口1
//任务堆栈
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
/* 私有函数原形 --------------------------------------------------------------*/
static void AppTaskCreate(void);
static void AppObjCreate(void);
static void AppTaskStart(void *p_arg);
//任务函数
void LEDPB6_TASK(void *p_arg);
void LEDPB7_TASK(void *p_arg);
void USART1_TASK(void *p_arg);
//任务优先级
#define LEDPB6_TASK_PRIO 3 //PB6优先级
#define LEDPB7_TASK_PRIO 3 //PB7优先级
#define USART1_TASK_PRIO 3 //USART1优先级
//任务栈大小
#define LEDPB6_STK_SIZE 128 //PB6栈大小
#define LEDPB7_STK_SIZE 128 //PB7栈大小
#define USART1_STK_SIZE 128 //串口1栈大小
CPU_STK LEDPB6_TASK_STK[LEDPB6_STK_SIZE];//PB6任务栈
CPU_STK LEDPB7_TASK_STK[LEDPB7_STK_SIZE];//PB7任务栈
CPU_STK USART1_TASK_STK[USART1_STK_SIZE];//串口任务栈
/* 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 */
/* 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();
MX_USART1_UART_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);
OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */
// while (1)
// {
// /* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// }
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses 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_1) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/**
* 函数功能: 启动任务函数体。
* 输入参数: 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 > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
OSTaskCreate((OS_TCB * )&LEDPB6TaskTCB,
(CPU_CHAR * )"PB6 task",
(OS_TASK_PTR )LEDPB6_TASK,
(void * )0,
(OS_PRIO )LEDPB6_TASK_PRIO,
(CPU_STK * )&LEDPB6_TASK_STK[0],
(CPU_STK_SIZE)LEDPB6_STK_SIZE/10,
(CPU_STK_SIZE)LEDPB6_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 * )&LEDPB7TaskTCB,
(CPU_CHAR * )"PB7 task",
(OS_TASK_PTR )LEDPB7_TASK,
(void * )0,
(OS_PRIO )LEDPB7_TASK_PRIO,
(CPU_STK * )&LEDPB7_TASK_STK[0],
(CPU_STK_SIZE)LEDPB7_STK_SIZE/10,
(CPU_STK_SIZE)LEDPB7_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 * )&USART1TaskTCB,
(CPU_CHAR * )"usart1 task",
(OS_TASK_PTR )USART1_TASK,
(void * )0,
(OS_PRIO )USART1_TASK_PRIO,
(CPU_STK * )&USART1_TASK_STK[0],
(CPU_STK_SIZE)USART1_STK_SIZE/10,
(CPU_STK_SIZE)USART1_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*)&AppTaskStartTCB,&err);
}
void LEDPB6_TASK (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 > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
}
}
void LEDPB7_TASK (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 > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
}
}
void USART1_TASK (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 > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
AppTaskCreate(); /* Create Application Tasks */
AppObjCreate(); /* Create Application Objects */
while (DEF_TRUE)
{
printf("hello uc/OS! 欢迎来到RTOS多任务环境!");
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
}
}
/**
* 函数功能: 创建应用任务
* 输入参数: 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 */
__disable_irq();
while (1)
{
}
/* 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,
ex: 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****/
结果



三、RTC实时时钟
工作过程

STM32CubeMx实现日历
1.项目创建
1)新建STM32CubeMx项目
时钟树设置

RCC设置

RTC设置

串口设置

2.日期打印代码
定义结构体
/* USER CODE BEGIN PV */
RTC_DateTypeDef GetData; //获取日期结构体
RTC_TimeTypeDef GetTime; //获取时间结构体
/* USER CODE END PV */
重写串口输出
int fputc(int ch,FILE *f){
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,2);
return ch;
}
串口打印时间
while (1)
{
/* Get the RTC current Time */
HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
/* Display date Format : yy年mm月dd日 */
printf("%02d年%02d月%02d日",2000 + GetData.Year, GetData.Month, GetData.Date);
/* Display time Format : hh时mm分ss秒 */
printf("%02d时%02d分%02d秒\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
a=GetData.WeekDay;
if(a==01){printf("星期一\r\n");}
else if(a==02){printf("星期二\r\n");}
else if(a==03){printf("星期三\r\n");}
else if(a==04){printf("星期四\r\n");}
else if(a==05){printf("星期五\r\n");}
else if(a==06){printf("星期六\r\n");}
else if(a==07){printf("星期天\r\n");}
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
3.效果演示

四、逻辑分析仪使用
一、GPIO逻辑分析
1.多任务逻辑分析
如图为uCOS多任务移植的GPIO高低电平输出逻辑图

一个周期为灯a闪3下,灯b闪1下
二、串口逻辑分析
RTC时间串口输出分析
串口输出为:


