学习链接:ucosIII下创建任务读取并输出DHT11采集到的温湿度数据
相关代码及事项:
首先,需要添加下面两个文件,
其次,main.c 中如下的代码:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "ds18b20.h"
#include "includes.h"
//UCOSIII中以下优先级, 用户程序不能使用.
//将这些优先级分配给了UCOSIII的5个系统内部任务
//优先级0:中断服务服务管理任务 OS_IntQTask()
//优先级1:时钟节拍任务 OS_TickTask()
//优先级2:定时任务 OS_TmrTask()
//优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
//优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
u8 rom1[]={0x28, 0x95, 0x73, 0xe5, 0x07, 0x00, 0x00, 0xd5,}; //64 ROM
u8 rom2[]={0x28, 0x13, 0xbf, 0x45, 0xd4, 0x49, 0x66, 0x4b,};
//任务优先级
#define START_TASK_PRIO 3
// 定义任务堆栈大小
#define START_STK_SIZE 512
// 定义任务控制块
OS_TCB StartTaskTCB; // OS_TCB是结构体类型
// 任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE]; // CPU_STK 是重新定义的数据类型 实质是 unsigned int
// 声明任务函数实体
void start_task(void *p_arg);
//任务优先级
#define LED0_TASK_PRIO 4
//任务堆栈大小
#define LED0_STK_SIZE 128
//任务控制块
OS_TCB Led0TaskTCB;
//任务堆栈 CPU_STK 为 CPU_INT32U 类型, 也就是 unsigned int 类型, 为4 Byte,
CPU_STK LED0_TASK_STK[LED0_STK_SIZE]; // 那么任务堆栈 LED0_TASK_STK 的大小为 128 * 4 = 512 Byte.
//声明任务函数实体
void led0_task(void *p_arg);
//任务优先级
#define LED1_TASK_PRIO 5
//任务堆栈大小
#define LED1_STK_SIZE 128
//任务控制块
OS_TCB Led1TaskTCB;
//任务堆栈
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
//声明任务函数实体
void led1_task(void *p_arg);
//任务优先级
#define FLOAT_TASK_PRIO 6
//任务堆栈大小
#define FLOAT_STK_SIZE 128
//任务控制块
OS_TCB FloatTaskTCB;
//任务堆栈
__align(8) CPU_STK FLOAT_TASK_STK[FLOAT_STK_SIZE];
//声明任务函数实体
void float_task(void *p_arg);
//任务优先级
#define DS18B20_TASK_PRIO 6
//任务堆栈大小
#define DS18B20_STK_SIZE 128
//任务控制块
OS_TCB DS18B20TaskTCB;
//任务堆栈
CPU_STK DS18B20_TASK_STK[DS18B20_STK_SIZE];
//声明任务函数实体
void ds18b20_task(void *p_arg);
int main(void)
{
OS_ERR err; // 定义返回错误的变量
CPU_SR_ALLOC();
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
uart_init(115200); //串口波特率设置
LED_Init(); //LED初始化
printf("System Going !\r\n");
OSInit(&err); //初始化UCOSIII系统及其相关的全局变量
OS_CRITICAL_ENTER();//进入临界区
/*
任务的栈,任务的函数实体,任务的TCB最终需要联系起来才能由系统统一调度。
这个联系工作就由任务创建函数OSTaskCreat来实现。
任务创建函数OSTaskCreat在os_task.c中。
*/
OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
(CPU_CHAR * )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void * )0, //传递给任务函数的参数,无参数指向NULL,即 0
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位, 意思是当任务堆栈剩余多少时, 就表示任务堆栈快用完了。通常为堆栈大小的 1/10
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启UCOSIII, 将不再返回
while(1);
}
//开始任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();// 进入临界区代码须调用该函数来声明一个变量。
p_arg = p_arg; // 因为参数 p_arg 没有使用, 这样做之后是为了防止编译器报警告。
CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建LED0任务
OSTaskCreate ((OS_TCB * ) &Led0TaskTCB,
(CPU_CHAR * ) "led0 task",
(OS_TASK_PTR ) led0_task,
( void * ) 0, // 无参数写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 * )"led1 task",
(OS_TASK_PTR )led1_task,
(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);
//创建浮点数任务
OSTaskCreate((OS_TCB * )&FloatTaskTCB,
(CPU_CHAR * )"float task",
(OS_TASK_PTR )float_task,
(void * )0,
(OS_PRIO )FLOAT_TASK_PRIO,
(CPU_STK * )&FLOAT_TASK_STK[0],
(CPU_STK_SIZE)FLOAT_STK_SIZE/10,
(CPU_STK_SIZE)FLOAT_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 * )&DS18B20TaskTCB,
(CPU_CHAR * )"ds18b20 task",
(OS_TASK_PTR )ds18b20_task,
(void * )0,
(OS_PRIO )DS18B20_TASK_PRIO,
(CPU_STK * )&DS18B20_TASK_STK[0],
(CPU_STK_SIZE)DS18B20_STK_SIZE/10,
(CPU_STK_SIZE)DS18B20_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(); //退出临界区
}
/*
************************************************************************************************************************
* 函数实体 --- 任务是一个独立的函数,函数主体无限循环且不能返回。
************************************************************************************************************************
*/
//led0任务函数
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED0=0;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
LED0=1;
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//led1任务函数
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//浮点测试任务
void float_task(void *p_arg)
{
CPU_SR_ALLOC();
static float float_num=0.01;
while(1)
{
float_num+=0.01f;
OS_CRITICAL_ENTER(); //进入临界区
printf("float_num的值为: %.4f\r\n",float_num);
OS_CRITICAL_EXIT(); //退出临界区
delay_ms(500); //延时500ms
}
}
//DS18B20任务函数
void ds18b20_task(void *p_arg)
{
u16 Temp = 0;
OS_ERR err;
CPU_SR_ALLOC();// 进入临界区代码须调用该函数来声明一个变量。
p_arg = p_arg;
DS18B20_UserConfig();
while(1)
{
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
OS_CRITICAL_ENTER(); //进入临界区
DS18B20_Read_Temperature(rom1,&Temp);
printf("T1- %d.%d%d ,",Temp/100,((Temp%100)/10),(Temp%100%10));
DS18B20_Read_Temperature(rom2,&Temp);
printf("T2- %d.%d%d ,",Temp/100,((Temp%100)/10),(Temp%100%10));
OS_CRITICAL_EXIT(); //退出临界区
}
}