第 7 章 シリアル通信 91
7.4 チュートリアル
7.4.2 受信
Step3 プログラムの解説
まず、オープンシステムコールでシリアルポートをオープンします。
第一引数に「/dev/ttyG0」という値を指定しています。この値は、ITC-N4007のUART CN1に割当てられているデバイス ノードです。※1
この値を指定し、実行したオープンシステムコールの戻り値を用いてITC-N4007のUART CN1の制御を行います。
次にtcflush関数を使用して受信バッファ、送信バッファをクリアします。
次に通信パラメータの設定を行います。tcsetattr関数を用いることで設定を行うことができます。
今回作成したプログラムでは以下の設定を行っております。
・ボーレート :38400bps
・データ長 :8bit
・ストップビット :1bit
・パリティチェック:なし
・フロー制御 :ハードウェアフロー制御 ※2
・カノニカルモード:有効 ※3
次にwrite関数を用いてデータの送信を行います。
第一引数にはオープンシステムコール関数で取得したファイルディスクリプタ、第二引数には送信するデータを格納し た配列、第三引数には送信するデータサイズを指定します。
最後にオープンしたシリアルポートのクローズを行います。
オープンしたシリアルポートは終了時には必ずクローズを行ってください。
※1 シリアルポートのデバイスノード「/dev/ttyGxx」はデバイスの認識した順番に番号が割り振られていきます。そのため、
デバイスごとの一意な名前ではありません。
デバイス名を確認するにはコンソール上で「cat /proc/tty/driver/cp4161」と入力します。
入力後、デバイスノード、製品型式が表示されます。
#cat /proc/tty/driver/cp4161
ttyG0: PCI/LPC-466120(P)(bid=0h) CH1 [9600bps] tx:0 rx:0 ttyG1: PCI/LPC-466120(P)(bid=0h) CH2 [9600bps] tx:0 rx:0
※ITC-N4007のUART CN1, CN2はそれぞれPCI-466120 CH1, CH2として表示されます。
前面下側には16550互換のUARTが2ポート搭載されています。
デバイスノードはそれぞれ、/dev/ttyS0、/dev/ttyS1となります。
※2 フロー制御については「7.1.8 フロー制御」のハードウェアフロー制御を参照してください。
ケーブルの結線については「7.3 環境図」を参照してください。
※3 カノニカルモードが有効な場合、送受信が行単位での動作となります。
送信の場合、行区切り文字をwrite関数に渡すまでデータの送信を行いません。
受信の場合、行区切り文字を受け取るまでread関数の処理から抜けません。
7.4.2 受信
Step1 プログラム作成
エディタを起動し、下記に示すプログラムを入力して、ファイル名を「Receive.c」として保存してください。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <linux/serial.h>
#include <asm/ioctls.h>
#define BAUDRATE B38400 char Recv_Buf[255];
int main(void) {
int fd;
int Ret;
struct termios Newtio;
// ポートのオープン
fd = open("/dev/ttyG1", O_RDWR | O_NOCTTY );
if ( fd < 0 ) {
printf( "Open fd Error ! Exit !¥n " );
return -1;
}
bzero( &Newtio, sizeof( Newtio ) );
Newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL| CREAD;
Newtio.c_iflag = IGNPAR | ICRNL;
Newtio.c_oflag = 0;
Newtio.c_lflag = ICANON;
// バッファのクリア
Ret = tcflush( fd, TCIOFLUSH );
if (Ret != 0 ){
printf( " tcsetattr Error ¥n" );
close( fd );
exit( -1 );
}
// 通信パラメータの設定
Ret = tcsetattr( fd, TCSANOW , &Newtio );
close( fd );
exit( -1 );
}
// 受信データを取得
if ( ( Ret = read( fd, Recv_Buf, 255 ) ) == -1 ) { printf( "Read Return Error ¥n" );
close( fd );
return -1;
}
// 受信データの表示 Recv_Buf[Ret] = 0;
printf( "Receive Characters¥n%s ",Recv_Buf );
// ポートのクローズ close( fd );
}
次にMakefileを作成します。エディタを起動し、下記に示すコードを記述します。
CC = gcc
TARGET = Receive all: $(TARGET) clean:
rm -f $(TARGET) *~
コードの記述が終わったら保存してください。
保存するファイル名は「Makefile」としてください。
Step2 コンパイル/実行
ソースコード・Makefileを保存したディレクトリに移動し、コマンドラインから下記コマンドを実行します。
下記コマンドを実行することでコンパイルを行う事が出来ます。
make
コンパイルが成功すると、オブジェクトファイル「Receive.o」と実行ファイル「Receive」が作られます。
※ErrorやWarningが表示された場合はコードの記述に誤りがありますので内容を見直してください。
プログラムを実行するには、以下のコマンドを実行します。
./Receive
実行すると何も表示されず処理が停止します。
この状態で「送信」で作成したプログラムを実行してください。
「送信」のプログラム実行後、正常に処理が終了すると下記が表示されます。
Receive Characters 0123456789ABCDEFG
今回作成したプログラムはシリアルデータの受信を行うプログラムです。
データの受信を行うには、read関数を使用します。
ITC-N4007のUART CN2でデータを受信し、受信したデータを表示します。
Step3 プログラムの解説
まず、オープンシステムコールでシリアルポートをオープンします。
第一引数に「/dev/ttyG1」という値を指定しています。この値は、ITC-N4007のUART CN2に割当てられているデバイス ノードです。※1
この値を指定し、実行したオープンシステムコールの戻り値を用いてITC-N4007のUART CN2の制御を行います。
次にtcflush関数を使用して受信バッファ、送信バッファをクリアします。
次に通信パラメータの設定を行います。tcsetattr関数を用いることで設定を行うことができます。
今回作成したプログラムでは以下の設定を行っております。
・ボーレート :38400bps
・データ長 :8bit
・ストップビット :1bit
・パリティチェック:なし
・フロー制御 :ハードウェアフロー制御 ※2
・カノニカルモード:有効 ※3
次にread関数を用いてデータの送信を行います。
第一引数にはオープンシステムコール関数で取得したファイルディスクリプタ、第二引数には受信したデータを格納す る配列のポインタ、第三引数には受信する最大データサイズを指定します。
関数の戻り値には実際に受信できたデータサイズが返されます。
最後にオープンしたシリアルポートのクローズを行います。
オープンしたシリアルポートは終了時には必ずクローズを行ってください。
※1 シリアルポートのデバイスノード「/dev/ttyGxx」はデバイスの認識した順番に番号が割り振られていきます。そのた め、デバイスごとの一意な名前ではありません。
デバイス名を確認するにはコンソール上で「cat /proc/tty/driver/cp4161」と入力します。
入力後、デバイスノード、製品型式が表示されます。
#cat /proc/tty/driver/cp4161
ttyG0: PCI/LPC-466120(P)(bid=0h) CH1 [9600bps] tx:0 rx:0 ttyG1: PCI/LPC-466120(P)(bid=0h) CH2 [9600bps] tx:0 rx:0
※ITC-N4007のUART CN1, CN2はそれぞれPCI-466120 CH1, CH2として表示されます。
前面下側には16550互換のUARTが2ポート搭載されています。
デバイスノードはそれぞれ、/dev/ttyS0、/dev/ttyS1となります。
※2 フロー制御については「7.1.8 フロー制御」のハードウェアフロー制御を参照してください。
信号線(RS、CS)が配線されていない場合正常に送受信を行うことができません。
ケーブルの結線については「7.3 環境図」を参照してください。
※3 カノニカルモードが有効な場合、送受信が行単位での動作となります。
送信の場合、行区切り文字をwrite関数に渡すまでデータの送信を行いません。
受信の場合、行区切り文字を受け取るまでread関数の処理から抜けません。