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时间串口输出分析
 串口输出为:
 
 


