AVR でRS-232C通信 その3

電力量計を作成する過程で意外に面倒なのは、シリアルデータをAVRとPCでやり取りする部分です。数値をAVRからPCに送るのに、RS-232C経由ですから1byteずつ送ります。ASCII文字で送るのは効率が悪いので、数値は内部表現のまま送ることにしたのですが、AVRはCでPC側のクライアントはJavaなので、各言語での変数の内部表現を気にしながら変換する必要があります。

下記にそれぞれのプラットフォームでの各変数の送信・受信関数を示します。

AVRからの送信:

void sio_puts(char *buf)

{

while(*buf){

while ( !(UCSR0A & (1<

UDR0 = *buf++;

}

}

void sio_putfloat(float num) {

union float_u_type {

float f;

uint8_t byte_rec[4];

} float_u;

float_u.f=num;

while ( !(UCSR0A & (1<

UDR0 = float_u.byte_rec[3];

while ( !(UCSR0A & (1<

UDR0 = float_u.byte_rec[2];

while ( !(UCSR0A & (1<

UDR0 = float_u.byte_rec[1];

while ( !(UCSR0A & (1<

UDR0 = float_u.byte_rec[0];

}

void sio_putbyte(int8_t num)

{

while ( !(UCSR0A & (1<

UDR0 = num;

}

void sio_putint(int16_t num)

{

while ( !(UCSR0A & (1<

UDR0 = (int8_t)(num>>8); //上位バイトを先に送信したほうが受信側処理がしやすい

while ( !(UCSR0A & (1<

UDR0 = (int8_t)(0x00ff&num);

}

PC側:

public float bufToFloat(byte b1, byte b2, byte b3, byte b4) {

byte[] buff=new byte[4];

buff[0]=b1;

buff[1]=b2;

buff[2]=b3;

buff[3]=b4;

float value=(float)0.0;

DataInputStream in = new DataInputStream(new ByteArrayInputStream(buff));

try {

value = (float)in.readFloat();

} catch (Exception e) {

e.printStackTrace();

}

return value;

}

public int bufToInt(byte b1, byte b2) {

int number=0;

return number=(int)*1;

}

ちなみに、バイト列 0x4048F5C3 が浮動小数点で 3.14 になります。これで動作テストをしました。

デバッグ中風景

画像

AC100Vになると、大き目の負荷でのテストが困難です。とりあえず負荷はこれを使ってます。

画像

*1:b1<<8)|(b2&0xFF