TinyOS - TinyOS中串口的收发操作

一、串口概述

二、源代码

TestSerial.h


#ifndef TEST_SERIAL_H
#define TEST_SERIAL_H

//这里自定义了一个结构体,作为发送我们需要发送的数据报
//结构体很简单,就是一个 特殊变量的 counter计数器
typedef nx_struct test_serial_msg {
  nx_uint16_t counter;
} test_serial_msg_t;

//下面这个枚举类型表示我们的串口标志位
enum {
  AM_TEST_SERIAL_MSG = 0x89,
};

#endif

TestSerialAppC.nc


#include "TestSerial.h"

configuration TestSerialAppC {}
implementation {

    //main
    components TestSerialC as App, MainC;
    App.Boot -> MainC.Boot;

    //led
    components LedsC;
    App.Leds -> LedsC;
    
    //serial
    components SerialActiveMessageC as AM;
    App.Control -> AM;
    App.Receive -> AM.Receive[AM_TEST_SERIAL_MSG];//接收数据的通道号,在.h文件中列举的枚举变量
    App.AMSend -> AM.AMSend[AM_TEST_SERIAL_MSG];//发送数据的通道号,在.h文件中列举的枚举变量
    App.Packet -> AM;
    
    
    //timer
    components new TimerMilliC();
    App.MilliTimer -> TimerMilliC;

}

TestSerialC.nc



#include "Timer.h"
#include "TestSerial.h"

module TestSerialC {
  uses {
    interface SplitControl as Control;
    interface Leds;
    interface Boot;
    interface Receive;
    interface AMSend;
    interface Timer<TMilli> as MilliTimer;
    interface Packet;
  }
}

implementation {

  message_t packet;//自定义的一个结构体类型

  bool locked = FALSE;
  uint16_t counter = 0;
  
  //主要流程如下:
  //1 开启主程序,开启串口
  //2 串口开启成功,开启定时器,以1s作为周期
  //3 定时器开启后,每秒 设置有效负载的值 为 counter
  //    3.1 发送数据包
  //    3.2 发送成功,上锁
  //4 发送完成后触发 sendDone 事件,
  //    4.1 判断发送完毕的包是否是我们想要发送的包
  event void Boot.booted() {
    call Control.start();//开启串口,对应事件为StartDone
  }
  
  event void MilliTimer.fired() {
    counter++;
    
    //如果没有锁定就,往下执行读取包数的程序
    if (locked) {
      return;
    }
    else {
        //getPayload 会返回一个有效负载区域的指针
      test_serial_msg_t* rcm = (test_serial_msg_t*)call Packet.getPayload(&packet, sizeof(test_serial_msg_t));
      if (rcm == NULL) {return;}
      if (call Packet.maxPayloadLength() < sizeof(test_serial_msg_t)) {
	return;
      }

      rcm->counter = counter;
      //AM_BROADCAST_ADDR 表示0xffff,表示广播之意,只是在串口通信中不作任何意义。
      if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS) {
	        locked = TRUE;
      }
    }
  }


    //收报的事件,
    //首先判断长度是否是两个字节,然后再根据字节开关灯
  event message_t* Receive.receive(message_t* bufPtr, 
				   void* payload, uint8_t len) {
    if (len != sizeof(test_serial_msg_t)) {return bufPtr;}
    else {
      test_serial_msg_t* rcm = (test_serial_msg_t*)payload;
      if (rcm->counter & 0x1) {
	call Leds.led0On();
      }
      else {
	call Leds.led0Off();
      }
      if (rcm->counter & 0x2) {
	call Leds.led1On();
      }
      else {
	call Leds.led1Off();
      }
      if (rcm->counter & 0x4) {
	call Leds.led2On();
      }
      else {
	call Leds.led2Off();
      }
      return bufPtr;
    }
  }

  event void AMSend.sendDone(message_t* bufPtr, error_t error) {
    if (&packet == bufPtr) {
      locked = FALSE;
    }
  }

  event void Control.startDone(error_t err) {
    if (err == SUCCESS) {
      call MilliTimer.startPeriodic(1000);
    }
  }
  event void Control.stopDone(error_t err) {}
}

Makefile

COMPONENT=TestSerialAppC
include $(MAKERULES)

三、现象数据分析

使用Listen来监听接收的数据。
在这里插入图片描述

 00 FF FF 00 00 02 00 89 00 03
  1. 第一个字节表示AM地址, 默认为00

  2. 第二个、第三个字节是接收者地址
    FFFF表示广播,但是再串口通信中无意义。
    在这里插入图片描述

  3. 第四、第五个字节是发送者地址
    0000表示0号节点发送数据

  4. 第六个字节是有效负载的长度
    02表示长度位两个字节,
    在这里插入图片描述

  5. 第七个字节是网络组号,

  6. 第八位是自定义的通道号
    在这里插入图片描述
    在这里插入图片描述

  7. 最后的即为我们的有效数据

在这里插入图片描述

信息报样例

在这里插入图片描述

四、举一反三。

修改代码

typedef nx_struct test_serial_msg {
  nx_uint16_t counter;
  nx_uint16_t id;
} test_serial_msg_t;
  event void MilliTimer.fired() {
    counter++;
    
    //如果没有锁定就,往下执行读取包数的程序
    if (locked) {
      return;
    }
    else {
        //getPayload 会返回一个有效负载区域的指针
      test_serial_msg_t* rcm = (test_serial_msg_t*)call Packet.getPayload(&packet, sizeof(test_serial_msg_t));
      if (rcm == NULL) {return;}
      if (call Packet.maxPayloadLength() < sizeof(test_serial_msg_t)) {
	return;
      }

      rcm->counter = counter;
      rcm->id = TOS_NODE_ID;
      //AM_BROADCAST_ADDR 表示0xffff,表示广播之意,只是在串口通信中不作任何意义。
      if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS) {
	        locked = TRUE;
      }
    }
  }

把节点ID打印出来
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值