2017年7月9日日曜日

Cで非カノニカル、非ブロッキングなシリアル通信プログラム

シリアル通信では2種類の設定項目があります。

カノニカルor非カノニカル

  • カノニカル(デフォルト)
    通信の単位は「行」、つまり\nの文字が来たらデータを送信する。つまりwrite(fd,"hello",5);では送信を行わなく、write(fd,"hell\n",6);で初めて送信をする。また\nを受信したらそこまでのデータを1行だとして受信処理をする。
  • 非カノニカル
    通信の単位は「Byte」つまりwrite(fd,"hello",5);でも送信をするし、受信も\nが来ていなくてもreadでデータを読み出せる。

 ブロッキングorノンブロッキング

  • ブロッキング(デフォルト)
    read関数を使ったときに、データを受信するまで、そこでウェイトをする。カノニカルモードなら\nが来るまで待つし、非カノニカルモードなら1byteでもデータが来るまで待つ。
  • ノンブロッキング
    read関数を使ったときに何もデータが来ていなくてもウェイトは発生せず、何も受信しなかったという結果を返す。read関数の返り値が受信バイト数。
普通のPCのプログラミングだとカノニカルかつブロッキングが通信をすることが普通です。組み込み的なプログラムは非カノニカルかつノンブロッキングに書くのが普通でしょう。この設定を書く資料が微妙に見つけにくいのでメモ的に書いておきます。
ノンブロッキングモードはopenで_NONBLOCKINGをつけるだけで良いとありましたがUbuntu14.4ではそれではダメなようです。

########モード#########

#include <stdio.h>

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

int main()
{   
    int fd1=open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    fcntl(fd1, F_SETFL,0);
    //load configuration
    struct termios conf_tio;
    tcgetattr(fd1,&conf_tio);
    //set baudrate
    speed_t BAUDRATE = B1000000;
    cfsetispeed(&conf_tio, BAUDRATE);
    cfsetospeed(&conf_tio, BAUDRATE);
    //non canonical, non echo back
    conf_tio.c_lflag &= ~(ECHO | ICANON);
    //non blocking
    conf_tio.c_cc[VMIN]=0;
    conf_tio.c_cc[VTIME]=0;
    //store configuration
    tcsetattr(fd1,TCSANOW,&conf_tio);

    write(fd1,"#;",2);
    printf("Bytes sent\n");
   
    sleep(1);
   
    char buff[100]="=======================";
    int rd=read(fd1,buff,sizeof(buff));
    printf("Bytes sent are %s\n",buff);
    printf("rd:%d\n",rd);
    close(fd1);
    return 0;
}

0 件のコメント:

コメントを投稿