|
- /***********************头文件****************************/
- #include "main.h"
- #include "sys.h"
- #include "delay.h"
- #include "led.h"
- #include "exti.h"
- #include "includes.h"
- #include "timer.h"
-
- /***********************指针变量****************************/
- OS_EVENT * sem_TaskC; //任务C信号量指针
- OS_EVENT * sem_Mutex; //互斥信号量
- OS_EVENT * q_Msg; //消息队列
- void * MsgGrp[256]; //消息队列存储地址,最大支持256个消息
-
- /***********************全局变量****************************/
- u16 *I3_Num;
- static u16 I3_InNum; // 存储邮箱消息
- u32 PB4_Num; //存储按键次数
- u8 flag_Exit; //执行按键函数中断标志位
- uint8_t taskA_Num = 0 ;//记录任务A小灯闪烁次数
-
- /**********************START 任务****************************/
- #define START_TASK_PRIO 3 //开始任务的优先级
- #define START_STK_SIZE 128 //设置任务堆栈大小
- OS_STK START_TASK_STK[START_STK_SIZE];//任务任务堆栈
- void start_task(void *pdata);//任务函数
-
- /**********************任务A*********************************/
- #define LEDA_TASK_PRIO 4 //设置任务优先级
- #define LEDA_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDA_TASK_STK[LEDA_STK_SIZE]; //任务堆栈
- void ledA_task(void *pdata); //任务函数
-
- /**********************任务B********************************/
- #define LEDB_TASK_PRIO 5 //设置任务优先级
- #define LEDB_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDB_TASK_STK[LEDB_STK_SIZE]; //任务堆栈
- void ledB_task(void *pdata); //任务函数
-
- /**********************任务C********************************/
- #define LEDC_TASK_PRIO 6 //设置任务优先级
- #define LEDC_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDC_TASK_STK[LEDC_STK_SIZE]; //任务堆栈
- void ledC_task(void *pdata); //任务函数
-
- /**********************任务D********************************/
- #define LEDD_TASK_PRIO 9 //设置任务优先级
- #define LEDD_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDD_TASK_STK[LEDD_STK_SIZE]; //任务堆栈
- void ledD_task(void *pdata); //任务函数
-
- /*********************任务E********************************/
- #define LEDE_TASK_PRIO 10 //设置任务优先级
- #define LEDE_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDE_TASK_STK[LEDE_STK_SIZE]; //任务堆栈
- void ledE_task(void *pdata); //任务函数
-
- /*********************任务F ********************************/
- #define LEDF_TASK_PRIO 7 //设置任务优先级
- #define LEDF_STK_SIZE 128 //设置任务堆栈大小
- OS_STK LEDF_TASK_STK[LEDF_STK_SIZE]; //任务堆栈
- void ledF_task(void *pdata); //任务函数
-
- /********************按键检测任务****************************/
- #define KEYG_TASK_PRIO 11 //设置任务优先级
- #define KEYG_STK_SIZE 128 //设置任务堆栈大小
- OS_STK KEYG_TASK_STK[KEYG_STK_SIZE]; //任务堆栈
- void keyG_task(void *pdata); //任务函数
-
-
- /********************主函数****************************/
- int main(void)
- {
-
- HSI_SetSysClock(16, 336, 2, 7); //使用HSI配置系统时钟为168M
- TIM3_Int_Init(4999, 8399); //时钟初始化
- delay_init(168); //延时初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
- LED_Init(); //LED初始化
- EXTIX_Init(); //外部中断初始化
- OSInit(); //UCOS初始化
- OSTaskCreate(start_task, (void*)0, (OS_STK*)&START_TASK_STK[START_STK_SIZE-1], START_TASK_PRIO); //创建开始任务
- OSStart(); //开始任务
- }
-
- /******************************************************
- //创建UCOS开始任务
- //提供外设初始化、创建信号量、创建邮箱、创建消息队列
- 、创建信号量集、创建任务、初始化统计任务等等
- ********************************************************/
- void start_task(void *pdata)
- {
- OS_CPU_SR cpu_sr = 0;
- pdata=pdata;
- u8 err; //错误标志码
- sem_TaskC = OSSemCreate(0); //创建信号量
- msg_TaskC = OSMboxCreate((void*) 0);//创建消息邮箱
- sem_Mutex = OSMutexCreate(8, &err); //创建互斥信号量 设置优先级为8
- q_Msg = OSQCreate(&MsgGrp[0],256); //创建消息队列
- OSStatInit(); //开启统计任务
- OS_ENTER_CRITICAL(); //进入临界区(关闭中断)
- OSTaskCreate(ledA_task,(void*)0,(OS_STK*)&LEDA_TASK_STK[LEDA_STK_SIZE-1],LEDA_TASK_PRIO);//创建任务A
- OSTaskCreate(ledB_task,(void*)0,(OS_STK*)&LEDB_TASK_STK[LEDB_STK_SIZE-1],LEDB_TASK_PRIO);//创建任务B
- OSTaskCreate(ledC_task,(void*)0,(OS_STK*)&LEDC_TASK_STK[LEDC_STK_SIZE-1],LEDC_TASK_PRIO);//创建任务C
- OSTaskCreate(ledD_task,(void*)0,(OS_STK*)&LEDD_TASK_STK[LEDD_STK_SIZE-1],LEDD_TASK_PRIO);//创建任务D
- OSTaskCreate(ledE_task,(void*)0,(OS_STK*)&LEDE_TASK_STK[LEDE_STK_SIZE-1],LEDE_TASK_PRIO);//创建任务E
- OSTaskCreate(ledF_task,(void*)0,(OS_STK*)&LEDF_TASK_STK[LEDF_STK_SIZE-1],LEDF_TASK_PRIO);//创建任务F
- OSTaskCreate(keyG_task,(void*)0,(OS_STK*)&KEYG_TASK_STK[KEYG_STK_SIZE-1],KEYG_TASK_PRIO);//创建任务G
- OSTaskSuspend(START_TASK_PRIO);//挂起开始任务
- OS_EXIT_CRITICAL(); //退出临界区(开中断)
- }
-
- /********************任务A任务函数****************************
- 1. 任务A小灯以1Hz的频率闪烁
- 2. 当任务A的小灯闪烁10次过后,任务A挂起,任务B执行
- *************************************************************/
- void ledA_task(void *pdata)
- {
- pdata=pdata;
- NVIC_InitTypeDef NVIC_InitStructure;
- while(1)
- {
- if(21 <= taskA_Num)
- {
- LED0 = 1;
- NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
- NVIC_InitStructure.NVIC_IRQChannelCmd=DISABLE;
- NVIC_Init(&NVIC_InitStructure);
- OSTaskSuspend(LEDA_TASK_PRIO);//当小灯闪烁10次后,挂起任务A
- }
- }
- }
-
- /********************任务B任务函数****************************
- 1. 任务B小灯以10Hz的频率闪烁
- 2. 当任务B的小灯闪烁20次过后,任务B挂起,给任务C发信号量
- *************************************************************/
- void ledB_task(void *pdata)
- {
- pdata=pdata;
- u8 taskB_Num = 0 ;//记录任务A小灯闪烁次数
- while(1)
- {
- LED1 = 0;
- delay_ms(50);
- LED1 = 1;
- delay_ms(50);
- taskB_Num++;
- if(20 <= taskB_Num)
- {
- OSSemPost(sem_TaskC);//给任务C发信号量
- OSTaskSuspend(LEDB_TASK_PRIO);//当小灯闪烁20次后,挂起任务B
- }
- }
- }
-
- /********************任务C任务函数****************************
- 1. 任务C接收到任务B的信号量时,任务C执行
- 2. 对于外部中断的触发次数进行计数,并通过邮箱发送给任务C
- 3. 中断次数小于5时,任务C小灯以1Hz频率闪烁,
- 中断次数大于等于5,且小于10时,任务C小灯以10Hz频率闪烁
- 4. 任务C把通过邮箱接收到的数据填入队列
- *************************************************************/
- void ledC_task(void *pdata)
- {
- pdata=pdata;
- u8 err;
- while (1)
- {
- OSSemPend(sem_TaskC, 0, &err); //请求信号量
- I3_Num = (u16* )OSMboxPend(msg_TaskC, 10, &err); //请求邮箱
- if (I3_Num != NULL) //如果消息邮箱没有消息,返回空指针。
- {
- I3_InNum = *I3_Num;
- OSQPost(q_Msg, I3_Num); //发送队列消息
- }
- if (I3_InNum < 5)
- {
- LED2 = 0;
- delay_ms(500);
- LED2 = 1;
- delay_ms(500);
- }
- else if (I3_InNum >= 5 && I3_InNum < 10)
- {
- LED2 = 0;
- delay_ms(50);
- LED2 = 1;
- delay_ms(50);
- }
- OSSemPost(sem_TaskC);
- }
- }
-
- /********************任务D任务函数****************************
- 1、任务D获取到互斥量时任务D小灯常亮,未获取到时任务D小灯长灭
- 2、当外部输入1为高电平时,任务D尝试获取互斥量,
- 当外部输入1为低电平时,任务D释放互斥量
- *************************************************************/
- void ledD_task(void *pdata)
- {
- pdata=pdata;
- u8 err;
- while(1)
- {
- if (KEY0 == 0) //外部输入1(PI_15)为高电平,尝试获取互斥信号量
- {
- OSMutexPend(sem_Mutex, 10, &err);
- if (err != 10u)
- {
- LED3 = 0;
- }
- }
- if (KEY0 == 1) //外部输入1为低电平,释放互斥信号量
- {
- OSMutexPost(sem_Mutex);
- LED3 = 1;
-
- }
- delay_ms(10); //任务调度
- }
- }
-
- /********************任务E任务函数****************************
- 1、任务E获取到互斥量时任务E小灯常亮,未获取到时任务E小灯长灭
- 2、当外部输入2为高电平时,任务E尝试获取互斥量,
- 当外部输入2为低电平时,任务E释放互斥量
- *************************************************************/
- void ledE_task(void *pdata)
- {
- pdata=pdata;
- u8 err;
- while(1)
- {
- if (KEY1 == 0) //外部输入2为高电平,尝试获取互斥信号量
- {
- OSMutexPend(sem_Mutex, 10, &err);
- if (err != 10u)
- {
- LED4 = 0;
- }
- }
- if (KEY1 == 1) //外部输入2为低电平,释放互斥信号量
- {
- OSMutexPost(sem_Mutex);
- LED4 = 1;
- }
- delay_ms(10);
- }
- }
-
- /********************任务F任务函数****************************
- 1、任务E获取到互斥量时任务E小灯常亮,未获取到时任务E小灯长灭
- 2、当外部输入2为高电平时,任务E尝试获取互斥量,
- 当外部输入2为低电平时,任务E释放互斥量
- *************************************************************/
- void ledF_task(void *pdata)
- {
- pdata=pdata;
- u8 err;
- u8 num;
- u8 *p;
- while(1)
- {
- p = OSQPend(q_Msg, 0, &err); //请求消息队列
- if (p != NULL)
- {
- num = *p % 8;
- }
- switch (num)
- {
- case 0:
- LED5 = 1; LED6 = 1; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 1:
- LED5 = 0; LED6 = 1; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 2:
- LED5 = 0; LED6 = 0; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 3:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 4:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 1; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 5:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 1; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 6:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 1;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 7:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 8:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 0; LED13 = 1; LED14 = 1; LED15 = 1;
- break;
- case 9:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 0; LED13 = 0; LED14 = 1; LED15 = 1;
- break;
- case 10:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 1;
- break;
- case 11:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 0;
- break;
- default:
- LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
- LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 0;
- break;
- }
- delay_ms(20); //任务调度
- }
- }
-
-
-
- //按键检测任务
- void keyG_task(void *pdata)
- {
- pdata=pdata;
- NVIC_InitTypeDef NVIC_InitStructure;
- while (1)
- {
- if (flag_Exit == 1)
- {
- NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
- NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;//使能外部中断通道
- NVIC_Init(&NVIC_InitStructure);//配置
- PB4_Num++;
- OSMboxPost(msg_TaskC, &PB4_Num); //发送邮箱消息
- delay_ms(500);
- NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
- NVIC_Init(&NVIC_InitStructure);//配置
- flag_Exit = 0;
- }
- }
-
- }
-
- //外部中断4服务程序---由PB4下降沿触发
- //中断服务程序不能调用可能会导致任务调度的函数
- void EXTI4_IRQHandler(void)
- {
-
- OSIntEnter(); //进入中断处理
- flag_Exit = 1;
- EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位
-
- OSIntExit(); //退出中断处理
- }
-
-
- //定时器3中断服务函数
- void TIM3_IRQHandler(void)
- {
- OSIntEnter(); //进入中断处理
- if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
- {
- LED0=!LED0;//LED0翻转
- taskA_Num++;
- }
- TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
- OSIntExit(); //退出中断处理
- }
-
-
-
-
-
-
-
|