UCOSii中的信号量

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_35675731/article/details/89408009

       任务间简单通个信,A告诉B你LED亮一下。这种问题可以用信号量来处理,UCOSii中关于信号量的函数也就八个,今天简单总结下。

  • 函数列表
/*
*********************************************************************************************************
*                                           CREATE A SEMAPHORE
*
* Description: This function creates a semaphore.
*
* Arguments  : cnt           is the initial value for the semaphore.  If the value is 0, no resource is
*                            available (or no event has occurred).  You initialize the semaphore to a
*                            non-zero value to specify how many resources are available (e.g. if you have
*                            10 resources, you would initialize the semaphore to 10).
*
* Returns    : != (void *)0  is a pointer to the event control block (OS_EVENT) associated with the
*                            created semaphore
*              == (void *)0  if no event control blocks were available
*********************************************************************************************************
*/
OS_EVENT  *OSSemCreate (INT16U cnt);


/*
*********************************************************************************************************
*                                         POST TO A SEMAPHORE
*
* Description: This function signals a semaphore
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired
*                            semaphore.
*
* Returns    : OS_ERR_NONE         The call was successful and the semaphore was signaled.
*              OS_ERR_SEM_OVF      If the semaphore count exceeded its limit.  In other words, you have
*                                  signalled the semaphore more often than you waited on it with either
*                                  OSSemAccept() or OSSemPend().
*              OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore
*              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
*********************************************************************************************************
*/
INT8U  OSSemPost (OS_EVENT *pevent);


/*
*********************************************************************************************************
*                                           PEND ON SEMAPHORE
*
* Description: This function waits for a semaphore.
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired
*                            semaphore.
*
*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
*                            wait for the resource up to the amount of time specified by this argument.
*                            If you specify 0, however, your task will wait forever at the specified
*                            semaphore or, until the resource becomes available (or the event occurs).
*
*              perr          is a pointer to where an error message will be deposited.  Possible error
*                            messages are:
*
*                            OS_ERR_NONE         The call was successful and your task owns the resource
*                                                or, the event you are waiting for occurred.
*                            OS_ERR_TIMEOUT      The semaphore was not received within the specified
*                                                'timeout'.
*                            OS_ERR_PEND_ABORT   The wait on the semaphore was aborted.
*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
*                                                would lead to a suspension.
*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
*                            OS_ERR_PEND_LOCKED  If you called this function when the scheduler is locked
*
* Returns    : none
*********************************************************************************************************
*/
void  OSSemPend (OS_EVENT  *pevent,
                 INT32U     timeout,
                 INT8U     *perr);


/*
*********************************************************************************************************
*                                      ABORT WAITING ON A SEMAPHORE
*
* Description: This function aborts & readies any tasks currently waiting on a semaphore.  This function
*              should be used to fault-abort the wait on the semaphore, rather than to normally signal
*              the semaphore via OSSemPost().
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired
*                            semaphore.
*
*              opt           determines the type of ABORT performed:
*                            OS_PEND_OPT_NONE         ABORT wait for a single task (HPT) waiting on the
*                                                     semaphore
*                            OS_PEND_OPT_BROADCAST    ABORT wait for ALL tasks that are  waiting on the
*                                                     semaphore
*
*              perr          is a pointer to where an error message will be deposited.  Possible error
*                            messages are:
*
*                            OS_ERR_NONE         No tasks were     waiting on the semaphore.
*                            OS_ERR_PEND_ABORT   At least one task waiting on the semaphore was readied
*                                                and informed of the aborted wait; check return value
*                                                for the number of tasks whose wait on the semaphore
*                                                was aborted.
*                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
*
* Returns    : == 0          if no tasks were waiting on the semaphore, or upon error.
*              >  0          if one or more tasks waiting on the semaphore are now readied and informed.
*********************************************************************************************************
*/
INT8U  OSSemPendAbort (OS_EVENT  *pevent,
                       INT8U      opt,
                       INT8U     *perr);

/*
*********************************************************************************************************
*                                           ACCEPT SEMAPHORE
*
* Description: This function checks the semaphore to see if a resource is available or, if an event
*              occurred.  Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
*              resource is not available or the event did not occur.
*
* Arguments  : pevent     is a pointer to the event control block
*
* Returns    : >  0       if the resource is available or the event did not occur the semaphore is
*                         decremented to obtain the resource.
*              == 0       if the resource is not available or the event did not occur or,
*                         if 'pevent' is a NULL pointer or,
*                         if you didn't pass a pointer to a semaphore
*********************************************************************************************************
*/
INT16U  OSSemAccept (OS_EVENT *pevent);


