Armadilloフォーラム

RS232Cのボーレートについて

tamuki

2025年8月21日 19時26分

==========
製品型番:armadillo-420
・開発環境:atde5-amd64-20191016.tar.gz
・Atmark-Dist:atmark-dist-20191216.tar.gz
・Linuxカーネル:linux-3.14-at13.tar.gz
==========

tamukiです。

armadillo-420のCON3端子(DSUB9ピン)にRS232Cケーブルを接続してシリアル通信をするプログラムを作成しています。
以下のプログラムでボーレート(115200byte)を設定した後にシリアルポートの状態を確認した結果、ボーレートが9600byteに変更されていました。

ちなみに、サンプルプログラムのprintf文の出力は以下のようになりました。
tcsetattr()は正常終了していたので、カーネル側で書き換えられたのか、拒否されたものと推測しています。
・cfsetospeed() After get: ispeed=4098, ospeed=4098 →115200byte
・tcsetattr() After get: ispeed=13, ospeed=13 →9600byte

<サンプルプログラム>
void setup_serial(int *fd) {
struct termios tty;
*fd = open("/dev/ttymxc1", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (*fd < 0) {
perror("Serial open");
exit(1);
}
tcgetattr(*fd, &tty);
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
printf("cfsetospeed() After get: ispeed=%d, ospeed=%d\n", cfgetispeed(&tty), cfgetospeed(&tty));

tty.c_iflag = IGNBRK | IGNPAR; //ブレーク文字無視/パリティなし
tty.c_cflag = CS8 | CLOCAL | CREAD; //フロー制御なし/8bit/非モデム/受信可
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tcflush(*fd, TCIFLUSH);
if(tcsetattr(*fd, TCSANOW, &tty) != 0){
perror("tcsetattr failed");
}
tcgetattr(*fd, &tty);
printf("tcsetattr() After get: ispeed=%d, ospeed=%d\n", cfgetispeed(&tty), cfgetospeed(&tty));
}

<シリアルポートの状態>
[root@armadillo420-0 (pts/1) ~]# stty -F /dev/ttymxc1 -a
speed 9600 baud;stty: /dev/ttymxc1
line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ;
eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
[root@armadillo420-0 (pts/1) ~]#

<etc/inittab>以下行をコメントアウトしています。
#::respawn:/sbin/getty -L 15200 ttymxc1 vt102

コメント

プログラムが間違っています。

cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);

は単に&ttyにあるtermios構造体にビット値をセットするだけなので、
その後

tty.c_iflag = IGNBRK | IGNPAR; //ブレーク文字無視/パリティなし
tty.c_cflag = CS8 | CLOCAL | CREAD; //フロー制御なし/8bit/非モデム/受信可

で上書きすると右辺でセットしていないビットであるボーレートの
ビットが消えてしまいます。

修正するのであれば

tty.c_iflag |= IGNBRK | IGNPAR; //ブレーク文字無視/パリティなし
tty.c_cflag |= CS8 | CLOCAL | CREAD; //フロー制御なし/8bit/非モデム/受信可

のようにorして代入するか、そもそもtcsetispeed等は

tty.c_iflag = B115200 | CS8 ... 

と書くのと等価なので、今回のような単発でセットするだけなら
使わないのもアリです。
(ボーレートを複数条件でcase文で分岐する等、直接ビット演算
では書きづらい場合は便利な関数です)

こちら古くからのドキュメントですが、
Linux Serial Programming HOWTOはベーシックから応用まで丁寧な記述で、おすすめです。
https://tldp.org/HOWTO/Serial-Programming-HOWTO/index.html