シリアル通信の送信・受信プログラム

シリアルのスピードの問題はさておき、受信側のプログラムも必要になってきます。テストでは TeraTerm を使ってきましたが、ターミナルプログラムで受信できるのは「文字」だけです。電力量のデータは「数値」です。数値を文字として送出することもできますが、そうすると1桁で1バイトが必要になりデータ量が増えてしまいます。数値はそのまま整数値として送出したほうが効率がよいです。

まず、AVR側のプログラムをなおします。「AVR でRS-232C通信 その2」のプログラムに整数値の送るために使うルーチンを追加します。

void sio_putbyte(char num) //8ビット値の送信用

{

while ( !(UCSR0A & (1<

UDR0 = num;

}

void sio_putint(int num) //16ビット値の送信用

{

char numL,numH;

numH = (0b11110000&num)>>4;

while ( !(UCSR0A & (1<

UDR0 = numH; //上位バイトを先に送信したほうが受信側処理がしやすい

while ( !(UCSR0A & (1<

numL = 0b00001111#

UDR0 = numL;

}

int main(void){

_delay_ms(1000);

sio_init(MYUBRR); // USART設定

while(1) {

sio_putint(254);

_delay_ms(1000);

}

}

問題は16ビット値の送信です。RS-232Cデータ通信で一度に送れるデータは1バイトなので、16ビットのデータは2回に分けて送る必要があります。

とりあえず、上位・下位バイトに分けて送るルーチンを作りました。

今度は受信プログラムです。どのプラットフォームでも動くように Java を使います。昔は Java が標準でシリアルポートもサポートしていましたが、久しぶりに見ると、今はサポートされていないため、RXTXというライブラリを使います。

ちょうどいいサンプルプログラムがあるので、これを改造して使います。

1)SerialReader クラスにここで見つけた toHex() メソッドを追加して、データ表示に使います。

public static String toHex(byte digest) {

StringBuilder sb = new StringBuilder();

for (byte b : digest) {

sb.append(String.format("%1$02X", b));

}

return sb.toString();

}

2) run() メソッドのデータ表示部分は buffer の値を16進で表示させます。そのままでは、データがあってもなくても byte 配列全部を表示してしまうので、len が0でなければ表示します。

public void run ()

{

byte buffer = new byte[2];

int len = -1;

try

{

while ( ( len = this.in.read(buffer)) > -1 )

{

// System.out.print(new String(buffer,0,len));

if (len>0) {

System.out.print("len="+len+" ");

System.out.println(toHex(buffer));

}

}

}

catch ( IOException e )

{

e.printStackTrace();

}

}

これで、AVRのプログラムを動かしてPC側の表示を見ます。

画像

2バイトずつ送っているのに、受信側は1バイト、2バイトが不定期に来ます。。もう少しデバッグが必要です。。