/*
*********************************************************************************************************
*                                         DELETE A SEMAPHORE
*
* Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired
*                            semaphore.
*
*              opt           determines delete options as follows:
*                            opt == OS_DEL_NO_PEND   Delete semaphore ONLY if no task pending
*                            opt == OS_DEL_ALWAYS    Deletes the semaphore even if tasks are waiting.
*                                                    In this case, all the tasks pending will be readied.
*
*              perr          is a pointer to an error code that can contain one of the following values:
*                            OS_ERR_NONE             The call was successful and the semaphore was deleted
*                            OS_ERR_DEL_ISR          If you attempted to delete the semaphore from an ISR
*                            OS_ERR_INVALID_OPT      An invalid option was specified
*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the semaphore
*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a semaphore
*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
*
* Returns    : pevent        upon error
*              (OS_EVENT *)0 if the semaphore was successfully deleted.
*
* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
*                 the semaphore MUST check the return code of OSSemPend().
*              2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
*                 they check 'pevent' to see that it's a NULL pointer.
*              3) This call can potentially disable interrupts for a long time.  The interrupt disable
*                 time is directly proportional to the number of tasks waiting on the semaphore.
*              4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
*                 applications where the semaphore is used for mutual exclusion because the resource(s)
*                 will no longer be guarded by the semaphore.
*********************************************************************************************************
*/
OS_EVENT  *OSSemDel (OS_EVENT  *pevent,
                     INT8U      opt,
                     INT8U     *perr);


/*
*********************************************************************************************************
*                                          QUERY A SEMAPHORE
*
* Description: This function obtains information about a semaphore
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired
*                            semaphore
*
*              p_sem_data    is a pointer to a structure that will contain information about the
*                            semaphore.
*
* Returns    : OS_ERR_NONE         The call was successful and the message was sent
*              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non semaphore.
*              OS_ERR_PEVENT_NULL  If 'pevent'     is a NULL pointer.
*              OS_ERR_PDATA_NULL   If 'p_sem_data' is a NULL pointer
*********************************************************************************************************
*/
INT8U  OSSemQuery (OS_EVENT     *pevent,
                   OS_SEM_DATA  *p_sem_data);

/*
*********************************************************************************************************
*                                              SET SEMAPHORE
*
* Description: This function sets the semaphore count to the value specified as an argument.  Typically,
*              this value would be 0.
*
*              You would typically use this function when a semaphore is used as a signaling mechanism
*              and, you want to reset the count value.
*
* Arguments  : pevent     is a pointer to the event control block
*
*              cnt        is the new value for the semaphore count.  You would pass 0 to reset the
*                         semaphore count.
*
*              perr       is a pointer to an error code returned by the function as follows:
*
*                            OS_ERR_NONE          The call was successful and the semaphore value was set.
*                            OS_ERR_EVENT_TYPE    If you didn't pass a pointer to a semaphore.
*                            OS_ERR_PEVENT_NULL   If 'pevent' is a NULL pointer.
*                            OS_ERR_TASK_WAITING  If tasks are waiting on the semaphore.
*********************************************************************************************************
*/
void  OSSemSet (OS_EVENT  *pevent,
                INT16U     cnt,
                INT8U     *perr);





使用 

1.创建信号量

2.发送信号量

3.等待信号量

这三个几乎应付了绝大部分场景了

OS_EVENT  *OSSemCreate (INT16U cnt);

INT8U  OSSemPost (OS_EVENT *pevent);

void  OSSemPend (OS_EVENT  *pevent,
                 INT32U     timeout,
                 INT8U     *perr);

//结构体指针声明
OS_EVENT *sem;

//信号量初始,10以下自己随意定义
INT8U cnt = 0;

int main()
{
	/*
	LED_Init();
	OSInit();
	OSTaskCreate(start_task,(void *)0, (OS_STK *)&START_TASK_STK[START_STK_SIZE-1],\
		START_TASK_PRID);
	OSStart();
	*/
}

void start_task(void* pdata)
{
	/*
	OS_CPU_SR cpu_sr = 0;
	pdata = pdata;
	OSStatInit();
	OS_ENTER_CRITICAL();
	OSTaskCreate(led0_task,(void*)0, (OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],\
				 LED0_TASK_PRIO);
	OSTaskCreate(led1_task,(void*)0, (OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],\
				 LED1_TASK_PRIO);
	OSTaskSuspend(START_TASK_PRID);
	*/
	sem = OSSemCreate(cnt); //初始化信号量指针
	/*
	OS_EXIT_CRITICAL();
	*/
}

