uCOSii任务管理
主要用来测试uCOSii“创建任务,挂起任务,恢复任务,发送删除任务请求,删除任务”。
在os_cfg.h中
#define OS_LOWEST_PRIO 63u
//设置最低优先级为63,则空闲任务优先级OS_TASK_IDLE_PRIO就等于63
//OS_PRIO_SELF为255,因此OS_LOWEST_PRIO<255
注意:
当OS_LOWEST_PRIO=63时,则μC/OS-II有64个优先级,优先级的高低按编号从0(最高)到63(最低)排序。
OS_TASK_IDLE_PRIO为63,是空闲任务优先级,OS_TASK_IDLE_ID为65535。
OS_TASK_STAT_PRIO为62,是统计任务优先级,OS_TASK_STAT_ID为65534。
因此μC/OS-II至少有两个任务,分别是"空闲任务"和"统计任务"。
#define OS_MAX_TASKS 5u
//设置"我的任务总数"为5,其中有两个任务分别是"空闲任务"和"统计任务",因此用户可以占用另外3个任务。
μC/OS-II内部任务堆栈大小定义
#define OS_TASK_TMR_STK_SIZE 128u
//设置"定时器任务堆栈大小"为128,由于它是一个硬件定时器,因此没有优先级,但它有一个任务ID,OS_TASK_TMR_ID为65533
#define OS_TASK_STAT_STK_SIZE 128u
//设置"统计任务堆栈大小"为128,统计任务优先级OS_TASK_STAT_PRIO为62,任务ID为OS_TASK_IDLE_ID,其值为65535
#define OS_TASK_IDLE_STK_SIZE 128u
//设置"空闲任务堆栈大小"为128,空闲任务优先级OS_TASK_IDLE_PRIO为63,其任务ID为OS_TASK_STAT_ID,其值为65534
μC/OS-II任务管理
#define OS_TASK_CHANGE_PRIO_EN 1u
//使能"改变任务优先级函数"OSTaskChangePrio()
#define OS_TASK_CREATE_EN 1u
//使能"创建任务函数"OSTaskCreate()
#define OS_TASK_CREATE_EXT_EN 1u
//使能"创建扩展任务函数"OSTaskCreateExt()
#define OS_TASK_DEL_EN 1u
//使能"删除任务函数"OSTaskDel()
#define OS_TASK_NAME_EN 1u
//使能任务名Enable task names
#define OS_TASK_PROFILE_EN 1u
//使能OS_TCB 结构内部某些变量
#define OS_TASK_QUERY_EN 1u
//使能"获取任务信息函数OSTaskQuery()"
#define OS_TASK_REG_TBL_SIZE 1u
//设置任务变量数组OSTCBRegTbl[]的大小,每个元素为INT32U型
#define OS_TASK_STAT_EN 1u
//使能统计任务函数OSTaskStat(),统计任务每秒运行一次,计算当前系统CPU使用率,结果保存在8位变量OSCPUUsage中
#define OS_TASK_STAT_STK_CHK_EN 1u
//使能检查"统计任务"任务栈的函数OS_TaskStatStkChk()
#define OS_TASK_SUSPEND_EN 1u
//使能挂起任务函数OSTaskSuspend()和恢复任务OSTaskResume()
#define OS_TASK_SW_HOOK_EN 1u
//使能"任务切换函数OSTaskSwHook()"
1、My_Task_Priority.c文件如下:
#include "My_Task_Priority.h"
__align(8) OS_STK START_TASK_STACK[START_TASK_STACK_SIZE];
//声明START_TASK任务堆栈
__align(8) OS_STK LED0_TASK_STACK[LED0_TASK_STACK_SIZE];
//声明LED0_TASK任务堆栈
__align(8) OS_STK LED1_TASK_STACK[LED1_TASK_STACK_SIZE];
//声明LED1_TASK任务堆栈
__align(8) OS_STK KEY_TASK_STACK[KEY_TASK_STACK_SIZE];
//声明KEY_TASK任务堆栈
//如果任务中使用printf来打印浮点数据的话一点要8字节对齐
#define OS_TICK_STEP_EN 1u
// Enable tick stepping feature for uC/OS-View
#define OS_TICKS_PER_SEC 100u
//设置OSTimeDlyHMSM()函数中每秒的节拍数
2、My_Task_Priority.h文件如下:
#ifndef __MY_TASK_PRIORITY_H
#define __MY_TASK_PRIORITY_H
#include "includes.h"
/*
为了保证“启动任务”能够连续运行,必须将“启动任务”的优先级选择为最高。
否则,当“启动任务”创建一个优先级高于自己的任务时,刚刚创建的任务就
会立即进入运行状态,而与这个任务关联的其它任务可能还没有创建,它使
用的通信工具也还没有创建,系统必然出错。
*/
#define START_TASK_PRIORITY 4
//设置START_TASK任务优先级,开始任务的优先级设置为最高
#define START_TASK_STACK_SIZE 192
//设置START_TASK任务堆栈大小,为8的倍数
extern OS_STK START_TASK_STACK[START_TASK_STACK_SIZE];
//START_TASK任务堆栈
#define LED0_TASK_PRIORITY 5
//设置LED0_TASK任务优先级为5
#define LED0_TASK_STACK_SIZE 56
//设置LED0_TASK任务堆栈大小为56,为8的倍数
extern OS_STK LED0_TASK_STACK[LED0_TASK_STACK_SIZE];
//LED0_TASK任务堆栈
#define LED1_TASK_PRIORITY 6
//设置LED1_TASK任务优先级为6
#define LED1_TASK_STACK_SIZE 72
//设置LED1_TASK任务堆栈大小为72,为8的倍数
extern OS_STK LED1_TASK_STACK[LED1_TASK_STACK_SIZE];
//LED1_TASK任务堆栈
#define KEY_TASK_PRIORITY 7
//设置KEY_TASK任务优先级为7
#define KEY_TASK_STACK_SIZE 56
//设置KEY_TASK任务堆栈大小为56,为8的倍数
extern OS_STK KEY_TASK_STACK[KEY_TASK_STACK_SIZE];
//KEY_TASK任务堆栈
#endif
3、Start_Task.c文件如下:
#include "Start_Task.h"
#include "stdio.h"
//使能getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "LED.h"
#include "key.h"
#include "My_Task_Priority.h"
#include "LED0_Task.h"
#include "LED1_Task.h"
#include "Key_Task.h"
void Start_Task(void *pdata);
const char Start_Task_rn_REG[]="\r\n";
const char Start_Task_Initialise_REG[]="Start_Task Initialise";
//Start_Task任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
pdata = pdata;
printf("%s",Start_Task_rn_REG);
printf("%s",Start_Task_Initialise_REG);
LED0_Init();
LED1_Init();
KEY_Init();
//OSTaskCreate()建立一个新任务.可以在多任务环境启动之前.或者运行任务中建立任务;
//注意:ISR中禁止建立任务,一个任务必须为无限循环结构;
OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
OSTaskCreate( LED0_Task,
(void *)0,
(OS_STK*)&LED0_TASK_STACK[LED0_TASK_STACK_SIZE-1],
LED0_TASK_PRIORITY
); //创建LED0_Task任务
OSTaskCreate( LED1_Task,
(void *)0,
(OS_STK*)&LED1_TASK_STACK[LED1_TASK_STACK_SIZE-1],
LED1_TASK_PRIORITY
); //创建LED1_Task任务
OSTaskCreate( Key_Task,
(void *)0,
(OS_STK*)&KEY_TASK_STACK[KEY_TASK_STACK_SIZE-1],
KEY_TASK_PRIORITY
); //创建Key_Task任务
//OSTaskSuspend(START_TASK_PRIO); //挂起起始任务Start_Task()
OSTaskDel (OS_PRIO_SELF); //删除自己
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
4、Start_Task.h文件如下:
#ifndef __Start_Task_H
#define __Start_Task_H
#include "includes.h"
extern void Start_Task(void *pdata);
#endif
5、main.c文件如下:
#include "stm32f10x.h"
//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,
//使能int16_t,int32_t,int64_t
#include "includes.h"
#include "USART1.h"
#include "My_Task_Priority.h"
#include "Start_Task.h"
//创建任务,挂起任务,恢复任务,发送删除任务请求,删除任务
const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{
SystemInit(); //系统初始化72M
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
USART1_Serial_Interface_Enable(115200);
printf("%s",CPU_Reset_REG);//调试串口输出"\r\nCPU reset!\r\n"
SysRstSrcRecord();//系统复位记录
OSInit();//初始化UCOS-II函数
OSTaskCreate(Start_Task,(void *)0,(OS_STK *)&START_TASK_STACK[START_TASK_STACK_SIZE-1],START_TASK_PRIORITY );
//创建启动任务
OSStart();//启动操作系统,开始对任务进行调度管理
}
6、LED0_Task.c文件如下:
#include "LED0_Task.h"
#include "stdio.h"
//使能getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "LED.h"
void LED0_Task(void *pdata);
const char LED0_Task_rn_REG[]="\r\n";
const char LED0_Task_Initialise_REG[]="LED0_Task Initialise";
//LED0_Task任务
void LED0_Task(void *pdata)
{
printf("%s",LED0_Task_rn_REG);
printf("%s",LED0_Task_Initialise_REG);
while(1)
{
LED0=!LED0;
OSTimeDlyHMSM(0,0,0,500);
//500ms闪烁一次,前面“设置OSTimeDlyHMSM()函数中每秒的节拍数为100”
}
}
7、LED0_Task.h文件如下:
#ifndef __LED0_Task_H
#define __LED0_Task_H
#include "includes.h"
extern void LED0_Task(void *pdata);
#endif
8、LED1_Task.c文件如下:
#include "LED1_Task.h"
#include "stdio.h"
//使能getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "LED.h"
void LED1_Task(void *pdata);
const char LED1_Task_rn_REG[]="\r\n";
const char LED1_Task_Initialise_REG[]="LED1_Task Initialise";
//LED1_Task任务
void LED1_Task(void *pdata)
{
printf("%s",LED1_Task_rn_REG);
printf("%s",LED1_Task_Initialise_REG);
while(1)
{
if(OSTaskDelReq(OS_PRIO_SELF)==OS_ERR_TASK_DEL_REQ)
{
OSTaskDel (OS_PRIO_SELF); //删除自己
}
else
{
LED1=!LED1;
OSTimeDlyHMSM(0,0,0,200);
//500ms闪烁一次,前面“设置OSTimeDlyHMSM()函数中每秒的节拍数为100”
}
}
}
9、LED1_Task.h文件如下:
#ifndef __LED1_Task_H
#define __LED1_Task_H
#include "includes.h"
extern void LED1_Task(void *pdata);
#endif
10、Key_Task.c文件如下:
#include "Key_Task.h"
#include "delay.h"
#include "stdio.h"
//使能getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "key.h"
#include "My_Task_Priority.h"
#include "LED1_Task.h"
const char Key_Task_rn_REG[]="\r\n";
const char Key_Task_Initialise_REG[]="Key_Task Initialise";
void Key_Task(void *pdata);
void Key_Task(void *pdata)
{
u8 key;
printf("%s",Key_Task_rn_REG);
printf("%s",Key_Task_Initialise_REG);
while(1)
{
key=KEY_Scan(0);
if(key==Cursor_Up)
{
OSTaskSuspend(LED0_TASK_PRIORITY);
//挂起LED0任务,LED停止闪烁
OSTaskCreate(LED1_Task,(void *)0,(OS_STK*)&LED1_TASK_STACK[LED1_TASK_STACK_SIZE-1],LED1_TASK_PRIORITY);
//重新创建任务LED1
}
else if (key==Cursor_Down)
{
OSTaskResume(LED0_TASK_PRIORITY);
//恢复LED0任务,LED恢复闪烁
}
else if (key==Cursor_Left)
{
OSTaskDelReq(LED1_TASK_PRIORITY);
//发送删除LED1任务请求
}
OSTimeDlyHMSM(0,0,0,100);
//延时100ms,前面“设置OSTimeDlyHMSM()函数中每秒的节拍数为100”
}
}
11、Key_Task.h文件如下:
#ifndef __Key_Task_H
#define __Key_Task_H
#include "includes.h"
extern void Key_Task(void *pdata);
#endif
12、LED.c文件如下:
#include "LED.h"
void LED0_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使用GPIO_InitTypeDef定义一个结构变量GPIO_InitStructure;
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOE, ENABLE );
//在配置外设之前,必须先使能GPIOE的外设时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
//选择第4脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//设置引脚的最高输出速率为50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
//设置引脚工作模式为推挽输出方式
GPIO_Init( GPIOE, &GPIO_InitStructure);
//根据GPIO_InitStructure结构变量指定的参数初始化GPIOE的外设寄存器
}
void LED1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使用GPIO_InitTypeDef定义一个结构变量GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
//使能GPIOE的外设时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//选择第5脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//设置引脚工作模式为推挽输出方式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置引脚的最高输出速率为50MHz
GPIO_Init(GPIOE, &GPIO_InitStructure);
//根据GPIO_InitStructure结构变量指定的参数初始化GPIOE的外设寄存器
}
void LED_Init(void)
{
LED0_Init();
LED1_Init();
}
13、LED.h文件如下:
#ifndef _LED_H
#define _LED_H
#include "stm32f10x.h"
#include "sys.h"
#define LED0 PEout(4) //PE4
#define LED1 PEout(5) //PE5
#define LED0_OFF() GPIO_SetBits(GPIOE,GPIO_Pin_4) //定义LED0关闭
#define LED0_ON() GPIO_ResetBits(GPIOE,GPIO_Pin_4) //定义LED0点亮
#define LED1_OFF() GPIO_SetBits(GPIOE,GPIO_Pin_5) //定义LED1关闭
#define LED1_ON() GPIO_ResetBits(GPIOE,GPIO_Pin_5) //定义LED1点亮
extern void LED0_Init(void);
extern void LED1_Init(void);
extern void LED_Init(void); /* LED 端口初始化 */
#endif
14、KEY.c文件如下:
#include "KEY.h"
#include "delay.h"
void KEY_Init(void);
u8 KEY_Scan(u8 mode);
//函数功能:将PB12,PB13,PB14,PB15,PD8初始化为输入口
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使用GPIO_InitTypeDef定义一个结构变量GPIO_InitStructure;
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB, ENABLE );
//在配置外设之前,必须先使能GPIOB的外设时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
//选择第12,13,14和15脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//设置引脚的最高输出速率为50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
//输入上拉,按钮输入低电平有效
GPIO_Init( GPIOB, &GPIO_InitStructure);
//根据GPIO_InitStructure结构变量指定的参数初始化GPIOB的外设寄存器
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOD, ENABLE );
//在配置外设之前,必须先使能GPIOD的外设时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
//选择第8脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//设置引脚的最高输出速率为50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
//输入上拉,按钮输入低电平有效
GPIO_Init( GPIOD, &GPIO_InitStructure);
//根据GPIO_InitStructure结构变量指定的参数初始化GPIOD的外设寄存器
}
//函数功能:按键扫描,按键检测时间为50ms
u8 KEY_Scan(u8 mode)
{
u8 i;
u8 ch0;
u8 ch1;
u8 retData;
static u8 key_backup=1;//记录按键被释放
if(mode == 1) key_backup=1;//记录按键被释放
retData=0;//假定无按键按下
ch0=0;ch1=0;
if(key_backup==1)
{
if( KEY2==0) ch0=Cursor_Right; //记录按键值
if( KEY3==0) ch0=Cursor_Up; //记录按键值
if( KEY1==0) ch0=Cursor_Left; //记录按键值
if( KEY4==0) ch0=Cursor_Down; //记录按键值
if( KEY5==0) ch0=OK; //记录按键值
}
if(ch0) i=0;
else i=200;
for(;i<20;)
{
i++;
ch1=0;
delay_ms(5);
if(KEY2==0) ch1=Cursor_Right; //记录按键值,向右
if(KEY3==0) ch1=Cursor_Up; //记录按键值,向上
if(KEY1==0) ch1=Cursor_Left; //记录按键值,向左
if(KEY4==0) ch1=Cursor_Down; //记录按键值,向下
if(KEY5==0) ch1=OK; //记录按键值,确认
if(ch1!=ch0) i=100;
}
if(i==20) retData=ch0;
else retData=0;
ch1=0;
if(KEY1==1) ch1=1;
if(KEY2==1) ch1=(u8)(ch1<<1);
if(KEY3==1) ch1=(u8)(ch1<<1);
if(KEY4==1) ch1=(u8)(ch1<<1);
if(KEY5==1) ch1=(u8)(ch1<<1);
if(ch1==0x20) key_backup=1;//记录按键被释放
return retData;
}
15、KEY.h文件如下:
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,
//使能int16_t,int32_t,int64_t
#include "sys.h" //启用bool定义
#define Cursor_Left 1
#define Cursor_Right 2
#define Cursor_Up 3
#define Cursor_Down 4
#define OK 5
#define KEY3 PBin(14) //PB14,向上
#define KEY4 PBin(13) //PB13,向下
#define KEY1 PBin(15) //PB15,向左
#define KEY2 PDin(8) //PD8,向右
#define KEY5 PBin(12) //PB12,确认
extern void KEY_Init(void);
extern u8 KEY_Scan(u8 mode);
#endif
16、USART1.c文件如下:
#include "USART1.h"
#include "stdio.h"
void USART1_GPIO_Config(void);
void USART1_NVIC_Cpnfig(void);
void USART1_Mode_Cpnfig(unsigned int bound);
void USART1_SendByte( unsigned char ch );
void USART1_SendString( char *str);
void USART1_Serial_Interface_Enable(unsigned int bound);
//函数功能:USART1的IO口配置
void USART1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//设置USART1的APB2外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
//选择PIN9,是USART1的TXD
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//设置引脚为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置引脚的最高工作速率为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
//选择PIN10,是USART1的RXD
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//设置引脚为输入悬浮
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置引脚的最高工作速率为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//函数功能:USART1 NVIC 配置
void USART1_NVIC_Cpnfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
//NVIC_PriorityGroup_4设置NVIC中断分组4:表示抢占优先级为4位,取值为0~15,没有响应优先级,取值为0
//NVIC_PriorityGroup_3设置NVIC中断分组3:表示抢占优先级为3位,取值为0~7,响应优先级只有1位,取值为0~1
//NVIC_PriorityGroup_2设置NVIC中断分组3:表示抢占优先级为2位,取值为0~3,响应优先级只有2位,取值为0~3
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
//选择中断源为USART1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
//抢占优先级7
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
}
//函数功能:USART1配置:波特率为9600,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,允许中断,使能串口模块
void USART1_Mode_Cpnfig(unsigned int bound)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断
//当开启串口中断,一定要写其中断服务程序,否则可能会导致FreeRTOS的任务不执行
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//开启接收中断
//当开启串口中断,一定要写其中断服务程序,否则可能会导致uCOS的任务不执行
USART_Cmd(USART1, ENABLE); //使能串口
}
//函数功能:串口4发送一个字节
void USART1_SendByte( unsigned char ch )
{
USART_SendData(USART1, ch);
while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);
//等待发送完成标志位被置1
}
//函数功能:串口4发送字符串
void USART1_SendString( char *str)
{
unsigned int k=0;
do{
USART1_SendByte( *(str + k) );
k++;
}while(*(str + k)!='\0');
}
//函数功能:USART1配置
void USART1_Serial_Interface_Enable(unsigned int bound)
{
USART1_GPIO_Config();
USART1_NVIC_Cpnfig();
USART1_Mode_Cpnfig(bound);
}
//函数功能:USART1中断服务函数
void USART1_IRQHandler(void)
{
unsigned char temp;
(void)temp;//不让temp产生警告
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
temp=USART_ReceiveData(USART1); //从串口读取一个字节;
}
}
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if USART1_VirtualSerialPort == 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
//函数功能:发送ch的值给USART1串口
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (unsigned char) ch);
while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);
//等待发送完成标志位被置1
return ch;
}
#else
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
struct __FILE
{
int handle; /* Add whatever you need here */
};
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
if (DEMCR & TRCENA)
{
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}
#endif
//函数功能:USART1中断服务函数
void UART1_IRQHandler(void)
{
unsigned char temp;
(void)temp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
temp=USART_ReceiveData(USART1); //从串口读取一个字节;
}
}
17、USART1.h文件如下:
#ifndef __USART1_H
#define __USART1_H
#include "stm32f10x.h"
//使能uint8_t,uint16_t,uint32_t,uint64_t,
//使能int8_t,int16_t,int32_t,int64_t
#include "sys.h" //使能bool
#define USART1_VirtualSerialPort 1
//使用USART1的printf功能
//#define USART1_VirtualSerialPort 0 //使用JLINK虚拟串口的printf功能
extern void USART1_SendByte( unsigned char ch );
extern void USART1_SendString( char *str);
extern void USART1_Serial_Interface_Enable(unsigned int bound);
#endif /* __USART1_H */
18、编译结果
19、uCOSii主要用户函数
/*
事件标志管理 (EVENT FLAGS MANAGEMENT)
OSFlagAccept() 检查事件标志组函数(标志组的指针、事件标志位、等待事件标志位的方式、错误码指针)
OSFlagCreate() 建立一个事件标志组(初值、错误码)
OSFlagDel() 删除一个事件标志组(指针、条件值、错误值)
OSFlagPend() 等待事件标志组的事件标志位(事件组指针、需要检查的标志位、等待事件标志位的方式、
允许等待的时钟节拍、出错代码的时钟节拍)
OSFlagPost() 置位或清0事件标志组中的标志位(指针、标志位、条件值、错误码)
OSFlagQuery() 查询事件标志组的当前事件标志状态(事件标志组的指针、错误代码的指针)
*/
/*
消息邮箱管理 (MESSAGE MAILBOX MANAGEMENT)
OSMboxAccept() 查看消息邮箱(消息邮箱指针)
OSMboxCreate() 建立并初始化一个消息邮箱(msg 参数不为空含内容)
OSMboxDel() 删除消息邮箱(消息邮箱指针、删除条件、出错代码指针)
OSMboxPend() 等待一个消息邮箱函数(消息邮箱指针、允许等待的时钟节拍、代码错误指针)
OSMboxPost() 发送消息函数(消息邮箱指针、即将实际发送给任务的消息)
OSMboxPostOpt() 向邮箱发送一则消息(邮箱指针、消息、条件)
OSMboxQuery() 查询一个邮箱的当前状态(信号量指针、状态数据结构指针)
*/
/*
内存管理项 (MEMORY MANAGEMENT)
OSMemCreate() 建立并初始化一块内存区(起始地址、需要的内存块数目、内存块大小、返回错误的指针)
OSMemGet() 从内存区分配一个内存块
OSMemPut() 释放一个内存块,内存块必须释放回原先申请的内存区
OSMemQuery() 得到内存区的信息
*/
/*
互斥型信号量项管理 (MUTUAL EXCLUSION SEMAPHORE MANAGEMENT)
OSMutexAccept() 无等待地获取互斥型信号量[任务不挂起](信号量指针、错误代码)
OSMutexCreate() 建立并初始化一个互斥型信号量(优先级继承优先级(PIP)、出错代码指针)
OSMutexDel() 删除互斥型信号量(信号指针、删除条件、错误指针)
OSMutexPend() 等待一个互斥型信号量(指针、等待超时时限、出错代码指针)
OSMutexPost() 释放一个互斥型信号量(互斥型信号量指针)
OSMutexQuery() 查询一个互斥型信号量的当前状态(互斥型信号量指针、状态数据结构指针)
*/
/*
消息队列管理(MESSAGE QUEUE MANAGEMENT)
OSQAccept() 检查消息队列中是否已经有需要的消息(消息队列的指针)
OSQCreate() 建立一个消息队列(消息内存区的基地址(指针数组)、消息内存区的大小)
OSQDel() 删除一个消息队列(消息队列指针、删除条件、错误指针)
OSQFlush() 清空消息队列(指向得到消息队列的指针)
OSQPend() 任务等待消息队列中的消息(消息队列指针、允许等待的时钟节拍、代码错误指针)
OSQPost() 向消息队列发送一则消息FIFO(消息队列指针、发送的消息)
OSQPostFront() 向消息队列发送一则消息LIFO(消息队列指针、发送的消息)
OSQPostOpt() 向消息队列发送一则消息LIFO(消息队列指针、发送的消息、发送条件)
OSQQuery() 查询一个消息队列的当前状态(信号量指针、状态数据结构指针)
*/
/*
信号量管理 (SEMAPHORE MANAGEMENT)
OSSemAccept() 无条件地等待请求一个信号量函数
OSSemCreate() 建立并初始化一个信号量(输入一个信号量值)
OSSemDel() 删除一个信号量(信号指针、删除条件、错误指针)
OSSemPend() 等待一个信号量函数(信号量指针、允许等待的时钟节拍、代码错误指针)
OSSemPost() 发出一个信号量函数(信号量指针)
OSSemQuery() 查询一个信号量的当前状态(信号量指针、状态数据结构指针)
*/
/*
任务管理(TASK MANAGEMENT)
OSTaskChangePrio(任务旧的优先级,任务新的优先级),改变一个任务的优先级
OSTaskCreate(任务代码指针,传递参数指针,分配任务堆栈栈顶指针,任务优先级),建立任务
OSTaskCreateExt() 建立扩展任务(任务代码指针/传递参数指针/分配任务堆栈栈顶指针/分配任务优先级
//(未来的)优先级标识(与优先级相同)/分配任务堆栈栈底指针/指定堆栈的容量(检验用)
//指向用户附加的数据域的指针/建立任务设定选项)
OSTaskDel(任务优先级),删除任务
OSTaskDelReq(任务优先级),发送删除任务请求,请求某个任务删除自己或者其它任务
OSTaskStkChk() 检查任务堆栈状态(任务优先级、检验堆栈数据结构)
OSTaskSuspend(任务优先级),无条件挂起一个任务()
OSTaskResume(任务优先级),唤醒一个用OSTaskSuspend()函数挂起的任务
OSTaskQuery(任务指针,保存数据结构指针),获取任务信息,获得自身或其它应用任务的信息
OSTaskStat(),统计任务每秒运行一次,计算当前系统CPU使用率,结果保存在8位变量OSCPUUsage中
OSTaskSwHook(),任务切换函数App_TaskSwHook()
*/
/*
时钟管理项(TIME MANAGEMENT)
OSTimeDly() 任务延时函数(时钟节拍数)
OSTimeDlyHMSM() 将一个任务延时若干时间(设定时、分、秒、毫秒)
OSTimeDlyResume() 唤醒一个用OSTimeDly()或OSTimeDlyHMSM()函数的任务(优先级)
OSTimeGet() 获取当前系统时钟数值
OSTimeSet() 设置当前系统时钟数值
*/
/*
混杂函数定义
OSInit() 初始化UCOS-II函数
OSIntEnter() 中断函数正在执行
OSIntExit() 中断函数已经完成(脱离中断)
OSSchedLock()给调度器上锁,函数允许应用程序锁定当前任务不被其它任务抢占,
OSSchedUnlock() 给调度器解锁
确保OSSchedLock()和OSSchedUnlock()函数成对出现;
注意:在OSSchedLock()和OSSchedUnlock()之键,不调用诸如OSFlagPend()、OSMboxPend()、OSMutexPend()、OSQPend()、OSSemPend()
之类的事件等待函数!因为调度器被上锁了,其它任务不会给当前任务发送消息。
OSStart() 启动多个任务
OSStatInit() 统计任务初始化
OSVersion() 获得版本号
*/
/*
内部函数原型 INTERNAL FUNCTION PROTOTYPES
你在应用程序中不能使用它们 (Your application MUST NOT call these functions)
OS_Dummy() 建立一个虚拟函数
OS_EventTaskRdy() 使一个任务进入就绪态(OS_EVENT *pevent, void *msg, INT8U msk)
OS_EventTaskWait() 使一个任务进入等待某事件发生状态(ECB指针)
OS_EventTO() 由于超时而将任务置为就绪态(ECB指针)
OS_EventWaitListInit()事件控制块列表初始化(事件控制块指针)
OS_FlagInit() 初始化事件标志结构
OS_FlagUnlink() 把这个OS_FLAG_NODE从事件标志组的等待任务链表中删除(OS_FLAG_NODE *pnode)
OS_MemInit() 初始化内存分区
OS_QInit() 初始化事件队列结构
OS_Sched() 任务调度函数
OS_TaskIdle() 空闲任务函数(指向一个数据结构)
OS_TaskStat() 统计任务(指向一个数据结构)
OS_TCBInit() 初始化任务控制块TCB(优先级指针、栈顶指针、栈底指针、任务标志符、堆栈容量、扩展指针、选择项)
*/