⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dataqueue.c

📁 一个WSN的树状路由,对于那些学WSN路由方面的朋友应该有说帮助.
💻 C
字号:
/*
****************************************************************************
*              宁波中科集成电路设计中心  版权所有 Copyright 2005
*						http:\\www.nbicc.com
*文件名:  dataqueue.c
*程序员:  蒋文丰
*主要内容:数据包缓存的队列管理
*
*如有问题或BUG,请登录www.wsn.net.cn 提问或用邮件和作者联系
****************************************************************************
*/
/////
#include "led.h"
#include "type.h"
#include "message.h"
#include "mac.h"
#include "dataqueue.h"
#include "os.h"
#include "route.h"
#include "app.h"
#include "global.h"
static void routeSendTask(void);
static void routeSendBroadcast(void);
static void routeSendLocalMsg(void);
static uint8_t enqueue_next; //队列尾指针
static uint8_t dequeue_next; //队列头指针
static bool QueueIdle; //队列的互斥变量
static uint8_t FreeAreaInQueue;//队列中的可用的空间数目

extern uint8_t currentparent;
static uint8_t TimeMask;
static uint8_t nextAddr;
static uint8_t QueueBroadcastState;
static uint8_t QueueLocalMsgState;
enum {IDLE,WRITE,USEFULL};
void QueueInit(void){  //mac层的调用在mac.c中被调用
   TimeMask = 0;
   enqueue_next = 0; 
   for( ;enqueue_next < MESSAGE_QUEUE_SIZE ; enqueue_next ++ )
   Queuemsgqueue[enqueue_next].length = 0 ;
   enqueue_next = 0; 
   dequeue_next = 0;
   FreeAreaInQueue = MESSAGE_QUEUE_SIZE;
   QueueIdle    = TRUE;
   QueueBroadcastState = IDLE;
   QueueLocalMsgState  = IDLE;
}
/**************************************************************************
*功能描述:数据入缓冲队列
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
    BROADCAST = 4,
    SENSOR = 3
};
           adress 表示下一调的地址还是广播地址,由type决定
		   length 数据包的长度
		   msg    数据包地址
                 
*返回值:
**************************************************************************/
result_t InQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg) {
    
	if ((enqueue_next + 1) % MESSAGE_QUEUE_SIZE == dequeue_next) {
            OSPostTask(routeSendTask); //队列满,调用任务,加快传输
		    return FAIL;
	}
	if(QueueIdle == TRUE) {
	QueueIdle = FALSE;
	//设置队列内容
	Queuemsgqueue[enqueue_next].length = length;
	Queuemsgqueue[enqueue_next].type = type;
	Queuemsgqueue[enqueue_next].Msg = *msg;
	enqueue_next++;  //进入队列数目加1
    enqueue_next %= MESSAGE_QUEUE_SIZE;
	FreeAreaInQueue = FreeAreaInQueue - 1;
	QueueIdle = TRUE;
    }
	return SUCCESS;
}

/**************************************************************************
*功能描述:广播包入缓冲区
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
    BROADCAST = 4,
    SENSOR = 3
};
           adress 表示下一调的地址还是广播地址,由type决定
		   length 数据包的长度
		   msg    数据包地址
                 
*返回值:
**************************************************************************/
result_t InBroadQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg) {
    if(QueueBroadcastState == IDLE){
	QueueBroadcastState = WRITE;
	QueueBroadcast.length = length;
	QueueBroadcast.type = type;
	QueueBroadcast.Msg = *msg;
	QueueBroadcastState = USEFULL;
	return 1;
	}else{
	return 0;
	}
}

/**************************************************************************
*功能描述:本地数据包入缓冲区
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
    BROADCAST = 4,
    SENSOR = 3
};
           adress 表示下一调的地址还是广播地址,由type决定
		   length 数据包的长度
		   msg    数据包地址
                 
*返回值:
**************************************************************************/
result_t InLocalMsgQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg){
    if(QueueLocalMsgState  == IDLE ) {
	QueueLocalMsgState = WRITE;
	QueueLocalMsg.length = length;
	QueueLocalMsg.type = type;
	QueueLocalMsg.Msg = *msg;
	QueueLocalMsgState = USEFULL;
	return 1;
	}else{
	return 0;
	}
}
/**************************************************************************
*功能描述:定时调用发送任务
*参数说明:
*返回值:
**************************************************************************/
void MACTask(void){
    if(currentparent != INVALID_NODE_ID) {
	LedRedOn();
	}else {
	LedRedOff();
	}
	if(TimeMask == 0 ){
		if(QueueBroadcastState == USEFULL) {
		OSPostTask(routeSendBroadcast);
		}else if(QueueLocalMsgState == USEFULL){
		OSPostTask(routeSendLocalMsg);    
		}else{
			if(QueueLocalMsgState == IDLE) LocalDataIn(); 
			if( OS_LOCAL_ADDRESS != SINKNODE){
			OSPostTask(routeSendTask); //调度发送任务,完成数据向MAC的传送  
			}
		}
	}else {
	TimeMask--;
	}
	
}
/**************************************************************************
*功能描述:调用MAC层函数实现广播包发送
*参数说明:
*返回值:
**************************************************************************/
static void routeSendBroadcast(void){
  
   MACBroadcastMsg(&QueueBroadcast.Msg, QueueBroadcast.length);
}