void led0_task(void* pdata)
{
	/*
	uint8_t num = 0;
	while(1)
	{
		num++;
		LED0 = 0;
		delay_ms(80);
		LED0 = 1;
		if((num % 10 == 0))
		{
			*/
			OSSemPost(sem); //发送信号量
			/*
			printf("发送信号%d 次\r\n", num/10);
		}
		delay_ms(400);
	}
	*/
}

void led1_task(void* pdata)
{
	INT8U err = 0;
	/*
	while(1)
	{
		*/
		OSSemPend(sem, 0, &err); //一直等待信号到来,等待超时0
		/*
		LED1 = 0;
		delay_ms(300);		
		LED1 = 1;
		delay_ms(300);
	}
	*/
}

4.接收信号量

INT16U  OSSemAccept (OS_EVENT *pevent);

 基本代码不变,这里只改动task1的代码

void led1_task(void* pdata)
{
	INT8U ac;
	/*
	while(1)
	{
	*/
		ac = OSSemAccept(sem);
		if(ac == 1){ //接受成功返回1
			/*
			printf("我已经接收到信号了\r\n");
			LED1 = 0;
			delay_ms(300);
			LED1 = 1;
			delay_ms(300);
			*/
		}

		else//接收不成功返回0
		{
			/*
			printf("我还没成功的接收到信号了呢\r\n");
			delay_ms(500);
			*/
		}
/*
	}
	*/
}

5.删除信号量

OS_EVENT  *OSSemDel (OS_EVENT  *pevent,
                     INT8U      opt,
                     INT8U     *perr);
void led0_task(void* pdata)
{
	uint8_t num = 0, err = 0;
	/*
	while(1)
	{
		num++;
		LED0 = 0;
		delay_ms(80);
		LED0 = 1;
		if(num == 10)
		{
			*/
			//删除后sem为null
			sem = OSSemDel(sem, OS_DEL_ALWAYS,&err);
			/*
			printf("我已经删除了信号sem\r\n");
		}
		delay_ms(400);
	}
	*/
}

void led1_task(void* pdata)
{
	INT8U err = 0;
	/*
	while(1)
	{
		*/
		if(sem != NULL){ //判断信号量指针是否为空,是的话代表已经被删除了
			/*
		OSSemPend(sem, 0, &err);
		LED1 = 0;
		delay_ms(300);
		LED1 = 1;
		delay_ms(300);
		*/
		}

		else{
			/*
			printf("任务被删除了\r\n");
			*/
		}
	/*}*/
}

6.忽略优先级的等待信号量

INT8U  OSSemPendAbort (OS_EVENT  *pevent,
                       INT8U      opt,
                       INT8U     *perr);
void led1_task(void* pdata)
{
	INT8U err = 0;
	/*
	while(1)
	{
		*/
		OSSemPendAbort(sem, OS_PEND_OPT_NONE, &err); //忽视优先级的等待函数
		/*
		LED1 = 0;
		delay_ms(300);		
		LED1 = 1;
		delay_ms(300);
	}
	*/
}

7.信号量信息查询

INT8U  OSSemQuery (OS_EVENT     *pevent,
                   OS_SEM_DATA  *p_sem_data);
OS_SEM_DATA mdata;
void led1_task(void* pdata)
{
	INT8U err = 0;
	INT8U ac;
	while(1)
	{
		OSSemPend(sem, 0, &err); //等待有效信号到来才执行后面的
		LED1 = 0;
		delay_ms(300);
		LED1 = 1;
		delay_ms(300);
		ac = OSSemQuery(sem, &mdata);//mdata不能用指针初始化,没有地方给他分配内存
		if(ac == OS_ERR_NONE)
		{
			/*
			printf("成功\r\n");
			printf("hi 看看我是多少 %d %d\r\n", ac,mdata.OSCnt);
			*/
		}
	}
}

8.信号量设置

void  OSSemSet (OS_EVENT  *pevent,
                INT16U     cnt,
                INT8U     *perr);
void led1_task(void* pdata)
{
	INT8U err = 0;
	INT8U ac;
	while(1)
	{
		OSSemPend(sem, 0, &err); //等待有效信号到来才执行后面的
		LED1 = 0;
		delay_ms(300);
		LED1 = 1;
		delay_ms(300);
		OSSemSet (sem, 5, &err); //重新设置信号量为5
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35675731/article/details/89408009