シリアルテストサンプル(Linux)
とりあえずで作ったシリアルのテストプログラムです。
ソースはあまりにも無様で下手したらコンパイル通らないかも!?
コンパイルは、gccで-Wallでもつけてください。
unsigned系は、typedefで定義しなおしたほうがいいです。
無保証なので、個人責任でご利用ください。

尚、本ページが万が一役にたった、ということがあれば、
HOME(最下部にリンク在)のTreeBBSに、何かメッセージをご記入ください。
お仕事中の方でも休み時間に、是非お願い致します。


シリアルテスト@Linux (OLD)


[1]シリアル設定
(1)COM1の設定
#setserial /dev/ttyS0 port 0x3f8 auto_irq skip_test autoconfig
(2)COM2の設定
#setserial /dev/ttyS1 port 0x2f8 auto_irq skip_test autoconfig


[2]テストプログラム
 (1)serial_lib.h
////////////////////////////////
// シリアルポートの初期化関数 //
////////////////////////////////
int init_sci(unsigned char *);

//////////////////////////////////
// シリアルポートのクローズ関数 //
//////////////////////////////////
int close_sci(unsigned int);

/////////////////////////////
// シリアル1バイト受信関数 //
/////////////////////////////
int get_sci(unsigned int ,char *);

//////////////////////
// シリアル受信関数 //
//////////////////////
int str_get_sci(unsigned int ,unsigned char *,unsigned int);

///////////////////////
// シリアル送信関数 //
//////////////////////
int str_put_sci(unsigned int ,unsigned char *,unsigned int);


 (2)serial_lib.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

////////////////////////////////
// シリアルポートの初期化関数 //
////////////////////////////////
int init_sci(unsigned char *sci_fd_name)
{
        struct termios tio;
        int sci_fd;

        printf("open sci:[%s]\n",sci_fd_name);
        if ((sci_fd = open(sci_fd_name, O_RDWR | O_NOCTTY | O_NONBLOCK))<0)
        {
                printf("sci open failed.\n");
                exit(-1);
        }
        memset(&tio,0x00,sizeof(tio));
        tio.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
        tio.c_iflag = IGNPAR;
        tio.c_oflag = 0;
        tio.c_lflag = 0;
        tio.c_cc[VTIME] = 0;
        tio.c_cc[VMIN] = 1;

        tcflush(sci_fd, TCIFLUSH);
        tcsetattr(sci_fd, TCSANOW, &tio);
        fcntl(sci_fd, F_SETFL, FNDELAY);

        return sci_fd;
}

//////////////////////////////////
// シリアルポートのクローズ関数 //
//////////////////////////////////
int close_sci(int sci_fd)
{
        close(sci_fd);
        return 0;
}

/////////////////////////////
// シリアル1バイト受信関数 //
/////////////////////////////
int get_sci(unsigned int scifd,unsigned char *get_char)
{
        int retval=0;

        while((retval = read(scifd, get_char, 1))<0) {
                switch (errno) {
                        case EAGAIN :
                        break;
                        default :
                                perror(strerror(errno));
                                return -1;
                }
        }

        return retval;
}

//////////////////////
// シリアル受信関数 //
//////////////////////
int str_get_sci(unsigned int scifd,unsigned char *get_str,unsigned int str_len)
{
        unsigned char tempbuff;
        int retval=0,loopcnt;

        for(loopcnt = 0; loopcnt<str_len; loopcnt++)
        {
                get_sci(scifd,&tempbuff);
                *get_str = tempbuff;
                get_str++;
        }
        return retval;
}

///////////////////////
// シリアル送信関数 //
//////////////////////
int str_put_sci(unsigned int scifd,unsigned char *put_str,unsigned int str_len)
{
        int retval=0,loopcnt;
        for(loopcnt = 0; loopcnt<str_len; loopcnt++)
        {
                retval = write(scifd,put_str,1);
                if(retval < 0)
                {
                        break;
                }
                put_str++;
        }
        return retval;
}


 (3)serial_test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "serial_lib.h"

#define SIOFD_NAME_SIZE 516
#define SEND_RECV_SIZE  2048
#define RECV_DATA_SIZE  5

//メイン関数
int main(int argc,char *argv[])
{
        //シリアルポート仮想ファイルディスクリプタ
        static int sci_fd;
        int retval = -1;
        unsigned char sci_fd_name[SIOFD_NAME_SIZE];//シリアルポート仮想ファイル名
        unsigned char data_buff[SEND_RECV_SIZE];//送受信データ

        //引数の数チェック
        if(argc < 3)
        {
                printf("usage:serialtest port send_data \n");
                return retval;
        }

        //シリアルポートの初期化
        memset(sci_fd_name,0x00,SIOFD_NAME_SIZE);
        strncpy(sci_fd_name,argv[1],SIOFD_NAME_SIZE);
        sci_fd = init_sci(sci_fd_name);
        if(sci_fd == -1)
        {
                printf("init sci failed.\n");
                return retval;
        }

        //送信データセット
        memset(data_buff,0x00,sizeof(data_buff));
        strncpy(data_buff,argv[2],SEND_RECV_SIZE);
        //送信処理
        printf("send:[%s]",data_buff);
        retval = str_put_sci(sci_fd,data_buff,strlen(data_buff));
        if(retval == -1)
        {
                printf("send failed.\n");
                return retval;
        }
        printf("...sending done !!\n");

        //受信処理
        memset(data_buff,0x00,sizeof(data_buff));
        retval = str_get_sci(sci_fd,data_buff,RECV_DATA_SIZE);
        if(retval == -1)
        {
                printf("recv failed.\n");
                return retval;
        }

        printf("recv:[%s]\n",data_buff);
        close_sci(sci_fd);

        return retval;
}


[3]コンパイル
gcc -g -Wall serial_lib.c serial_test.c -o serialtest


[4]実行結果
 ・クロスケーブルでCOM1,COM2をダイレクトに接続。
 ・ターミナルを2つ起動し、それぞれCOM1,COM2で実行。

# ./serialtest /dev/ttyS0 test1
open sci:[/dev/ttyS0]
send:[test1]...sending done !!
recv:[hoge1]
# ./serialtest /dev/ttyS0 test2
open sci:[/dev/ttyS0]
send:[test2]...sending done !!
recv:[hoge2]
 
# ./serialtest /dev/ttyS1 hoge1
open sci:[/dev/ttyS1]
send:[hoge1]...sending done !!
recv:[test2]
# ./serialtest /dev/ttyS1 hoge2
open sci:[/dev/ttyS1]
send:[hoge2]...sending done !!



[5]その他
 ・スーパユーザ権限がいいよ。
 ・受信バイト5バイト固定でやっているから注意!

 ・あるアプリのプログラムのテスト用に作ったからソースは無様。

シリアルテスト@Linux (NEW)


serial_test.h


//バッファサイズ
#define SIOFD_NAME_SIZE 516
#define SEND_RECV_SIZE  512
#define RECV_DATA_SIZE  512

//制御キャラクタ
#define STX 0x02
#define ETX 0x03
#define ENQ 0x05
#define ACK 0x06


////////////////////////////////
// シリアルポートの初期化関数 //
////////////////////////////////
int init_sci(unsigned char *);

//////////////////////////////////
// シリアルポートのクローズ関数 //
//////////////////////////////////
int close_sci(int);

/////////////////////////////
// シリアル1バイト受信関数 //
/////////////////////////////
int get_sci(unsigned int ,char *);

//////////////////////
// シリアル受信関数 //
//////////////////////
int str_get_sci(unsigned int ,unsigned char *,unsigned int);

//////////////////////////////
// シリアル1バイト送信関数 //
/////////////////////////////
int put_sci(unsigned int ,unsigned char *);

///////////////////////
// シリアル送信関数 //
//////////////////////
int str_put_sci(unsigned int ,unsigned char *,unsigned int);


/////////////////////////////////
//  16進数変換処理⇒16進ASCII  //
/////////////////////////////////
unsigned char _htoa(unsigned char);

/////////////////////////////////
//  16進数変換処理⇒16進ASCII  //
/////////////////////////////////
void _hex2str(unsigned char,unsigned char *,unsigned char *);

