XbeeApi

Dependents:   XbeeAPI Hybrid_main_FirstEdtion

Committer:
ark777
Date:
Mon Mar 13 06:31:22 2017 +0000
Revision:
2:30220fb0e20e
Parent:
1:34007fc9235e
????????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ark777 0:bca23ad9e6b5 1 #include "mbed.h"
ark777 0:bca23ad9e6b5 2 #include <XbeeApiLib.h>
ark777 0:bca23ad9e6b5 3 #include <string>
ark777 0:bca23ad9e6b5 4
ark777 1:34007fc9235e 5 XbeeApi::XbeeApi(PinName Tx, PinName Rx, int BaudRate, void (*onPacketReceived)(int, char*)) : Xbee(Tx, Rx, BaudRate){
ark777 0:bca23ad9e6b5 6 //Xbee = Serial(Tx, Rx, BaudRate);
ark777 0:bca23ad9e6b5 7 //Xbee.baud(BaudRate);
ark777 0:bca23ad9e6b5 8
ark777 0:bca23ad9e6b5 9 HopLimit = 0;
ark777 0:bca23ad9e6b5 10 for(int i = 0;i < 4;i++){
ark777 0:bca23ad9e6b5 11 address[i].IsAvailable = false;
ark777 0:bca23ad9e6b5 12 }
ark777 0:bca23ad9e6b5 13 IsTransmitting = false;
ark777 1:34007fc9235e 14 SetInterrupt(true);
ark777 1:34007fc9235e 15 OnPacketReceived = onPacketReceived;
ark777 0:bca23ad9e6b5 16 }
ark777 0:bca23ad9e6b5 17
ark777 0:bca23ad9e6b5 18 void XbeeApi::SetAddress(int Num, unsigned long HIGH, unsigned long LOW){
ark777 0:bca23ad9e6b5 19 for(int i = 0;i < 4;i++){
ark777 0:bca23ad9e6b5 20 address[Num].ADR[3 - i] = reinterpret_cast<char (&)[sizeof(HIGH)]>(HIGH)[i];
ark777 0:bca23ad9e6b5 21 address[Num].ADR[7 - i] = reinterpret_cast<char (&)[sizeof(LOW)]>(LOW)[i];
ark777 0:bca23ad9e6b5 22 }
ark777 1:34007fc9235e 23 address[Num].IsAvailable = false;
ark777 0:bca23ad9e6b5 24 address[Num].sum = 0;
ark777 0:bca23ad9e6b5 25 //EndPacket()でチェックサムを計算する際、宛先アドレスもチェックサムに含まれる
ark777 0:bca23ad9e6b5 26 //宛先アドレスは頻繁に変更されないので、アドレス分の合計だけを先にまとめて計算しておく
ark777 0:bca23ad9e6b5 27 for(int i = 0;i < 8;i++){
ark777 0:bca23ad9e6b5 28 address[Num].sum += address[Num].ADR[i];
ark777 0:bca23ad9e6b5 29 }
ark777 0:bca23ad9e6b5 30 address[Num].ADR16bit[0] = 0x00;
ark777 0:bca23ad9e6b5 31 address[Num].ADR16bit[1] = 0x00;
ark777 0:bca23ad9e6b5 32 }
ark777 0:bca23ad9e6b5 33
ark777 0:bca23ad9e6b5 34 //
ark777 0:bca23ad9e6b5 35 //char StartWith: 送信されるデータの最初の1バイトに送信内容のタグとしての役割を持たせている
ark777 0:bca23ad9e6b5 36 //これにより、受信側では送信されてきたバイナリデータをどのような形式で読み取ればよいのか判断する
ark777 0:bca23ad9e6b5 37 void XbeeApi::StartPacket(char StartWith){
ark777 0:bca23ad9e6b5 38 CheckSum = 0x12;
ark777 0:bca23ad9e6b5 39 buf[17] = StartWith;
ark777 0:bca23ad9e6b5 40 itr = 18;
ark777 0:bca23ad9e6b5 41 }
ark777 0:bca23ad9e6b5 42
ark777 0:bca23ad9e6b5 43 //文字列を送信バッファに書き込む
ark777 0:bca23ad9e6b5 44 void XbeeApi::Write(string val){
ark777 0:bca23ad9e6b5 45 int length = val.length();
ark777 0:bca23ad9e6b5 46 if(length < 128 - itr){ //送信バッファの空きよりも文字列が長い場合は何もしない
ark777 0:bca23ad9e6b5 47 for(int i = 0;i < length;i++){
ark777 0:bca23ad9e6b5 48 buf[itr + i] = val.c_str()[i];
ark777 0:bca23ad9e6b5 49 }
ark777 0:bca23ad9e6b5 50 itr += length;
ark777 0:bca23ad9e6b5 51 }else{
ark777 0:bca23ad9e6b5 52 buf[17] = 0x00;
ark777 0:bca23ad9e6b5 53 EndPacket();
ark777 0:bca23ad9e6b5 54 }
ark777 0:bca23ad9e6b5 55 }
ark777 0:bca23ad9e6b5 56
ark777 0:bca23ad9e6b5 57 //int型の数値をバイト列として書き込む
ark777 0:bca23ad9e6b5 58 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
ark777 0:bca23ad9e6b5 59 void XbeeApi::Write(int val){
ark777 0:bca23ad9e6b5 60 if(sizeof(val) < 128 - itr){
ark777 0:bca23ad9e6b5 61 for(int i = 0;i < sizeof(val);i++){
ark777 0:bca23ad9e6b5 62 buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
ark777 0:bca23ad9e6b5 63 }
ark777 0:bca23ad9e6b5 64 itr += sizeof(val);
ark777 0:bca23ad9e6b5 65 }else{
ark777 0:bca23ad9e6b5 66 buf[17] = 0x00;
ark777 0:bca23ad9e6b5 67 EndPacket();
ark777 0:bca23ad9e6b5 68 }
ark777 0:bca23ad9e6b5 69 }
ark777 0:bca23ad9e6b5 70
ark777 1:34007fc9235e 71 //long型の数値をバイト列として書き込む
ark777 1:34007fc9235e 72 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
ark777 1:34007fc9235e 73 void XbeeApi::Write(long long val){
ark777 1:34007fc9235e 74 if(sizeof(val) < 128 - itr){
ark777 1:34007fc9235e 75 for(int i = 0;i < sizeof(val);i++){
ark777 1:34007fc9235e 76 buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
ark777 1:34007fc9235e 77 }
ark777 1:34007fc9235e 78 itr += sizeof(val);
ark777 1:34007fc9235e 79 }else{
ark777 1:34007fc9235e 80 buf[17] = 0x00;
ark777 1:34007fc9235e 81 EndPacket();
ark777 1:34007fc9235e 82 }
ark777 1:34007fc9235e 83 }
ark777 1:34007fc9235e 84
ark777 0:bca23ad9e6b5 85 //double型の数値をバイト列として書き込む
ark777 0:bca23ad9e6b5 86 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
ark777 0:bca23ad9e6b5 87 void XbeeApi::Write(double val){
ark777 0:bca23ad9e6b5 88 if(sizeof(val) < 128 - itr){
ark777 0:bca23ad9e6b5 89 for(int i = 0;i < sizeof(val);i++){
ark777 0:bca23ad9e6b5 90 buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
ark777 0:bca23ad9e6b5 91 }
ark777 0:bca23ad9e6b5 92 itr += sizeof(val);
ark777 0:bca23ad9e6b5 93 }else{
ark777 0:bca23ad9e6b5 94 buf[17] = 0x00;
ark777 0:bca23ad9e6b5 95 EndPacket();
ark777 0:bca23ad9e6b5 96 }
ark777 0:bca23ad9e6b5 97 }
ark777 0:bca23ad9e6b5 98
ark777 0:bca23ad9e6b5 99 //float型の数値をバイト列として書き込む
ark777 0:bca23ad9e6b5 100 //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意
ark777 0:bca23ad9e6b5 101 void XbeeApi::Write(float val){
ark777 0:bca23ad9e6b5 102 if(sizeof(val) < 128 - itr){
ark777 0:bca23ad9e6b5 103 for(int i = 0;i < sizeof(val);i++){
ark777 0:bca23ad9e6b5 104 buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i];
ark777 0:bca23ad9e6b5 105 }
ark777 0:bca23ad9e6b5 106 itr += sizeof(val);
ark777 0:bca23ad9e6b5 107 }else{
ark777 0:bca23ad9e6b5 108 buf[17] = 0x00;
ark777 0:bca23ad9e6b5 109 EndPacket();
ark777 0:bca23ad9e6b5 110 }
ark777 0:bca23ad9e6b5 111 }
ark777 0:bca23ad9e6b5 112
ark777 0:bca23ad9e6b5 113 void XbeeApi::EndPacket(){
ark777 0:bca23ad9e6b5 114 if(itr != 0){
ark777 0:bca23ad9e6b5 115 buf[0] = 0x7E; //パケットの先頭を表す
ark777 0:bca23ad9e6b5 116 buf[1] = (char)(itr - 3) >> 8;
ark777 0:bca23ad9e6b5 117 buf[2] = (char)(itr - 3) & 0x00FF;
ark777 0:bca23ad9e6b5 118 buf[3] = 0x10;
ark777 0:bca23ad9e6b5 119 buf[4] = 0x00; //ここを01にするとxbeeは送信の成否の判定を行うようになる(クソ重い)
ark777 0:bca23ad9e6b5 120 buf[15] = 0x01;
ark777 0:bca23ad9e6b5 121 buf[16] = 0x01; //0x01:送りっぱなし
ark777 0:bca23ad9e6b5 122 for(int i = 17;i < itr; i++){
ark777 0:bca23ad9e6b5 123 CheckSum += buf[i];
ark777 0:bca23ad9e6b5 124 }
ark777 0:bca23ad9e6b5 125 BytesToTransmit = itr + 1;
ark777 0:bca23ad9e6b5 126 NextTransmitIndex = BytesToTransmit;
ark777 0:bca23ad9e6b5 127 TransmittingAddrNum = -1;
ark777 0:bca23ad9e6b5 128 itr = 0;
ark777 0:bca23ad9e6b5 129 IsTransmitting = true;
ark777 0:bca23ad9e6b5 130 OnTransmitEnabled();
ark777 0:bca23ad9e6b5 131 }
ark777 0:bca23ad9e6b5 132 }
ark777 0:bca23ad9e6b5 133
ark777 0:bca23ad9e6b5 134 void XbeeApi::OnTransmitEnabled(){
ark777 0:bca23ad9e6b5 135 if(IsTransmitting == true){
ark777 0:bca23ad9e6b5 136 if(NextTransmitIndex < BytesToTransmit){
ark777 0:bca23ad9e6b5 137 WriteWithEsc(buf[NextTransmitIndex]);
ark777 0:bca23ad9e6b5 138 NextTransmitIndex++;
ark777 0:bca23ad9e6b5 139 }else{
ark777 0:bca23ad9e6b5 140 NextTransmitIndex = 0;
ark777 0:bca23ad9e6b5 141 //次の送信先に切り替える
ark777 0:bca23ad9e6b5 142 while(true){
ark777 0:bca23ad9e6b5 143 if(TransmittingAddrNum < 4){
ark777 0:bca23ad9e6b5 144 TransmittingAddrNum++;
ark777 0:bca23ad9e6b5 145 if(address[TransmittingAddrNum].IsAvailable == true){
ark777 0:bca23ad9e6b5 146 //次の送信先に送るためのバッファの準備
ark777 0:bca23ad9e6b5 147 for(int i = 0; i < 8; i++){
ark777 0:bca23ad9e6b5 148 buf[i + 5] = address[TransmittingAddrNum].ADR[i];
ark777 0:bca23ad9e6b5 149 }
ark777 0:bca23ad9e6b5 150 buf[13] = address[TransmittingAddrNum].ADR16bit[0];
ark777 0:bca23ad9e6b5 151 buf[14] = address[TransmittingAddrNum].ADR16bit[1];
ark777 0:bca23ad9e6b5 152 buf[BytesToTransmit - 1] = (char)(0xFF - (CheckSum + address[TransmittingAddrNum].sum + address[TransmittingAddrNum].ADR16bit[0] + address[TransmittingAddrNum].ADR16bit[1]) & 0xFF);
ark777 0:bca23ad9e6b5 153 Xbee.putc(buf[0]);
ark777 0:bca23ad9e6b5 154 NextTransmitIndex++;
ark777 0:bca23ad9e6b5 155 break;
ark777 0:bca23ad9e6b5 156 }
ark777 0:bca23ad9e6b5 157 }else{
ark777 0:bca23ad9e6b5 158 //送信完了
ark777 0:bca23ad9e6b5 159 IsTransmitting = false;
ark777 0:bca23ad9e6b5 160 break;
ark777 0:bca23ad9e6b5 161 }
ark777 0:bca23ad9e6b5 162 }
ark777 0:bca23ad9e6b5 163 }
ark777 0:bca23ad9e6b5 164 }
ark777 0:bca23ad9e6b5 165 }
ark777 0:bca23ad9e6b5 166
ark777 0:bca23ad9e6b5 167 void XbeeApi::WriteWithEsc(char c){
ark777 0:bca23ad9e6b5 168 if(c == 0x7E){
ark777 0:bca23ad9e6b5 169 Xbee.putc(0x7D);
ark777 0:bca23ad9e6b5 170 Xbee.putc(0x5E);
ark777 0:bca23ad9e6b5 171 }else if(c == 0x7D){
ark777 0:bca23ad9e6b5 172 Xbee.putc(0x7D);
ark777 0:bca23ad9e6b5 173 Xbee.putc(0x5D);
ark777 0:bca23ad9e6b5 174 }else{
ark777 0:bca23ad9e6b5 175 Xbee.putc(c);
ark777 0:bca23ad9e6b5 176 }
ark777 0:bca23ad9e6b5 177 }
ark777 0:bca23ad9e6b5 178
ark777 0:bca23ad9e6b5 179 void XbeeApi::ClearPacket(){
ark777 0:bca23ad9e6b5 180 CheckSum = 0;
ark777 0:bca23ad9e6b5 181 itr = 0;
ark777 0:bca23ad9e6b5 182 }
ark777 0:bca23ad9e6b5 183
ark777 0:bca23ad9e6b5 184
ark777 0:bca23ad9e6b5 185 //データ受信時の処理 1バイトごとに呼び出される必要がある
ark777 0:bca23ad9e6b5 186 void XbeeApi::OnDataReceived(){
ark777 0:bca23ad9e6b5 187 static bool EscFlag = false;
ark777 0:bca23ad9e6b5 188 static int PacketLength = 0;
ark777 0:bca23ad9e6b5 189 static bool IsReceivingPacket = false;
ark777 0:bca23ad9e6b5 190
ark777 0:bca23ad9e6b5 191 char message;
ark777 0:bca23ad9e6b5 192 message = Xbee.getc();
ark777 0:bca23ad9e6b5 193 if(message == 0x7E){ //パケットの先頭バイトは0x7E
ark777 0:bca23ad9e6b5 194 ReceivedBytesCounter = 0;
ark777 0:bca23ad9e6b5 195 PacketLength = 0;
ark777 0:bca23ad9e6b5 196 IsReceivingPacket = true;
ark777 0:bca23ad9e6b5 197 EscFlag = false;
ark777 0:bca23ad9e6b5 198 }
ark777 0:bca23ad9e6b5 199 if(IsReceivingPacket == true){
ark777 0:bca23ad9e6b5 200 if(message == 0x7D){
ark777 0:bca23ad9e6b5 201 EscFlag = true;
ark777 0:bca23ad9e6b5 202 }else{
ark777 0:bca23ad9e6b5 203 if(EscFlag == true){
ark777 0:bca23ad9e6b5 204 RxBuf[ReceivedBytesCounter] = message ^ 0x20;
ark777 0:bca23ad9e6b5 205 EscFlag = false;
ark777 0:bca23ad9e6b5 206 }else{
ark777 0:bca23ad9e6b5 207 RxBuf[ReceivedBytesCounter] = message;
ark777 0:bca23ad9e6b5 208 }
ark777 0:bca23ad9e6b5 209 ReceivedBytesCounter++;
ark777 1:34007fc9235e 210 if(ReceivedBytesCounter >= 256){
ark777 1:34007fc9235e 211 IsReceivingPacket = false; //受信バッファを溢れる場合は、パケットの読み込みを中止する 次に0x7Eを受信するまで再開されない
ark777 1:34007fc9235e 212 }
ark777 0:bca23ad9e6b5 213 }
ark777 0:bca23ad9e6b5 214 //この時点でReceivedBytesCounterには受信したデータのバイト数が入っている
ark777 0:bca23ad9e6b5 215 //2バイト目と3バイト目はパケットの長さを表している
ark777 0:bca23ad9e6b5 216 if(RxBuf[0] == 0x7E){
ark777 1:34007fc9235e 217 if(ReceivedBytesCounter == 3){ //パケットの3バイト目までを受信した時点で、パケットの長さを計算できる
ark777 0:bca23ad9e6b5 218 PacketLength = 255 * RxBuf[1] + RxBuf[2];
ark777 0:bca23ad9e6b5 219 }
ark777 1:34007fc9235e 220 if(ReceivedBytesCounter > 3 && ReceivedBytesCounter == PacketLength + 4){ //パケットの長さと同じだけのデータを受信したら
ark777 0:bca23ad9e6b5 221 int sum = 0;
ark777 0:bca23ad9e6b5 222 for(int i = 3; i < ReceivedBytesCounter - 1; i++){ //先頭3バイトとチェックサム以外のすべてのバイトを合計
ark777 0:bca23ad9e6b5 223 sum += RxBuf[i];
ark777 0:bca23ad9e6b5 224 }
ark777 1:34007fc9235e 225 if((char)(0xFF - sum & 0xFF) == RxBuf[ReceivedBytesCounter - 1]){ //チェックサムが一致するならば
ark777 0:bca23ad9e6b5 226 //ここにデータ受信時の処理を書く
ark777 0:bca23ad9e6b5 227 //パケット受信直後なので、多少時間のかかる処理でも問題ないはず
ark777 1:34007fc9235e 228 if(RxBuf[3] == 0x90){ // パケットタイプ0x90は他のXbeeから送信されたデータを表す
ark777 1:34007fc9235e 229 int DataLength = PacketLength - 12; //データ本体の長さは パケットの長さ - 12 ここでいう「パケットの長さ」に、最初の3バイトとチェックサムは含まない
ark777 1:34007fc9235e 230 OnPacketReceived(DataLength, &RxBuf[15]); //パケットタイプ0x90は地上局から送信されたデータが16バイト目 すなわち RxBuf[15] から格納されている
ark777 1:34007fc9235e 231 //OnPacketReceived(DataLength + 16, RxBuf); //デバッグ用 パケットすべてを渡す場合
ark777 2:30220fb0e20e 232 if(DataLength == 2 && RxBuf[15] == 0x59 && RxBuf[16] == 0x4D){ //0x594Dが送られて来たら、送信元の64bitアドレスをチェックする
ark777 2:30220fb0e20e 233 for(int i = 0; i < 4; i++){
ark777 2:30220fb0e20e 234 bool IsMatchAddr = true;
ark777 2:30220fb0e20e 235 for(int j = 0; j < 8; j++){
ark777 2:30220fb0e20e 236 if(address[i].ADR[j] != RxBuf[j + 4]){
ark777 2:30220fb0e20e 237 IsMatchAddr = false; //16bitアドレスを調べる 1つでも一致しなければ終了するし
ark777 2:30220fb0e20e 238 break;
ark777 2:30220fb0e20e 239 }
ark777 2:30220fb0e20e 240 }
ark777 2:30220fb0e20e 241 if(IsMatchAddr == true){ //0x594Dを送信してきた地上局の64bitアドレスがaddress[i]と一致した場合
ark777 2:30220fb0e20e 242 address[i].ADR16bit[0] = RxBuf[12]; //address[i]の16bitアドレスを地上局側に合わせる
ark777 2:30220fb0e20e 243 address[i].ADR16bit[1] = RxBuf[13];
ark777 2:30220fb0e20e 244 address[i].IsAvailable = true;
ark777 2:30220fb0e20e 245 break;
ark777 2:30220fb0e20e 246 }
ark777 2:30220fb0e20e 247 }
ark777 0:bca23ad9e6b5 248 }
ark777 0:bca23ad9e6b5 249 }
ark777 0:bca23ad9e6b5 250 }
ark777 0:bca23ad9e6b5 251 IsReceivingPacket = false;
ark777 0:bca23ad9e6b5 252 }
ark777 0:bca23ad9e6b5 253 }
ark777 0:bca23ad9e6b5 254 }
ark777 0:bca23ad9e6b5 255 }
ark777 0:bca23ad9e6b5 256
ark777 0:bca23ad9e6b5 257 void XbeeApi::SetInterrupt(bool val){
ark777 0:bca23ad9e6b5 258 if(val == true){
ark777 0:bca23ad9e6b5 259 Xbee.attach(callback(this, &XbeeApi::OnDataReceived), Serial::RxIrq);
ark777 0:bca23ad9e6b5 260 Xbee.attach(callback(this, &XbeeApi::OnTransmitEnabled), Serial::TxIrq);
ark777 0:bca23ad9e6b5 261 }else{
ark777 1:34007fc9235e 262 Xbee.attach(NULL, Serial::RxIrq);
ark777 1:34007fc9235e 263 Xbee.attach(NULL, Serial::TxIrq);
ark777 0:bca23ad9e6b5 264 }
ark777 0:bca23ad9e6b5 265 }
ark777 0:bca23ad9e6b5 266