ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

シリアル通信でノンブロッキング処理にするには

2016-10-21 15:31:33 | ネットワーク
シリアル通信(だけじゃないと思うけど)において、
入力待ちをしない、いわゆるノンブロッキングにする方法について。

カノニカルモードにすることは知っていると思うけど、
ほかにせっていするところがある。
まとめると、2つの方法があるらしい

【方法1】
1.termiosの
    c_lflag &= ~(ICANON);
  で、カノニカルモード無効化(非カノニカルモード)

2.termiosの
    c_cc[VMIN] = 0;
c_cc[VTIME]= 0;
  にする。このVMINとVTIMEの関係は、以下を参照

termios.c_cc の VMIN VTIME について(メモ)
http://oasynnoum.hatenablog.com/entry/2012/10/31/184038


【方法2】
 上記さいとにある、O_NDELAY指定。つまり、openでO_NONBLOCK または O_NDELAYを指定する。
詳しくは、以下のサイト

open - システムコールの説明 - Linux コマンド集 一覧表
http://kazmax.zpp.jp/cmd/o/open.2.html


ちなみに、以前の記事

LinuxのCで、キー入力されたらすぐ表示するけど、入力しないとき待たないようにしたい
http://blog.goo.ne.jp/xmldtp/e/067f5e0ff4efeca546e4458f4d36a619

では(これはコンソール端末=標準入力なので、fd=0で説明している)、
方法1で、VMIN=0,VTIME=1にしている

以下、raspberry piのシリアル通信における方法1の雰囲気(確認していないので、バグがあるかも・・・)

/*
 *	ノンブロッキングテスト
 *	内容 電文の送受信を1電文繰り返す
 *	参考:	http://www.rt-shop.jp/blog/archives/4145 (シリアル通信)
 *		http://oasynnoum.hatenablog.com/entry/2012/10/31/184038 (ノンブロッキング)
 *		http://simd.jugem.jp/?eid=145 (時間部分)
 */

#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#include <time.h>
#include <sys/time.h>

#define SERIAL_PORT	"/dev/ttyAMA0"
#define BAUDRATE	B9600

int main(int argc, char *argv[])
{
	int		fd;
	char		com[16];	//	とりあえず16バイト以上来ないものとする
	char		buf[2];		//	一時的に入れておく
	struct termios	newtio, oldtio;	//	コントロールの構造体
	int		len;		//	文字列の長さ
	clock_t nowtime,oldtime;
	double		keika;		//	経過時間

	//==============================//
	//	オープンと設定		//
	//==============================//
	if(!(fd = open(SERIAL_PORT, O_RDWR)))
	{
		printf("data error \n");
		return -1;
	}

       	//	現在のシリアルポートの設定を待避
	ioctl(fd, TCGETS, &oldtio);
 
	//	ポートのコントロール初期化
	bzero(&newtio, sizeof(newtio));
	newtio = oldtio;	// ポートの設定をコピー=基本的には同じにする
				//	ボーレートなど設定
	newtio.c_cflag = (BAUDRATE | CS8 | CLOCAL | CREAD);
 
	newtio.c_iflag = (IGNPAR);	//	エラー処理:無視
 	newtio.c_oflag = 0;
					//	非カノニカルモード
	newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	newtio.c_cc[VMIN] = 0;		//	ノンブロッキング
	newtio.c_cc[VTIME]= 0;

 	ioctl(fd, TCSETS, &newtio);	//	初期設定


	//==============================//
	//	データ処理		//
	//==============================//
	bzero(com, sizeof(com));
	len	=	0;	//	文字の長さ=次に文字が入るところ
	oldtime = clock();
	while(len < 15)
	{
		if ( read(fd,buf,1) <= 0 )	//	1バイトだけ読む
		{	//	読めないとき
			nowtime = clock();
			keika = ((double)(nowtime - oldtime)) / (double)CLOCKS_PER_SEC;
			if (keika > 0.5)	//	0.5秒たっても読めない
			{
				printf("no data \n");
				oldtime = nowtime;
				continue;
			}
		}
		else
		{
			com[len] = buf[0];
			len++; 
			oldtime = nowtime;
			nowtime = clock();
		}
	}
	com[len] = 0;
	printf("data:%s\n",com);

	//==============================//
	//	終了			//
	//==============================//
	newtio = oldtio;		// ポートの設定を戻す
 	ioctl(fd, TCSETS, &newtio);	//	前に戻す
	close(fd);
	printf("end\n");

}


この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« プログラムの型とデバッグ手... | トップ | 杉並清掃工場、ビッグデータ... »
最新の画像もっと見る

ネットワーク」カテゴリの最新記事