/**************************************************************************
*功能描述:调用MAC层函数实现本地数据包发送
*参数说明:
*返回值:
**************************************************************************/
static void routeSendLocalMsg(void){
    //本地的数据包直接以currentparent为下一跳地址
	if(currentparent != INVALID_NODE_ID) {
	MACUnicastMsg(&QueueLocalMsg.Msg, QueueLocalMsg.length,currentparent); 
    } 
}
/**************************************************************************
*功能描述:调用MAC层函数实现发送
*参数说明:
*返回值:
**************************************************************************/
//读队列数据的时候可以写,但是写的时候不能读
static void routeSendTask(void) {
    SHopMsgPtr sHopMsg;
	if (QueueIdle == FALSE ) return ; //正在写队列
	if (Queuemsgqueue[dequeue_next].length != 0) { //队列中还有消息存在 则
			if(currentparent == INVALID_NODE_ID) return ;
			nextAddr = CheckRoute(&Queuemsgqueue[dequeue_next].Msg);
			if (nextAddr != INVALID_NODE_ID)  {
			    MACUnicastMsg(&Queuemsgqueue[dequeue_next].Msg, Queuemsgqueue[dequeue_next].length,nextAddr);
			} else{ //如果currentparent存在但是没有可以解决循环路由的合适的下一跳节点,drop该数据项
					/*Queuemsgqueue[dequeue_next].length = 0;
					dequeue_next++;
					dequeue_next %= MESSAGE_QUEUE_SIZE; 
					FreeAreaInQueue = FreeAreaInQueue + 1;*/
					sHopMsg = (SHopMsgPtr )Queuemsgqueue[dequeue_next].Msg.data;
					if(sHopMsg->lifetime >= 1 ){
					sHopMsg->lifetime = (sHopMsg->lifetime)|0xF0;
					MACUnicastMsg(&Queuemsgqueue[dequeue_next].Msg, Queuemsgqueue[dequeue_next].length,currentparent);
					}else{
					Queuemsgqueue[dequeue_next].length = 0;
					dequeue_next++;
					dequeue_next %= MESSAGE_QUEUE_SIZE; 
					FreeAreaInQueue = FreeAreaInQueue + 1;
					}
			}
			
	} else {
            
            if( dequeue_next !=enqueue_next ) {
			dequeue_next = (dequeue_next + 1)%MESSAGE_QUEUE_SIZE;
			}
	} 
}
/**************************************************************************
*功能描述:数据包发送完成后的处理
*参数说明:发送出去的数据包地址
*返回值:
**************************************************************************/
result_t TransmitDone(OSMACMsgPtr msg) {

	uint8_t type;
	SHopMsgPtr sHopMsg;
	sHopMsg = (SHopMsgPtr )msg->data;
    type = sHopMsg->type;

	switch (type) {
    case BROADCAST: //发送广播包结束
	    if (msg != &QueueBroadcast.Msg) {
		return FAIL;
		}
	    QueueBroadcastState = IDLE;
		routeBroadcastDone(msg);
        break;
    
	case SENSOR:  //发送数据包结束
	    TimeMask = 4;//如果数据报发送成功,为了保证上层节点发送数据包时不冲突,尽量退避
	    if (msg == &Queuemsgqueue[dequeue_next].Msg) {
			Queuemsgqueue[dequeue_next].length = 0;
			dequeue_next++;
			dequeue_next %= MESSAGE_QUEUE_SIZE; 
			FreeAreaInQueue = FreeAreaInQueue + 1;
		}else if(msg == &QueueLocalMsg.Msg){
			QueueLocalMsgState = IDLE;
		}
		routeSendSENSORDone(msg);
	    break;
	}
	 
	return SUCCESS;
}


result_t GetFreeQueueLength(void){
    return FreeAreaInQueue;
}

void SendFail(OSMACMsgPtr receivemsg){
    RouteChangeP(receivemsg->toAddr);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -