シリアルテストサンプル(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