嵌入式实时操作系统small RTOS51原理及应用 ----笔记 第七章 任务之间的通信和同步之消息队列
Small_RTOS1.12.1\small_rtos\SerialIn
实现方式 类似于 信号量
主要是理解 循环队列
消息队列 应用场景
#define NBYTE 7
#define STARTBYTE1 0xf0
#define STARTBYTE2 0xf1
#define RECIVE_TASK_ID 0
uint8 Buf[NBYTE - 3];
uint8 SerialData[14];
void TaskA(void)
{
uint8 data temp,temp1;
uint8 Sum,i;
OSQCreate(SerialData,14);
OSQPend(&temp,SerialData,0);
while (1)
{
if (OSQPend(&temp1,SerialData,20) == OS_Q_TMO)
{
goto start;
}
}
}
void TaskB(void)
{
while (1)
{
OSWait(K_TMO,10);
OSQPost(SerialData,0xf0);
OSWait(K_TMO,10);
OSQPost(SerialData,0xf1);
OSWait(K_TMO,10);
OSQPost(SerialData,0xf0);
OSWait(K_TMO,10);
OSQPost(SerialData,0xf0);
OSWait(K_TMO,10);
OSQPost(SerialData,0x00);
OSWait(K_TMO,10);
OSQPost(SerialData,0x00);
OSWait(K_TMO,10);
OSQPost(SerialData,0x3f);
}
}
初始化消息队列 OSQCreate
OSQCreate
//输 入: Buf:为队列分配的存储空间地址
//SizeOfBuf:为队列分配的存储空间大小
// 输 出: NOT_OK:参数错误
// OS_Q_OK:成功
//Buf[0]:队列中字节数,Buf[1]:Buf总长度,Buf[2]:出对端,Buf[3](,Buf[4]):等待队列任务列表
uint8 OSQCreate(uint8 *Buf, uint8 SizeOfBuf)
{
OS_ENTER_CRITICAL();
if ((SizeOfBuf >= 5) && (Buf != NULL))
{
Buf[0] = 0; /* 队列中消息数目 */
Buf[1] = SizeOfBuf; /* 消息队列占用内存字节数 */
Buf[2] = 4; /* 将要出队的消息所在位置 */
Buf[3] = 0; /* 消息队列的等待任务列表 */
Buf[4] = 0; /* 任务数大于等于8时为等待任务列表的一部分, */
/* 否则为消息缓冲区 */
OS_EXIT_CRITICAL();
return OS_Q_OK;
}
else
{
OS_EXIT_CRITICAL();
return NOT_OK;
}
}
OSQPend 等待消息队列中的消息
函数名称: OSQPend
功能描述: 等待消息队列中的消息
输 入: Ret:返回的消息
Buf:指向队列的指针
Tick:等待时间
输 出: NOT_OK:参数错误
OS_Q_OK:收到消息
OS_Q_TMO:超时到
OS_Q_NOT_OK:无消息
uint8 OSQPend(uint8 data *Ret, uint8 OS_Q_MEM_SEL *Buf, uint8 Tick)
{
#ifdef __C51__
uint8 data *cp;
#endif
OS_ENTER_CRITICAL(); // 关闭中断
/* 设置当前任务的超时时间 */
OSWaitTick[OSRunningTaskID()] = Tick;
/* 使用堆栈是为了使函数具有重入性 */
#ifdef __C51__
SP++;
*((uint8 data * data *)SP) = Ret;
#endif
/* 把任务加入等待任务队列 */
Buf[3] |= OSMapTbl[OSRunningTaskID()];
while (Buf[0] == 0) /* 消息队列中是否有消息 */
{
Buf[0] =0 表示 没有数据
#ifdef __C51__
SP = SP + sizeof(Buf);
*((uint8 * data *)(SP + 1 - sizeof(Buf))) = Buf;
#endif
OSClearSignal(OSRunningTaskID()); /* 任务进入等待状态 */
OSSched(); /* 运行下一个任务 */
#ifdef __C51__
Buf = *((uint8 OS_Q_MEM_SEL * data *)(SP + 1 - sizeof(Buf)));
SP = SP - sizeof(Buf);
#endif
/* 任务再次运行,如果超时到,退出循环 */
if (OSWaitTick[OSRunningTaskID()] == 0)
{
break;
}
} // end of while (Buf[0] == 0)
/* 将任务从等待队列中清除(可以删除) */
/*Buf[3]这个字节的每一位,对应一个任务*/
Buf[3] &= ~OSMapTbl[OSRunningTaskID()];
//如果是消息队列中,有消息
if (Buf[0] > 0)
{
/* 有,消息出队 */
Buf[0]--; /* 队列的消息数目减一 */
/* 指向下一个出队位置 */
Buf[2]++; // 出队消息指针
/* Buf[1]消息队列占用内存字节数 */
if (Buf[2] >= Buf[1] )
{
Buf[2] = 4;
}
#ifdef __C51__
cp = (uint8 data *)(*((uint8 data *)SP));
SP--;
*cp = Buf[Buf[2]];
#else
*Ret = Buf[Buf[2]];
#endif
OS_EXIT_CRITICAL();
return OS_Q_OK;
}
else
{
/* 无,返回错误码 */
#ifdef __C51__
SP--;
#endif
OS_EXIT_CRITICAL();
return OS_Q_TMO;
}
}
OSWait(K_SIG,0) 应用场景
其中 : OSIntSendSignal(1) 和OSWait(K_SIG,0); 是对应的
TaskB 的 任务索引ID 等于 1
void comm(void) interrupt 4
{
OS_INT_ENTER();
if (RI == 1)
{
RI = 0;
#if EN_OS_Q_INT_POST > 0
OSQIntPost(SerialData,SBUF);
#endif
#if EN_OS_Q_INT_POST_FRONT > 0
OSQIntPostFront(SerialData,SBUF);
#endif
}
if (TI == 1)
{
TI = 0;
OSIntSendSignal(1);
}
OSIntExit();
}
void TaskB(void)
{
while (1)
{
OSWait(K_SIG,0);
SBUF = 'O';
OSWait(K_SIG,0);
SBUF = 'K';
OSWait(K_SIG,0);
SBUF = '!';
OSWait(K_SIG,0);
SBUF = '\n';
OSWait(K_SIG,0);
}
}