OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5323|回复: 1

想用一个任务释放信号量来控制多个任务接收信号量

[复制链接]

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
发表于 2021-2-3 09:49:08 | 显示全部楼层 |阅读模式
1金钱
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

#include "key.h"
#include "includes.h"
/************************************************
ALIENTEK 精英版STM32开发板UCOS实验
例10-3 UCOSIII 信号量用于任务同步
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司  
作者:正点原子 @ALIENTEK
************************************************/

//UCOSIII中以下优先级用户程序不能使用,ALIENTEK
//将这些优先级分配给了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()
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com  
//广州市星翼电子科技有限公司  
//作者:正点原子 @ALIENTEK

//任务优先级
#define START_TASK_PRIO                3
//任务堆栈大小       
#define START_STK_SIZE                 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈       
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define TASK1_TASK_PRIO                4
//任务堆栈大小       
#define TASK1_STK_SIZE                 128
//任务控制块
OS_TCB Task1_TaskTCB;
//任务堆栈       
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);


//任务优先级
#define TASK2_TASK_PRIO                5
//任务堆栈大小       
#define TASK2_STK_SIZE                 128
//任务控制块
OS_TCB Task2_TaskTCB;
//任务堆栈       
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
void task2_task(void *p_arg);


//任务优先级
#define TASK3_TASK_PRIO                6
//任务堆栈大小       
#define TASK3_STK_SIZE                 128
//任务控制块
OS_TCB Task3_TaskTCB;
//任务堆栈       
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];
void task3_task(void *p_arg);


OS_SEM        SYNC_SEM;                //定义一个信号量,用于任务同步

//主函数
int main(void)
{
        OS_ERR err;
        CPU_SR_ALLOC();
       
        delay_init();  //时钟初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
        uart_init(115200);   //串口初始化
        LED_Init();         //LED初始化       

        KEY_Init();                        //按键初始化
       

       
        OSInit(&err);                            //初始化UCOSIII
        OS_CRITICAL_ENTER();        //进入临界区                         
        //创建开始任务
        OSTaskCreate((OS_TCB         * )&StartTaskTCB,                //任务控制块
                                 (CPU_CHAR        * )"start task",                 //任务名字
                 (OS_TASK_PTR )start_task,                         //任务函数
                 (void                * )0,                                        //传递给任务函数的参数
                 (OS_PRIO          )START_TASK_PRIO,     //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],        //任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/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
}


//开始任务函数
void start_task(void *p_arg)
{
        OS_ERR err;
        CPU_SR_ALLOC();
        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();        //进入临界区
        //创建一个信号量
        OSSemCreate ((OS_SEM*        )&SYNC_SEM,
                 (CPU_CHAR*        )"SYNC_SEM",
                 (OS_SEM_CTR)2,               
                 (OS_ERR*        )&err);
        //创建TASK1任务
        OSTaskCreate((OS_TCB         * )&Task1_TaskTCB,               
                                 (CPU_CHAR        * )"Task1 task",                
                 (OS_TASK_PTR )task1_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )TASK1_TASK_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],       
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,       
                 (CPU_STK_SIZE)TASK1_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);                       
        //创建TASK2任务
        OSTaskCreate((OS_TCB         * )&Task2_TaskTCB,               
                                 (CPU_CHAR        * )"Task2 task",                
                 (OS_TASK_PTR )task2_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )TASK2_TASK_PRIO,     
                 (CPU_STK   * )&TASK2_TASK_STK[0],       
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,       
                 (CPU_STK_SIZE)TASK2_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);               
        //创建TASK2任务
        OSTaskCreate((OS_TCB         * )&Task3_TaskTCB,               
                                 (CPU_CHAR        * )"Task3 task",                
                 (OS_TASK_PTR )task3_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )TASK3_TASK_PRIO,     
                 (CPU_STK   * )&TASK3_TASK_STK[0],       
                 (CPU_STK_SIZE)TASK3_STK_SIZE/10,       
                 (CPU_STK_SIZE)TASK3_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_CRITICAL_EXIT();        //退出临界区
        OSTaskDel((OS_TCB*)0,&err);        //删除start_task任务自身
}


//任务1的任务函数
void task1_task(void *p_arg)
{
        u8 key;
        OS_ERR err;
        while(1)
        {
                OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err);       
//                key = KEY_Scan(0);  //扫描按键
//                if(key==WKUP_PRES)       
//                {
                OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err);//发送信号量
//                       
//                }
                printf("任务1\r\n");
                OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_PERIODIC,&err);   //延时10ms
        }
}

//任务2的任务函数
void task2_task(void *p_arg)
{       
        u8 num;
        OS_ERR err;
        while(1)
        {
                OSSemPend(&SYNC_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); //请求信号量
                num++;
                printf("single1 Rec\r\n");
                LED1 = ~LED1;
                //OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err);//发送信号量
                OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_PERIODIC,&err);   //延时1s
        }
}
void task3_task(void *p_arg)
{       
        u8 num;
        OS_ERR err;
        while(1)
        {
                OSSemPend(&SYNC_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); //请求信号量
                num++;
                printf("single2 Rec\r\n");
                LED1 = ~LED1;
                //OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err);//发送信号量
                OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_PERIODIC,&err);   //延时1s
        }
}
void USART1_IRQHandler(void)        
{
        unsigned char r;
        OS_ERR err;
        OSIntEnter();
       
        if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET)
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志
                //printf("串口1中断接收任务产生\r\n");
                r=USART_ReceiveData(USART1);
               
       
                //printf("数据接收");       
                printf("数据接收完成,释放一个任务信号量到数据分析任务\r\n");
//                        USART1RecFlag=1;
                OSTaskSemPost(&Task1_TaskTCB,OS_OPT_POST_NONE,&err);
               
        }       
               
       
        OSIntExit();
}

我把信号量计数设置成2,然后串口中断接收到数据就立即发送任务信号量到任务1,然后在任务1中释放信号量,任务2和任务3等待信号量。目的是想在任务1中释放信号量任务2和任务3都能接收到信号量从而实现任务2和任务3同步。目前这个程序的状态是上电任务2和任务3都运行了一次,然后串口接收到数据后任务1释放了一个信号量。任务2运行,任务3得不到信号量不运行。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2021-2-8 00:36:45 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 16:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表