2016-05-26 31 views
0

私は、私のマイクロコントローラを非同期に読み書きするためにブーストを使用しています。私は自分のマイクロコントローラを操作して、非同期書き込みによって送信されたデータを読み取り、それをコンピュータに戻し、コンピュータが単一スレッド上で非同期読み取りを介してそれを読み取るようにする。私はマイクロコントローラーに "15"以上を送ります。マイクロコントローラを接続した後に最初に送信するとうまく動作しますが、その後はシリアルポート "f"と "?f15"から散発的に "読み取り"されます。 fまたは?f15が送信されるたびに、コールバックで7バイトが転送されます.fは単なるascii値なので、私にとってはほとんど意味がありません。ここに私のクライアント側のシリアルポートラッパーのコードは次のとおりです。非同期でデータを読み込み、ストリームバッファから奇妙なデータを読み込みます。

void Serial::async_write(std::string string){ 
    std::cout << "String size:" << string.size() << std::endl; 
    // char stringToChar[string.size() + 1]; 
    // strcpy(stringToChar, string.c_str()); 
    // this->async_write(stringToChar); 
    boost::asio::async_write(*port_, boost::asio::buffer(string, string.length()), boost::bind(&Serial::async_write_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
} 

void Serial::async_write_buffer(std::vector<char> data){ 
    int num = data.size(); 
    std::cout << num << std::endl; 
    boost::asio::mutable_buffer buf(&data, data.size()); 
    boost::asio::async_write(*port_, boost::asio::buffer(data, data.size()), boost::bind(&Serial::async_write_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
} 

void Serial::async_write_handler(const boost::system::error_code &e, std::size_t bytes_written){ 
    std::cout << "Data written" << std::endl; 
    //b_->consume(bytes_written); 
} 

void Serial::async_read_handler(const boost::system::error_code &e, std::size_t bytes_read){ 
    if(!(*e)){ 
    std::cout << "bytes read in async read handler:" << bytes_read << std::endl; 
    if(bytes_read > 0){ 
     b_->commit(bytes_read); 
     std::istream* instream = new std::istream(b_); 
     std::string streamtostring; 
     *instream >> streamtostring; 
     std::cout << "size of input buffer:" << b_->size() << std::endl; 
     std::cout << "Read: " <<std::endl; 
     b_->consume(bytes_read); 
     std::cout << streamtostring << std::endl; 
    } 
    else{ 
     std::cout << "No bytes read" << std::endl; 
    } 
    } 
    else{ 
    std::cout << "Error occurred!" << std::endl; 
    std::cerr << e.message() << std::endl; 
    } 
} 
void Serial::async_read_until(std::string delim){ 
    boost::system::error_code e; 
    boost::asio::async_read_until(*port_, *b_, delim, boost::bind(&Serial::async_read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
} 

、ここではmain.cppにそれを呼び出すコードです:

int main(){ 
    boost::asio::io_service io; 
    Serial::Serial serial(PORT, &io, 9600); 
    if(!serial.is_open()){ 
     serial.open(PORT); 
    } 
    std::string s = "15"; 
    serial.async_write(s); 
    serial.async_read_until("\n"); 
    // const char arr[] = {'2', '5', '5'}; 
    // serial.async_write(arr); 
    // std::string s = "50089q503320232500202"; 
    // std::vector<char> data(s.begin(), s.end()); 
    // serial.async_write_buffer(data); 
    io.run(); 
} 

は、マイクロコントローラ側では今、私はそれが入ってくるのそれぞれを配置していデータバイトをcharのstackArrayに格納します。次に、スタック配列の長さより1文字長いchar配列に1つずつポップアウトされます。非同期読み込みは改行まで読み込むので、文字配列の最後に改行を挿入します。私はストリームを渡ってそれを送信します。

#include <StackArray.h> 
StackArray<int> binary; 
int ledPin = 13; 
int numberOfExecs = 0; 
byte data = 0; 
void setup() { 
    Serial.begin(9600); 
    //binary.setPrinter(Serial); 
    pinMode(ledPin, OUTPUT); 
} 

void blink(int times, int duration){ 
    for(int i = 0; i < times; i++){ 
    digitalWrite(ledPin, HIGH); 
    delay(duration); 
    digitalWrite(ledPin, LOW); 
    delay(duration); 
    } 
} 

void loop() { 
    //get number of bytes waiting in the serial buffer 
    int bytesWaiting = Serial.available(); 
    //create array of character values 
    StackArray<char> letterVals; 
    //Set the printer for the stack array to serial 
    letterVals.setPrinter(Serial); 
    //while serial is available, push each byte of data to the stack array 
    while(Serial.available() > 0){ 
    byte data = Serial.read(); 
    char c = data; 
    //Serial.println(c); 
    letterVals.push(c); 
// convertToBinary(data, binary); 
// printToLED(binary); 
    } 
    //Get the number of elements in the stack array 
    int numElements = letterVals.count(); 
    //indicate how many elements there are on the led 
    blink(numElements, 1000); 
// blink(1, 5000); 
//length of array 
    int len = numElements + 1; 
    //create array to send back data 
    char sendback[len]; 
    if(bytesWaiting > 0){ 
     for(int i = len - 2; i >= 0; i--){ 
     //pop each character into its original position 
     int asciiVal = letterVals.pop(); 
     //blink(asciiVal, 350); 
     //blink(20, 20); 
     sendback[i] = asciiVal; 
    } 
    } 
    //set last character to newline 
    sendback[len - 1] = 10; 
    //if there are no bytes available to read, send off data 
    if(bytesWaiting > 0){ 
    Serial.println(sendback); 
    } 
} 

誰もがランダムなfとfの出現をなぜ知っていますか?ありがとう。

答えて

0

これは、クライアントコードが定義されていない動作を呼び出す結果である可能性があります。具体的には、コードはのための生涯の要件を満たすために失敗したboost::asio::async_write()buffersパラメータ:

[...]基本的なメモリ・ブロックの所有権が、彼らは、ハンドラまで有効ことを保証しなければならない、呼び出し側によって保持され、が呼び出されます。 Serial::async_write()Serial::async_write_buffer()両方において

、バッファとして設けられ、基礎となるメモリは、その寿命関数戻り一旦終了オブジェクトによって所有されています。これらの関数のどちらも、async_writeの完了ハンドラが呼び出されるまで返されないことを保証しないため、一時的なライフタイムは、async_write()の要件に違反し、結果として未定義の動作になります。

void Serial::async_write(std::string string) 
{ 
    boost::asio::async_write(
    ..., 
    boost::asio::buffer(string, string.length()), 
    ...); 
} // `string`'s lifetime ends. 

void Serial::async_write_buffer(std::vector<char> data) 
{ 
    boost::asio::async_write(
    ..., 
    boost::asio::buffer(data, data.size()), 
    ...); 
} // `data`'s lifetime ends. 
+0

コードレビューコメント:バッファのようなオブジェクトのすべてのデータを送信するときのように、バッファのサイズを指定_not_検討[ '(バッファ)'](http://www.boost.org/doc /libs/1_61_0/doc/html/boost_asio/reference/buffer.html)オーバーロードによってサイズが推測されます。 'istream'はフリーストアに割り当てられ、決して削除されません。自動変数の使用を検討してください。 'streambuf'の使い方は、コミットと消費がno-opsになるので、厄介です(詳細については、[this](http://stackoverflow.com/a/31992879/1053968)の回答を参照してください)。 –

関連する問題