|
节点与计算机利用串口通信2-BaseStation
BaseStation的功能是实现一个中转的功能,将收到的节点信息发送给计算机,将收到的计算机的信息广播给其他的节点。
对于基站的节点来说,LED0s闪烁:发送一个数据包到其他节点。LED1闪烁:接收到数据包,发送一个数据包到串口。LED2闪烁:丢失一个数据包(接收的速度大于发送的速度)。
下面对BaseStationP.nc的代码进行分析:
//需要用到发送信息的数据包和串口
#include "AM.h"
#include "Serial.h"
module BaseStationP @safe() {
uses {
interface Boot;//启动系统
interface SplitControl as SerialControl; //串口控制
interface SplitControl as RadioControl; //radio控制
//向串口发送数据的设置am_id_t id,指定发送接收的am数据id
interface AMSend as UartSend[am_id_t id];
interface Receive as UartReceive[am_id_t id];
interface Packet as UartPacket;
interface AMPacket as UartAMPacket;
//向radio发送数据的设置
interface AMSend as RadioSend[am_id_t id];
interface Receive as RadioReceive[am_id_t id];
interface Receive as RadioSnoop[am_id_t id]; //嗅探
interface Packet as RadioPacket;
interface AMPacket as RadioAMPacket;
//Led灯设置
interface Leds;
}
}
implementation
{
//设置序列的长度
enum {
UART_QUEUE_LEN = 12,
RADIO_QUEUE_LEN = 12,
};
//串口设置
message_t uartQueueBufs[UART_QUEUE_LEN];//数据Buffer
message_t * ONE_NOK uartQueue[UART_QUEUE_LEN]; //??????
uint8_t uartIn, uartOut; //???????????
bool uartBusy, uartFull;//串口状态
//radio设置
message_t radioQueueBufs[RADIO_QUEUE_LEN];//buffer
message_t * ONE_NOK radioQueue[RADIO_QUEUE_LEN];
uint8_t radioIn, radioOut; //????
bool radioBusy, radioFull;//radio状态
//声明
task void uartSendTask();//串口发送
task void radioSendTask();//radio发送
//丢失数据包led2闪烁
void dropBlink() {
call Leds.led2Toggle();
}
//失败,led2闪烁
void failBlink() {
call Leds.led2Toggle();
}
//启动
event void Boot.booted() {
uint8_t i;
for (i = 0; i < UART_QUEUE_LEN; i++)
uartQueue = &uartQueueBufs; //将buffer中的每一个赋给指针
uartIn = uartOut = 0; //输入输出都为0
uartBusy = FALSE; //串口不忙
uartFull = TRUE; //数据已满
//同理设置radio
for (i = 0; i < RADIO_QUEUE_LEN; i++)
radioQueue = &radioQueueBufs;
radioIn = radioOut = 0;
radioBusy = FALSE;
radioFull = TRUE;
call RadioControl.start(); //启动radio
call SerialControl.start();//启动串口
}
event void RadioControl.startDone(error_t error) {
if (error == SUCCESS) {
radioFull = FALSE; //启动成功,radio数据不满
}
}
event void SerialControl.startDone(error_t error) {
if (error == SUCCESS) {
uartFull = FALSE; //启动成功,serial数据不满
}
}
event void SerialControl.stopDone(error_t error) {}
event void RadioControl.stopDone(error_t error) {}
uint8_t count = 0; //计数
message_t* ONE receive(message_t* ONE msg, void* payload, uint8_t len);
//radio嗅探接收数据
event message_t *RadioSnoop.receive[am_id_t id](message_t *msg,
void *payload,
uint8_t len) {
return receive(msg, payload, len);
}
//radio接收数据
event message_t *RadioReceive.receive[am_id_t id](message_t *msg,
void *payload,
uint8_t len) {
return receive(msg, payload, len);
}
//接收数据
message_t* receive(message_t *msg, void *payload, uint8_t len) {
message_t *ret = msg; //整个数据
//原子操作,不可被打断
atomic {
if (!uartFull)//串口未满
{
ret = uartQueue[uartIn];//ret指向输入
uartQueue[uartIn] = msg;//msg进入序列
uartIn = (uartIn + 1) % UART_QUEUE_LEN; //uarIn指向下一个
if (uartIn == uartOut) //入==出,串口序列的数据已满
uartFull = TRUE;
if (!uartBusy) //串口不忙,则发送数据
{
post uartSendTask(); //发送操作
uartBusy = TRUE; //串口变忙
}
}
else
dropBlink();//串口已满,数据丢失
}
return ret;
}
uint8_t tmpLen;
//向串口发送收到的数据
task void uartSendTask() {
uint8_t len;
am_id_t id;
am_addr_t addr, src;
message_t* msg;
//将所有数据发送完毕
atomic
if (uartIn == uartOut && !uartFull)
{
uartBusy = FALSE;
return;
}
msg = uartQueue[uartOut]; //待发送的数据
//从radio的msg数据包中获取每一个参数
tmpLen = len = call RadioPacket.payloadLength(msg);
id = call RadioAMPacket.type(msg);
addr = call RadioAMPacket.destination(msg);
src = call RadioAMPacket.source(msg);
call UartPacket.clear(msg);//清空串口数据包
call UartAMPacket.setSource(msg, src);//设置数据
//发送数据给串口,成功led1闪烁,寻找sendDone
if (call UartSend.send[id](addr, uartQueue[uartOut], len) == SUCCESS)
call Leds.led1Toggle();
else
{
failBlink();//发送失败,继续发送
post uartSendTask();
}
}
event void UartSend.sendDone[am_id_t id](message_t* msg, error_t error) {
if (error != SUCCESS)
failBlink();//发送失败
else
atomic //发送成功
if (msg == uartQueue[uartOut]) //发送的数据是所要发的数据
{
if (++uartOut >= UART_QUEUE_LEN) //输入指向下一个的超过了长度12
uartOut = 0; //从0开始
if (uartFull) //如果满的话,设置为没满
uartFull = FALSE;
}
post uartSendTask(); //继续发送其他数据
}
//串口接收数据
event message_t *UartReceive.receive[am_id_t id](message_t *msg,
void *payload,
uint8_t len) {
message_t *ret = msg;
bool reflectToken = FALSE;
//串口接收到数据发送给radio
atomic
if (!radioFull)
{
reflectToken = TRUE;
ret = radioQueue[radioIn];
radioQueue[radioIn] = msg;
if (++radioIn >= RADIO_QUEUE_LEN)
radioIn = 0;
if (radioIn == radioOut)
radioFull = TRUE;
if (!radioBusy)
{
post radioSendTask();
radioBusy = TRUE;
}
}
else
dropBlink(); //丢失数据
if (reflectToken) {
//call UartTokenReceive.ReflectToken(Token);
}
return ret;
}
task void radioSendTask() {
uint8_t len;
am_id_t id;
am_addr_t addr,source;
message_t* msg;
atomic
if (radioIn == radioOut && !radioFull)
{
radioBusy = FALSE;
return;
}
msg = radioQueue[radioOut];
len = call UartPacket.payloadLength(msg);
addr = call UartAMPacket.destination(msg);
source = call UartAMPacket.source(msg);
id = call UartAMPacket.type(msg);
call RadioPacket.clear(msg);
call RadioAMPacket.setSource(msg, source);
if (call RadioSend.send[id](addr, msg, len) == SUCCESS)
call Leds.led0Toggle();
else
{
failBlink();
post radioSendTask();
}
}
event void RadioSend.sendDone[am_id_t id](message_t* msg, error_t error) {
if (error != SUCCESS)
failBlink();
else
atomic
if (msg == radioQueue[radioOut])
{
if (++radioOut >= RADIO_QUEUE_LEN)
radioOut = 0;
if (radioFull)
radioFull = FALSE;
}
post radioSendTask();
}
}
|
|