uCOSIII构建多任务
上一节移植构建了模板和创建了单任务,这一节来构建多任务
uCOSIII系统移植(一)构建单任务
任务要求:构建三个任务(两个LED,一个BUZ)
参考野火的移植,(我的板子与野火的不同,所以需要做些更改)
原理图:
最下面的蓝灯是电源指示灯,LED0和LED1依据原理图低电平点亮(所以我们在初始化的时候要把这两个LED对应的引脚设置为高电平)
BEEP我们依据原理图,初始化设置为低电平(高电平工作)
所对应引脚关系
PF8—BUZ
PF9—LED0
PF10—LED1
LED.C
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK| LED2_GPIO_CLK| BUZ_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED2_PIN;
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BUZ_PIN;
GPIO_Init(BUZ_GPIO_PORT, &GPIO_InitStructure);
LED_MODE3; //这里是用.h文件中的宏定义/*关闭LED1/LED2灯*/
}
F407时钟挂载
对于F407系列的板子可以看到绝大部分IO口都是在AHB1总线上,所以在初始化外设的时候用到时钟直接写上(绝大部分,个别特别的需要注意下)RCC_AHB1PeriphClockCmd
在用到定时器(TIM)和串口(UART)以及SPI(如下两图)可以看到这些是用到APB1或者APB2时钟
其中可以看到:F407有三个I2C全部在APB1时钟总线上,有四个ADC全部在APB2时钟总线上
LED.H(宏定义狂魔)
#ifndef __LED_H
#define __LED_H
#include "stm32f4xx.h"
//引脚定义
/*******************************************************/
//LED1
#define LED1_PIN GPIO_Pin_9
#define LED1_GPIO_PORT GPIOF
#define LED1_GPIO_CLK RCC_AHB1Periph_GPIOF
//LED2
#define LED2_PIN GPIO_Pin_10
#define LED2_GPIO_PORT GPIOF
#define LED2_GPIO_CLK RCC_AHB1Periph_GPIOF
//BUZ
#define BUZ_PIN GPIO_Pin_8
#define BUZ_GPIO_PORT GPIOF
#define BUZ_GPIO_CLK RCC_AHB1Periph_GPIOF
/************************************************************/
/** 控制LED灯亮灭的宏,
* LED低电平亮,设置ON=0,OFF=1
* 若LED高电平亮,把宏设置成ON=1 ,OFF=0 即可
*/
#define ON 0
#define OFF 1
/* 带参宏,可以像内联函数一样使用 */
#define LED1(a) if (a) \
GPIO_SetBits(LED1_GPIO_PORT,LED1_PIN);\
else \
GPIO_ResetBits(LED1_GPIO_PORT,LED1_PIN)
#define LED2(a) if (a) \
GPIO_SetBits(LED2_GPIO_PORT,LED2_PIN);\
else \
GPIO_ResetBits(LED2_GPIO_PORT,LED2_PIN)
#define BUZ(a) if (a) \
GPIO_SetBits(BUZ_GPIO_PORT,BUZ_PIN);\
else \
GPIO_ResetBits(BUZ_GPIO_PORT,BUZ_PIN)
/* 直接操作寄存器的方法控制IO */
#define digitalHi(p,i) {p->BSRRL=i;} //设置为高电平
#define digitalLo(p,i) {p->BSRRH=i;} //输出低电平
#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态
/* 定义控制IO的宏 */
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_PIN) //翻转
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_PIN)
#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_PIN)
#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_PIN)
#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_PIN)
#define BUZ_TOGGLE digitalToggle(BUZ_GPIO_PORT,BUZ_PIN)
#define BUZ_ON digitalHi(BUZ_GPIO_PORT,BUZ_PIN) //蜂鸣器高电平打开
#define BUZ_OFF digitalLo(BUZ_GPIO_PORT,BUZ_PIN) //低电平关闭
//LED1 打开 LED2关闭
#define LED_MODE1 \
LED1_ON;\
LED2_OFF;\
//LED1 关闭 LED2打开
#define LED_MODE2 \
LED1_OFF;\
LED2_ON;\
//LED1 LED2都关闭
#define LED_MODE3 \
LED1_OFF;\
LED2_OFF;\
//LED1 LED2都打开
#define LED_MODE4 \
LED1_OFF;\
LED2_OFF;\
void LED_GPIO_Config(void);
#endif /* __LED_H */
这里可以看到很多宏定义,大部分移植以后直接更改LED.文件里面的宏就可以了,上一节也有提到过。
//LED1
#define LED1_PIN GPIO_Pin_9
#define LED1_GPIO_PORT GPIOF
#define LED1_GPIO_CLK RCC_AHB1Periph_GPIOF
//LED2
#define LED2_PIN GPIO_Pin_10
#define LED2_GPIO_PORT GPIOF
#define LED2_GPIO_CLK RCC_AHB1Periph_GPIOF
//BUZ
#define BUZ_PIN GPIO_Pin_8
#define BUZ_GPIO_PORT GPIOF
#define BUZ_GPIO_CLK RCC_AHB1Periph_GPIOF
接下来就是把初始化函数加入到
BSP.C
这个函数中,所有初始化函数以后都放在这里(规范)
APP.C
#include <includes.h>
/*============任务控制块==============*/
static OS_TCB AppTaskStartTCB;
static OS_TCB AppTaskLed1TCB;
static OS_TCB AppTaskLed2TCB;
static OS_TCB AppTaskbuz3TCB;
/*======================任务堆栈大小=====================*/
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];
static CPU_STK AppTaskLed1Stk [ APP_TASK_LED1_STK_SIZE ];
static CPU_STK AppTaskLed2Stk [ APP_TASK_LED2_STK_SIZE ];
static CPU_STK AppTaskBUZStk [ APP_TASK_BUZ3_STK_SIZE ];
/*=====================函数申明======================*/
static void APPTaskStart (void *p_arg);
static void AppTaskLed1 ( void * p_arg );
static void AppTaskLed2 ( void * p_arg );
static void AppTaskBUZ3 ( void * p_arg );
int main (void)
{
OS_ERR err;
OSInit(&err); /* Init uC/OS-III. */
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, /* 任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 */
(OS_TICK ) 0u, /* 当使能时间片轮转时的时间片长度,为0时为默认长度 */
(void *) 0, /* 用户补充的存储区 */
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),/*任务选项 */
(OS_ERR *)&err); /*存放该函数错误时的返回值*/
OSStart(&err); //开启UCOSIII /* Start multitasking (i.e. give control to uC/OS-III). */
while(1);
}
static void APPTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
(void)p_arg;
/*开发板硬件初始化*/
CPU_Init();
BSP_Init(); /* Initialize BSP functions */
cpu_clk_freq = BSP_CPU_ClkFreq(); /* Determine SysTick reference freq. */
cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz; /* Determine nbr SysTick increments */
OS_CPU_SysTickInit(cnts); /* Init uC/OS periodic time src (SysTick). */
/*内存初始化*/
Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务 /* Compute CPU capacity with no task running */
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_IntDisMeasMaxCurReset();
#endif
/*==========================================App Task Led1================================================================*/
OSTaskCreate((OS_TCB *)&AppTaskLed1TCB, /* Create the Led1 task */
(CPU_CHAR *)"App Task Led1",
(OS_TASK_PTR ) AppTaskLed1,
(void *) 0,
(OS_PRIO ) APP_TASK_LED1_PRIO,
(CPU_STK *)&AppTaskLed1Stk[0],
(CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED1_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);
/*===========================================App Task Led2================================================================*/
OSTaskCreate((OS_TCB *)&AppTaskLed2TCB, /* Create the Led2 task */
(CPU_CHAR *)"App Task Led2",
(OS_TASK_PTR ) AppTaskLed2,
(void *) 0,
(OS_PRIO ) APP_TASK_LED2_PRIO,
(CPU_STK *)&AppTaskLed2Stk[0],
(CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_LED2_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);
/*============================================App Task BUZ3==========================================================*/
OSTaskCreate((OS_TCB *)&AppTaskbuz3TCB, /* Create the BUZ3 task */
(CPU_CHAR *)"App Task BUZ3",
(OS_TASK_PTR ) AppTaskBUZ3,
(void *) 0,
(OS_PRIO ) APP_TASK_BUZ3_PRIO ,
(CPU_STK *)&AppTaskBUZStk[0],
(CPU_STK_SIZE) APP_TASK_BUZ3_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK_BUZ3_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);
OSTaskDel ( & AppTaskStartTCB, & err ); //删除自身任务
}
/*
*********************************************************************************************************
* LED1 TASK
*********************************************************************************************************
*/
static void AppTaskLed1 ( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { /* Task body, always written as an infinite loop. */
LED1_TOGGLE;
OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err );
}
}
/*
*********************************************************************************************************
* LED2 TASK
*********************************************************************************************************
*/
static void AppTaskLed2 ( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { /* Task body, always written as an infinite loop. */
LED2_TOGGLE;
OSTimeDly ( 500, OS_OPT_TIME_DLY, & err );
}
}
/*
*********************************************************************************************************
* BUZ TASK
*********************************************************************************************************
*/
static void AppTaskBUZ3 ( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) { /* Task body, always written as an infinite loop. */
//BUZ_TOGGLE;
BUZ_OFF;
OSTimeDly ( 500, OS_OPT_TIME_DLY, & err );
}
}
指定堆栈大小以及优先级放在app_cfg.h
这里就构建了三个单独的任务,大体流程如下
1.定义任务控制块
2.定义各个任务堆栈大小
3,先创建一个任务(任务中的各项指令,堆栈剩余量,优先级,接口函数等等)
4,在上一个创建的任务中添加三个新的任务并且删除任务本身OSTaskDel()(或者挂起)
5,启动最开始创建任务
完整工程下载
选择工程:2.ucos多任务构建