XbeeApi
Dependents: XbeeAPI Hybrid_main_FirstEdtion
XbeeApiLib.cpp
- Committer:
- ark777
- Date:
- 2017-03-10
- Revision:
- 1:34007fc9235e
- Parent:
- 0:bca23ad9e6b5
- Child:
- 2:30220fb0e20e
File content as of revision 1:34007fc9235e:
#include "mbed.h" #include <XbeeApiLib.h> #include <string> XbeeApi::XbeeApi(PinName Tx, PinName Rx, int BaudRate, void (*onPacketReceived)(int, char*)) : Xbee(Tx, Rx, BaudRate){ //Xbee = Serial(Tx, Rx, BaudRate); //Xbee.baud(BaudRate); HopLimit = 0; for(int i = 0;i < 4;i++){ address[i].IsAvailable = false; } IsTransmitting = false; SetInterrupt(true); OnPacketReceived = onPacketReceived; } void XbeeApi::SetAddress(int Num, unsigned long HIGH, unsigned long LOW){ for(int i = 0;i < 4;i++){ address[Num].ADR[3 - i] = reinterpret_cast<char (&)[sizeof(HIGH)]>(HIGH)[i]; address[Num].ADR[7 - i] = reinterpret_cast<char (&)[sizeof(LOW)]>(LOW)[i]; } address[Num].IsAvailable = false; address[Num].sum = 0; //EndPacket()でチェックサムを計算する際、宛先アドレスもチェックサムに含まれる //宛先アドレスは頻繁に変更されないので、アドレス分の合計だけを先にまとめて計算しておく for(int i = 0;i < 8;i++){ address[Num].sum += address[Num].ADR[i]; } address[Num].ADR16bit[0] = 0x00; address[Num].ADR16bit[1] = 0x00; } // //char StartWith: 送信されるデータの最初の1バイトに送信内容のタグとしての役割を持たせている //これにより、受信側では送信されてきたバイナリデータをどのような形式で読み取ればよいのか判断する void XbeeApi::StartPacket(char StartWith){ CheckSum = 0x12; buf[17] = StartWith; itr = 18; } //文字列を送信バッファに書き込む void XbeeApi::Write(string val){ int length = val.length(); if(length < 128 - itr){ //送信バッファの空きよりも文字列が長い場合は何もしない for(int i = 0;i < length;i++){ buf[itr + i] = val.c_str()[i]; } itr += length; }else{ buf[17] = 0x00; EndPacket(); } } //int型の数値をバイト列として書き込む //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意 void XbeeApi::Write(int val){ if(sizeof(val) < 128 - itr){ for(int i = 0;i < sizeof(val);i++){ buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i]; } itr += sizeof(val); }else{ buf[17] = 0x00; EndPacket(); } } //long型の数値をバイト列として書き込む //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意 void XbeeApi::Write(long long val){ if(sizeof(val) < 128 - itr){ for(int i = 0;i < sizeof(val);i++){ buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i]; } itr += sizeof(val); }else{ buf[17] = 0x00; EndPacket(); } } //double型の数値をバイト列として書き込む //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意 void XbeeApi::Write(double val){ if(sizeof(val) < 128 - itr){ for(int i = 0;i < sizeof(val);i++){ buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i]; } itr += sizeof(val); }else{ buf[17] = 0x00; EndPacket(); } } //float型の数値をバイト列として書き込む //リトルエンディアン(位の大きい数字ほどバイト列では後ろになる)であることに注意 void XbeeApi::Write(float val){ if(sizeof(val) < 128 - itr){ for(int i = 0;i < sizeof(val);i++){ buf[itr + i] = reinterpret_cast<char (&)[sizeof(val)]>(val)[i]; } itr += sizeof(val); }else{ buf[17] = 0x00; EndPacket(); } } void XbeeApi::EndPacket(){ if(itr != 0){ buf[0] = 0x7E; //パケットの先頭を表す buf[1] = (char)(itr - 3) >> 8; buf[2] = (char)(itr - 3) & 0x00FF; buf[3] = 0x10; buf[4] = 0x00; //ここを01にするとxbeeは送信の成否の判定を行うようになる(クソ重い) buf[15] = 0x01; buf[16] = 0x01; //0x01:送りっぱなし for(int i = 17;i < itr; i++){ CheckSum += buf[i]; } BytesToTransmit = itr + 1; NextTransmitIndex = BytesToTransmit; TransmittingAddrNum = -1; itr = 0; IsTransmitting = true; OnTransmitEnabled(); } } void XbeeApi::OnTransmitEnabled(){ if(IsTransmitting == true){ if(NextTransmitIndex < BytesToTransmit){ WriteWithEsc(buf[NextTransmitIndex]); NextTransmitIndex++; }else{ NextTransmitIndex = 0; //次の送信先に切り替える while(true){ if(TransmittingAddrNum < 4){ TransmittingAddrNum++; if(address[TransmittingAddrNum].IsAvailable == true){ //次の送信先に送るためのバッファの準備 for(int i = 0; i < 8; i++){ buf[i + 5] = address[TransmittingAddrNum].ADR[i]; } buf[13] = address[TransmittingAddrNum].ADR16bit[0]; buf[14] = address[TransmittingAddrNum].ADR16bit[1]; buf[BytesToTransmit - 1] = (char)(0xFF - (CheckSum + address[TransmittingAddrNum].sum + address[TransmittingAddrNum].ADR16bit[0] + address[TransmittingAddrNum].ADR16bit[1]) & 0xFF); Xbee.putc(buf[0]); NextTransmitIndex++; break; } }else{ //送信完了 IsTransmitting = false; break; } } } } } void XbeeApi::WriteWithEsc(char c){ if(c == 0x7E){ Xbee.putc(0x7D); Xbee.putc(0x5E); }else if(c == 0x7D){ Xbee.putc(0x7D); Xbee.putc(0x5D); }else{ Xbee.putc(c); } } void XbeeApi::ClearPacket(){ CheckSum = 0; itr = 0; } //データ受信時の処理 1バイトごとに呼び出される必要がある void XbeeApi::OnDataReceived(){ static bool EscFlag = false; static int PacketLength = 0; static bool IsReceivingPacket = false; char message; message = Xbee.getc(); if(message == 0x7E){ //パケットの先頭バイトは0x7E ReceivedBytesCounter = 0; PacketLength = 0; IsReceivingPacket = true; EscFlag = false; } if(IsReceivingPacket == true){ if(message == 0x7D){ EscFlag = true; }else{ if(EscFlag == true){ RxBuf[ReceivedBytesCounter] = message ^ 0x20; EscFlag = false; }else{ RxBuf[ReceivedBytesCounter] = message; } ReceivedBytesCounter++; if(ReceivedBytesCounter >= 256){ IsReceivingPacket = false; //受信バッファを溢れる場合は、パケットの読み込みを中止する 次に0x7Eを受信するまで再開されない } } //この時点でReceivedBytesCounterには受信したデータのバイト数が入っている //2バイト目と3バイト目はパケットの長さを表している if(RxBuf[0] == 0x7E){ if(ReceivedBytesCounter == 3){ //パケットの3バイト目までを受信した時点で、パケットの長さを計算できる PacketLength = 255 * RxBuf[1] + RxBuf[2]; } if(ReceivedBytesCounter > 3 && ReceivedBytesCounter == PacketLength + 4){ //パケットの長さと同じだけのデータを受信したら int sum = 0; for(int i = 3; i < ReceivedBytesCounter - 1; i++){ //先頭3バイトとチェックサム以外のすべてのバイトを合計 sum += RxBuf[i]; } if((char)(0xFF - sum & 0xFF) == RxBuf[ReceivedBytesCounter - 1]){ //チェックサムが一致するならば //ここにデータ受信時の処理を書く //パケット受信直後なので、多少時間のかかる処理でも問題ないはず if(RxBuf[3] == 0x90){ // パケットタイプ0x90は他のXbeeから送信されたデータを表す int DataLength = PacketLength - 12; //データ本体の長さは パケットの長さ - 12 ここでいう「パケットの長さ」に、最初の3バイトとチェックサムは含まない OnPacketReceived(DataLength, &RxBuf[15]); //パケットタイプ0x90は地上局から送信されたデータが16バイト目 すなわち RxBuf[15] から格納されている //OnPacketReceived(DataLength + 16, RxBuf); //デバッグ用 パケットすべてを渡す場合 if(DataLength == 2 && RxBuf[15] == 0x59 && RxBuf[16] == 0x4D){ address[0].ADR16bit[0] = RxBuf[12]; address[0].ADR16bit[1] = RxBuf[13]; address[0].IsAvailable = true; } } } IsReceivingPacket = false; } } } } void XbeeApi::SetInterrupt(bool val){ if(val == true){ Xbee.attach(callback(this, &XbeeApi::OnDataReceived), Serial::RxIrq); Xbee.attach(callback(this, &XbeeApi::OnTransmitEnabled), Serial::TxIrq); }else{ Xbee.attach(NULL, Serial::RxIrq); Xbee.attach(NULL, Serial::TxIrq); } }