1、消息队列只 是一种先进先出的队列型数据结构口,实际上是系统内核中的一个内部链表。消息被顺序插入队列中,其中发送进程将消息添加到队列未尾,接受进程从队列头读取消息。
2、多个进程可同时向一个消息队列发送消息,也可以同时从一个消息队列中接收消息。发送进程把消息发送到队列尾部,接受进程从消息队列头部读取消息,消息一旦被读出就从队列中删除。在主程序中进行处理任务,删除任务。若不删除任务,会导致任务堆栈的溢出,从而导致程序的进入硬件错误。二、结构组成1、消息队列中消息本身由消息类型和消息数据组成,通常使用如下结构:
typedef struct MESSAGE0 //消息结构体
{
int iWParm; //消息参数
int iLParm;
int Mnumber; //消息值,取值1-254
}MESSAGE;1:iWparm 指定了消息类型,为正整数。1)引入消息类型之后,消息队列在逻辑上由一个消息链表转化为多个消息链表。发送进程仍然无条件把消息写入队列的尾部,但接收进程却可以有选择地读取某个特定类型的消息中最接近队列头的一个,即使该消息不在队列头。相应消息一旦被读取,就从队列中删除,其它消息维持不变。2)iLParm指定了消息的数据。我们可以定义任意的数据类型甚至包括结构来描述消息数据。2:消息队列的创建:定义消息队列的深度和当前指针的个数MESSAGE ArrayMessage[MES_MAX]; //消息队列最大64 static char CurrentMesgPoint; //当前需要操作的消息指针创建消息任务如下所示:
void SendMessage(char Mnumber,int WParm,int LParm)
{
char i;
CurrentMesgPoint++; //这样处理的原因是避免在SendMessage函数重入导致的消息被改写的BUG
if(CurrentMesgPoint >= MES_MAX)
CurrentMesgPoint = 0;
i = CurrentMesgPoint;
if(ArrayMessage[i].Mnumber == 0)
{
ArrayMessage[i].Mnumber = Mnumber;
ArrayMessage[i].iWParm = WParm;
ArrayMessage[i].iLParm = LParm;
return;
}
}删除任务方式如下所示:void DeleteMessage(char MPoint)
{
ArrayMessage[MPoint].iWParm = 0;
ArrayMessage[MPoint].iLParm = 0;
ArrayMessage[MPoint].Mnumber=0; //避免函数重载出现BUG,对Mnumber的改写放在最后面
}三:软件配置如下使用AIcube 配置一下串口1的中断
void UART1_ISR(void) interrupt UART1_VECTOR
{
//<<AICUBE_USER_UART1_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART1_CheckTxFlag()) //判断串口发送中断
{
UART1_ClearTxFlag(); //清除串口发送中断标志
uSendPoint1 ++; //指向下一个数据
if (uSendPoint1 >= uSendLength1) //发送完毕
{
b_send1 = 0; //关闭发送标志
return;
}
SBUF = SendBuffer1[uSendPoint1]; //发送下一个数
}
if (UART1_CheckRxFlag()) //判断串口接收中断
{
UART1_ClearRxFlag(); //清除串口接收中断标志
RX1_Buffer[RX1_Cnt++] = SBUF;
RX1_COUNT = 5 ;
}
//<<AICUBE_USER_UART1_ISR_CODE1_END>>
}实现主要思想:将串口1接收到的数据放到接收数组中,同时做一个超时判断的时间戳,同时将每次收到数据时候将超时判断数据更新。3.2 串口1发送函数:void SendBufData1(u8 length)
{
uSendLength1 = length;
uSendPoint1 = 0;
SBUF = SendBuffer1[0]; //启动COM发送
b_send1 = 1;
}3.3 超时判断的函数处理:void DealData(int length)
{
memcpy(&SendBuffer1,&RX1_Buffer,length);
RX1_Cnt = 0 ;
RX1_COUNT = 5 ;
SendBufData1(length);
}3.4 将接收到的数据,拷贝给发送的buffer,同时通过串口发送函数发出。void System_Tim_Driver(char Tim_Intev)
{
switch(Tim_Intev)
{
case 1: if(RX1_COUNT>0)
RX1_COUNT-- ;
if((RX1_COUNT ==0)&& (RX1_Cnt!=0))
{
SendMessage(MW_USARTMESSAGE,RX1_Cnt,0);
}
break;
case 2:
break;
case 10:
break ;
default:break;
}
}3.5 在中断中添加,超时判断函数,即5ms中收不到数据时候,发送串口消息任务。主函数处理如下所示: mspoint ++;
if(mspoint>=MES_MAX) mspoint = 0; //消息循环查讯
if(ArrayMessage[mspoint].Mnumber !=0)
{
switch(ArrayMessage[mspoint].Mnumber)
{
case MW_TIMERINT:
System_Tim_Driver(ArrayMessage[mspoint].iWParm);
break;
case MW_USARTMESSAGE:
DealData(ArrayMessage[mspoint].iWParm);
break;
default:
break;
}
DeleteMessage(mspoint); //删除已经处理的消息
}四:验证如下所示:
我要赚赏金
