Sunday, November 16, 2008

シリアル通信メモ

参考:
[1] シリアル通信プログラム
[2] プログラム例
[3] Manpage of TERMIOS

[4] Serial Programming:Unix/termios
[5] Serial Programming Guide for Posix Operating Systems 非常に簡潔に説明してある.わかりやすい09-03-27
[6] シリアル通信の“Space voltage” の説明ページ ( [pdf])またここの説明もわかりやすい09-03-27
[7] プログラム例2 結構詳細なコメントがある
■ Openning A Serial Port [5]

   fd = open("/dev/ttyS0", O_RDWR  O_NOCTTY  O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);

と書いてある.なぜ“fcntl()”を使用したのか?をずっと考えてみた.“open()”の部分だけで十分じゃないのかと思った.ネット上のサンプルシリアルプログラムはこの部分はない.なぜだ?

オープンファイル記述 (open file description) には、ファイル記述毎に設定される状態フラグがいくつかある。これらのフラグは open(2) によって初期化され、 fcntl(2) により変更することもできる
(Manpage of FCNTL より)

どうもファイルの状態を変更したいからそうやったみたいだな.
■ O_NOCTTY ( output --> no control tty )

ttyを制御しない.
という説明でわかるか!
ファイルをOpenするときに,open()で指定したファイルはもしデバイスファイルであれば,たとえばそのプロセスが制御端末を持っていなくても,Openしたファイルは制御端末にならない.つまりopenして放置するということ.例えば“Ctrl+C”が発生しても終了しないとか,いろいろ端末に対する制御を無視
ってやっぱりよくわからん.試してみるしかないな~,指定するとしないときの違い
制御端末という言葉はこのサイトの説明はわかりやすい(daemon起動時の2重forkの理由節)

*追記2009-04-01:
O_NOCTTYの日本語の説明は“ttyを制御しない” と説明しているが,“/usr/include/fcntl.h”を読んだらO_NOCTTYの行のコメントは

#define O_NOCTTY 0x8000 /* don't assign controlling terminal */
でした.やっと意味がわかった.なんでdon't assign controlling terminalをttyを制御しないと訳したんだ?自分もだけどO_NOCTTYをno control ttyの略と勘違いして決めつけちゃったかもしれない.わかりにくい!!!.これはユーザのプログラムがオープンしたファイルはデバイスファイル(シリアルポート)でこのファイルをプログラムの制御端末にしないでほしいということだ.シリアルポートをそれを開いたプログラムに制御端末として割り当てないでほしい!なるほど~.よく組み込みLinuxで外部からシリアル―シリアル接続で制御を行うときシリアルポートを制御端末として使っているじゃん.でもここではその機能がほしくないからO_NOTTYをセットしているの!

■ カノニカル&非カノニカル 入力,同期 & 非同期入力

  • カノニカル:入力はEnterキーを押すまで入力バッファにデータが貯められる(Default設定)
  • 非カノニカル:read()で決まった文字を読み出す.足りないときはブロックになるのか?まだわからん
  • 同期:入力が終わるまでread()はブロックされる(Default設定)
  • 非同期:read()はブロックされることなく,終了になる.

カノニカル入力処理
これは端末に対しての通常の処理モードですが、他のデバイスとの通信の時にも便利です。全ての入力は行単位で処理されます。つまり、read は入力の1行全体のみを返してきます。デフォルトでは、行はNL(ASCII のLF)、ファイル終端、行終端文字のいずれかで終ります。標準の設定では、CR (DOS/Windows のデフォルトの行終端文字)は行の終端とはなりません。
カノニカル入力処理では、消去(erase)、単語の削除(delete word)、文字の再出力(reprint characters)、CRのNLへの変換などを扱うことができます。

非カノニカル入力処理
非カノニカル入力処理は、read 毎に決まった数の文字を扱う方法で、キャラクタタイマを利用することもできます。このモードはアプリケーションが決まった文字数のキャラクタを読み込む時や、接続したデバイスが大量の文字を送ってくる場合に使用します。

非同期入力
上記2つのモードは、同期及び非同期モードで使うことができます。デフォルトは、入力がうまくいくまで read 文がブロックされる同期モードです。非同期モードでは、read 文は即座に終了し、後で読み込みが完了した時にプログラムにシグナルが送られます。このシグナルは、シグナルハンドラを使って受け取ります。
■ DCD(Data Carrier Detect) 1番ピン(9ピンポートの場合)
これはモデムが相手とつながっているかどうかを検出するためのものです.下の図(wikipediaより)はDCDがRTSとつながっていることがわかる.The Linux Serial HOWTO:ピン配置と信号節でポートのオープンを禁止する方法について

シリアルポートのlocalフラグを無効にする場合,DCDがオン(+12V)になるまではシリアルポートをOpenできない
と書いてある.シリアルポートをOpenするとにに
fd = open("/dev/ttyS0", O_RDWR O_NOCTTY O_NDELAY)
のようにOpenする.オプションO_NDELAYはDCDのシグナル線を無視するようになる.もしこれを指定しないとDCDシグナル線がSpace Voltage(オン)になるまでプロセスはSleep状態になるらしい[5] , [6] なるほど




ピン番号 ピン番号 略称 正式名称 方向 動作および目的
9ピン 25ピン
3 2 TxD Transmit Data → PC からバイトデータを送信する
2 3 RxD Receive Data ← PC がバイトデータを受け取る
7 4 RTS Request To Send → RTS/CTS フロー制御
8 5 CTS Clear To Send ← RTS/CTS フロー制御
6 6 DSR Data Set Ready ← 通信可能になったことを知らせる
4 20 DTR Data Terminal Ready → 通信可能になったことを知らせる
1 8 DCD Data Carrier Detect ← モデムが相手と繋がっていることを示す
9 22 RI Ring Indicator ← 電話のベルが鳴っている状態を示す
5 7 Signal Ground


■ Cooked モード,Raw モード?
Cookedモードはキーボードから入力した“キー”(特に制御キー,特殊キー,例:Backspace, Delete, Ctrl+ D, など)を処理してからプログラムに渡すモードで,どのように処理するかはOSによって異なる.これに対しRawモードは入力したキーをそのまま前処理せずに渡す.

例えば“ABC<BackSpace>D”を入力すると
  • Cookedモードではプログラムに渡されるのは“ABD”になり
  • Rawモードでは“ABC<BackSpace>の文字コードD”になる
■STOP BIT, START BIT
キャラクタ(1文字)の前後に、文字を識別できるように必ず付けるのがスタートビットおよびストップビットです。スタートビットは1ビットですが、ストップビットは1ビット・1.5ビット・2ビットがあります。

■パリティビット
EVEN(偶数)、ODD(奇数)、なし、の3つから選択します。EVENまたはODDのときは、データビットとパリティビットの中でビットが1となる数をEVENまたはODDになるよう調整します。シリアル通信で必要な機能:
ボーレート設定
read()
write()

[未完成]