Linuxでシリアル通信しようとしたら引っかかった

今までWindowsC#でシリアル通信のプログラムを書いていたのですが、今回Linuxでプログラムを書く必要があったのでいろいろ試してみました。


どこかにサンプルがあるだろう!ということでgoogle先生に聞いてみるとたくさん出てきました。
以下のページからソースをお借りしました。
PCのシリアル通信


シリアル送信のソースコード

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX 準拠のソース */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

main()
{
	int fd,c, res;
	struct termios oldtio,newtio;
	char buf[255];

	fd = open(MODEMDEVICE, O_WRONLY | O_NOCTTY ); 
	if (fd <0) {perror(MODEMDEVICE); exit(-1); }

	tcgetattr(fd,&oldtio); /* 現在のポート設定を待避 */

	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
	newtio.c_iflag = IGNPAR;
	newtio.c_oflag = 0;

	/* set input mode (non-canonical, no echo,...) */
	newtio.c_lflag = 0;

	newtio.c_cc[VTIME]    = 0;   /* キャラクタ間タイマは未使用 */
	newtio.c_cc[VMIN]     = 5;   /* 5文字受け取るまでブロックする */

	tcflush(fd, TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);

	buf[0] = 123;
	write(fd, buf, 1);

	tcsetattr(fd,TCSANOW,&oldtio);//設定をもとに戻す
	close(fd);
}

テストのため秋月のUSB-シリアル変換モジュールを2つ接続し、それぞれWindowsLinuxに接続しました。
Linux側で受信は難なくできたのですが、Linux側からの送信で毎回送信される値が変わるという現象が発生。
以前PICでシリアル通信のプログラムを書いていたときに似たようなことが起こっていたことを思い出して、ボーレートの設定ミスじゃないかと予想しました。
しかしプログラム中ではしっかり"#define BAUDRATE B9600"となっており、9,600bpsという設定がポート設定にも反映されているよに見えます。
そこでとりあえず受信のWindows側でボーレートをいろいろ変化させてみると57,600bpsの設定で正しく受信できました。
送信側のプログラムで57,600bpsなんて設定どこにもないよ!と思いつつ送信側のプログラムでボーレートの値をいろいろ変えても結局57,600bpsで送信されている模様。
いろいろ調べているうちにsttyコマンドなるものを知りました。これを実行してみました。


・stty -F /dev/ttyUSB0
speed 57600 baud;...


57600という数値を発見。
つまりプログラム中で指定していたボーレートは有効になっていなかった様子。
しかし受信は先のプログラムのままで9,600bpsで正常に行われていました。不思議です。
ここでsttyコマンドを使ってデフォルトの57,600bpsというボーレートを9,600bpsに変更してみました。
stty -F /dev/ttyUSB0 ospeed 9600
その結果、9,600bpsでの送信が正常に行われるようになりました。
結局原因はどこにあったのかは謎のままです。


環境
秋月のUSB-シリアル変換モジュール(FT232RL)
・OS標準の仮想シリアルポートドライバで動作(ポート名:ttyUSB0)
・OS:Ubuntu 10.04 desktop