////////////////////////
//  チェックサム計算  //
////////////////////////
unsigned int calc_sum(unsigned char *,unsigned int);



serial_test_func.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include "serial_test.h"

////////////////////////////////
// シリアルポートの初期化関数 //
////////////////////////////////
int init_sci(unsigned char *sci_fd_name)
{
        struct termios tio;
        int sci_fd;

        printf("open sci:[%s]\n",sci_fd_name);
        if ((sci_fd = open(sci_fd_name, O_RDWR | O_NOCTTY | O_NONBLOCK))<0)
        {
                printf("sci open failed.\n");
                exit(-1);
        }
        memset(&tio,0x00,sizeof(tio));
        tio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
        //tio.c_cflag = B38400 | CS8 | CLOCAL | CREAD;
        tio.c_iflag = IGNPAR;
        tio.c_oflag = 0;
        tio.c_lflag = 0;
        tio.c_cc[VTIME] = 0;
        tio.c_cc[VMIN] = 1;

        tcflush(sci_fd, TCIFLUSH);
        tcsetattr(sci_fd, TCSANOW, &tio);
        fcntl(sci_fd, F_SETFL, FNDELAY);

        return sci_fd;
}

//////////////////////////////////
// シリアルポートのクローズ関数 //
//////////////////////////////////
int close_sci(int sci_fd)
{
        close(sci_fd);
        return 0;
}

/////////////////////////////
// シリアル1バイト受信関数 //
/////////////////////////////
int get_sci(unsigned int scifd,char *get_char)
{
        int retval=0;

        while((retval = read(scifd, get_char, 1))<0) {
                switch (errno) {
                    case EAGAIN :
                        break;
                    default :
                        perror(strerror(errno));
                        return -1;
                }
        }

        return retval;
}

//////////////////////
// シリアル受信関数 //
//////////////////////
int str_get_sci(unsigned int scifd,unsigned char *get_str,unsigned int str_len)
{
        unsigned char tempbuff;
        int retval=0,loopcnt;

        for(loopcnt = 0; loopcnt= 0x0A)
    {
        data -= 0x09;
        data += 0x40;
    }
    else
    {
        data += 0x30;
    }
    return data;
}

/*********************************************************************************
    _hex2str                                   16進数変換処理⇒16進ASCII
    ※1バイト(1B)⇒2バイト(2B(上位1B+下位1B))
**********************************************************************************/
void _hex2str(unsigned char data,unsigned char *hi,unsigned char *low)
{
    unsigned char h_tmp,l_tmp;
    h_tmp = data >> 4;
    l_tmp = data & 0x0F;

    *hi =  _htoa(h_tmp);
    *low = _htoa(l_tmp);
}


/*********************************************************************************
    calc_sum                                        チェックサム作成
**********************************************************************************/
unsigned int calc_sum(unsigned char *recv_data,unsigned int length)
{
    int temp_sum = STX + ETX; //STX〜ETXのチェックSUMの計算値
    unsigned int i;

    //STX〜ETXまでのSUM
    for(i=0;i<length;i++)
    {
        temp_sum += *recv_data;
        recv_data++;
    }
    temp_sum &= 0x00FF; //STX〜ETXまでのSUM値の上位1バイトカット
    temp_sum ^= 0x00FF; //STX〜ETXまでのSUM値とXOR

    // チェックサム結果を返す。
    return temp_sum;
}



serial_test.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include "serial_test.h"
////////////////////////////
// 送信回数               //
////////////////////////////
#define SEND_CNT 1

////////////////////////////
// 制御キャラクタ送信設定 //
////////////////////////////
#define SET_SEND_STX_ETX
#define SET_SEND_ENQ
#define SET_SEND_ACK
#define SET_SEND_CHK_SUM
#define SET_RECV_DATA

#ifdef SET_SEND_STX_ETX
unsigned char stx = STX;
unsigned char etx = ETX;
#endif

#ifdef SET_SEND_ENQ
unsigned char enq = ENQ;
#endif

#ifdef SET_SEND_ACK
unsigned char ack = ACK;
#endif

#ifdef SET_SEND_CHK_SUM
unsigned char chksum_hi = 0x00;
unsigned char chksum_low = 0x00;
#endif

//////////////
//メイン関数//
//////////////
int main(int argc,char *argv[])
{
    int i;


        //シリアルポート仮想ファイルディスクリプタ
        static int sio_fd;
        int retval = -1;
        unsigned char sio_fd_name[SIOFD_NAME_SIZE];	//シリアルポート仮想ファイル名
        unsigned char data_buff[SEND_RECV_SIZE];	//送受信データ

        //引数の数チェック
        if(argc < SEND_CNT+2)
        {
                printf("usage:serialtest port send_data \n");
                return retval;
        }

        //シリアルポートの初期化
        memset(sio_fd_name,0x00,SIOFD_NAME_SIZE);
        strncpy(sio_fd_name,argv[1],SIOFD_NAME_SIZE);
        sio_fd = init_sio(sio_fd_name);
        if(sio_fd == -1)
        {
                printf("init sio failed.\n");
                return retval;
        }

#ifdef SET_SEND_ENQ
        //ENQ送信
        retval = put_sio(sio_fd,&enq);
        if(retval < 0)
        {
                printf("enq send failed.\n");
                return retval;
        }
        printf("enq send;wait ack.\n");

        //ENQに対するACK受信
        retval = get_sio(sio_fd,&data_buff[0]);
        if(retval < 0)
        {
                printf("ack recv failed.\n");
                return retval;
        }
        printf("ack recv.\n");
#endif
    for(i=0;i<SEND_CNT;i++)
    {
        //送信データセット
        memset(data_buff,0x00,sizeof(data_buff));
        strncpy(data_buff,argv[i+2],SEND_RECV_SIZE);

        //送信処理
#ifdef SET_SEND_STX_ETX
        retval = put_sio(sio_fd,&stx);
        if(retval < 0)
        {
                printf("stx send failed.\n");
                return retval;
        }
        printf("stx send.\n");
#endif
        printf("send:[%s]\n",data_buff);
        retval = str_put_sio(sio_fd,data_buff,strlen(data_buff));
        if(retval < 0)
        {
                printf("send failed.\n");
                return retval;
        }
#ifdef SET_SEND_STX_ETX
        retval = put_sio(sio_fd,&etx);
        if(retval < 0)
        {
                printf("etx send failed.\n");
                return retval;
        }
        printf("etx send.\n");
#endif
#ifdef SET_SEND_CHK_SUM
        chksum_hi = calc_sum(argv[i+2],strlen(argv[i+2]));
        _hex2str(chksum_hi,&chksum_hi,&chksum_low);
        retval = put_sio(sio_fd,&chksum_hi);
        if(retval < 0)
        {
                printf("chksum hi send failed.\n");
                return retval;
        }
        retval = put_sio(sio_fd,&chksum_low);
        if(retval < 0)
        {
                printf("chksum low send failed.\n");
                return retval;
        }
        printf("chk sum send.\n");
#endif
        printf("...sending done !!\n");
    }//送信ループ終了

        // コマンドに対するACK受信
        retval = get_sio(sio_fd,&data_buff[0]);
        if(retval < 0)
        {
                printf("ack recv failed.\n");
                return retval;
        }
        printf("ack/nak recv.[%.02X]\n",data_buff[0]);

#ifdef SET_RECV_DATA
        //受信処理
        memset(data_buff,0x00,sizeof(data_buff));
        // retval = str_get_sio(sio_fd,data_buff,RECV_DATA_SIZE);
        retval = str_get_sio(sio_fd,data_buff,10);
        if(retval < 0)
        {
                printf("recv failed.\n");
                return retval;
        }
        printf("recv:[%s]\n",&data_buff[1]);
#endif

#ifdef SET_SEND_ACK
        //データ受信に対するACK送信
        retval = put_sio(sio_fd,&ack);
        if(retval < 0)
        {
                printf("ack send failed.\n");
                return retval;
        }
        printf("ack send.\n");
#endif

        close_sio(sio_fd);

        return retval;
}


<おわり>

Links:
HOME
WIKI PAGE
Macha's Home Page