[ C++で開発 ]
UNIX系OSでは、POSIX規格によりおおよそシリアル通信のシステムコール等が標準化されています。(POSIX.1-2001らしい)
シリアル通信(RS-232C)での設定について、最低限前提となる知識を整理します。
キャラクタ(1文字)の前後に、文字を識別できるように必ず付けるのがスタートビットおよびストップビットです。スタートビットは1ビットですが、ストップビットは1ビット・1.5ビット・2ビットがあります。
EVEN(偶数)、ODD(奇数)、なし、の3つから選択します。EVENまたはODDのときは、データビットとパリティビットの中でビットが1となる数をEVENまたはODDになるよう調整します。
Request To Sendの略で端末からモデムへ出力する制御信号の1つ。フロー制御の方式でハードウェアフロー制御を用いる場合に使われる。
シリアルポートのデバイスファイル名を指定してシステムコールopenを呼び出します。デバイスファイル名は、OSによって異なります。
OS | デバイスファイル名 | 内容 | 備考 |
---|---|---|---|
Solaris 2.x |
/dev/ttya |
ポートA(1) | |
/dev/ttyb |
ポートB(2) | ||
#include <unistd.h> #include <errno.h> int main(int argc, char* argv[]) { int fd = open("/dev/ttya", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("Unable to open /dev/ttya - "); return -1; } :
O_RDWRは、ポートを読み書き両方でオープンする指定
O_NOCTTYは、tty制御をしない指定
O_NDELAYは、***
シリアルポートの属性の取得と設定は、tcgetattrおよびtcsetattrシステムコールを呼び出します。
属性には、ボーレート、データビット数、パリティ、ストップビット、フロー制御等があります。これらを通信の両者で合わせる必要があります。
アプリケーションが使用後は元の設定に戻しておくのが良識でしょう。
struct termios old_options, new_options; int ret; ret = tcgetattr(fd, &old_options); : // 通信処理 ret = tcsetattr(fd, TCSANOW, &old_options); // 既存の設定を復帰 close(fd);
termios構造体は以下のように定義されています。
struct termios { tcflag_t c_iflag; /* input modes */ tcflag_t c_oflag; /* output modes */ tcflag_t c_cflag; /* control modes */ tcflag_t c_lflag; /* line discipline modes */ cc_t c_cc[NCCS]; /* control chars */ };
tcflag_tは、unsigned intのtypedefです。cc_tは、unsigned charのtypedefです。
すべてのビットを0にするのがよい(らしい)。ソフトウェアフロー制御を有効にするときだけ0以外の値を設定。
すべてのビットを0にするのがよい(らしい)。遅い端末へ何とか出力するための制御なので昨今では不要というのが理由。
options.c_cflag &= ~CSIZE; // キャラクタ・サイズ数のビット部分だけ0にセット options.c_cflag |= CS8; // データビット数を8にする
属性定義シンボル | 内容 | ビットマスク |
---|---|---|
CLOCAL | ローカルライン(モデム制御なし) | 0x00000800 |
CREAD | 受信を有効にする | 0x00000080 |
CRTSCTS | ハードウェアフロー制御を有効にする | 0x80000000 |
CSTOPB | ストップビットを2に設定する | 0x00000040 |
CSIZE | データビット数を指定するためのビットマスク | 0x00000030 |
CS5〜CS8 | データビット数、5〜8ビットまで指定可能 | 0x00000000 0x00000010 0x00000020 0x00000030 |
PARENB | パリティビットを有効 | 0x00000100 |
PARODD | パリティビットは奇数とする | 0x00000200 |
CLOCALとCREADを指定しているサンプルコードが多いようです。これは必須なのかもしれません。
CREADを0( options.c_cflag &= CREAD )してみたところ、受信できなくなりました。
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
属性定義シンボル | 内容 |
---|---|
ECHO | 入力文字の表示 |
ECHOCTL | 制御文字を^charとしてエコーする |
ECHOE | |
ECHOK | |
ECHONL | NLをエコーする |
ICANON | |
options.c_cc[VTIME] = 0; // タイマを使わない options.c_cc[VMIN] = 1; // 1文字来るまでreadをブロック