WSLで制御コードのCRを送信するにはどうすればよいですか
解決したいこと
WSLでアスキーベースのシリアル通信で、パソコンから分析機器にCRを送信したいです。
発生している問題・エラー
https://atmarkit.itmedia.co.jp/ait/articles/1711/09/news032_3.html
より、WSLでEnterキーを押すとLFが送信されるのではないかと思います。
CRを送信する方法がわかりません。
追記 2022/01/28
目標
CMO,1[CR]
と送信して、[ACK][CR][LF]
と返事をもらいたい。
コマンドと実行結果
an@DESKTOP-HGVMRCT:~/demo$ stty -F /dev/ttyS1 speed 9600
1200
an@DESKTOP-HGVMRCT:~/demo$ stty -F /dev/ttyS1 speed 9600
9600
an@DESKTOP-HGVMRCT:~/demo$ stty -icrnl
an@DESKTOP-HGVMRCT:~/demo$ ./ssample
シリアルポートを初期化しました
メインループを開始
CMO,1^M
ssample.c
#include <stdio.h>
#include <stdlib.h> //追加
#include <unistd.h>
//#include <conio.h> 無い
#include <ctype.h> //追加
#include <fcntl.h> //追加
#include <string.h>
#include <termios.h> //追加
//#include <io.h> 無い
#define DEV_NAME "/dev/ttyS1"
#define BAUD_RATE B9600
#define BUFF_SIZE 2048
#define NUL 0x00
#define ETX 0x03
#define ENQ 0x05
#define ACK 0x06
#define CR 0x0D
#define LF 0x0A
#define BS 0x08
#define TAB 0x09
#define NAK 0x15
#define ESC 0x1b
char buf[BUFF_SIZE], send_buf[BUFF_SIZE];
void serial_init(int fd)
{
// termios型の構造体tioを宣言
struct termios tio;
memset(&tio, 0, sizeof(tio));
tio.c_iflag = 0;
tio.c_oflag = 0;
//文字サイズ・受信を有効にする・モデムの制御線を無視
tio.c_cflag = CS8 | CREAD | CLOCAL;
tio.c_lflag = 0;
//最小文字数
tio.c_cc[VMIN] = 1;
//タイムアウト時間
tio.c_cc[VTIME] = 0;
//入力ボーレートの設定
cfsetispeed(&tio, BAUD_RATE);
//出力ボーレートの設定
cfsetospeed(&tio, BAUD_RATE);
//デバイスに設定をする
tcsetattr(fd, TCSANOW, &tio);
}
int main(int argc, char **argv)
{
int fd; //ファイルディスクリプタ
unsigned char c;
//デバイスファイル(シリアルポート)オープン
fd = open(DEV_NAME, O_RDWR);
// fd = open(DEV_NAME, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("デバイスを開いているときにエラーが発生しました\n");
exit(1);
}
serial_init(fd); //シリアルポートの初期化
printf("シリアルポートを初期化しました\n");
printf("メインループを開始\n");
//返り値が1の間繰り返す
while (1)
{
// if new data is available on the serial port, print it out
// 受信
if (read(fd, &buf[0], BUFF_SIZE) > 0)
{
write(STDOUT_FILENO, &buf[0], BUFF_SIZE);
printf("\x1b[32m"); //前景色を緑に
if (isprint(c)) //印字可能な文字の場合
printf("%02x", c); //受信データを16進数で表示
else //印字できない文字の場合
{
switch (c)
{
case NUL:
printf("[NUL]\n");
break;
case ETX:
printf("[ETX]\n");
break;
case ENQ:
printf("[ENQ]\n");
break;
case ACK:
printf("[ACK]\n");
break;
case CR:
printf("[CR]\n");
break;
case LF:
printf("[LF]\n");
break;
case BS:
printf("[BS]\n");
break;
case TAB:
printf("[TAB]\n");
break;
case NAK:
printf("[NAK]\n");
break;
default:
printf("[%x]\n", c);
}
}
// if new data is available on the console, send it to the serial port
// 送信
if (read(STDIN_FILENO, &send_buf[0], BUFF_SIZE) > 0)
{
write(fd, &send_buf[0], BUFF_SIZE);
printf("\x1b[37m"); //前景色を白に
if (isprint(c))
printf("%c", c);
switch (c)
{
case LF: //改行で送信「CR」 →「LF」に変更
write(fd, &send_buf[0], BUFF_SIZE);
printf("[[LF]]\n");
break;
case CR: //改行で送信
write(fd, &send_buf[0], BUFF_SIZE);
printf("[[CR]]\n");
break;
case ESC: //エスケープで終了
exit(-1);
default:
write(fd, &send_buf[0], BUFF_SIZE);
}
}
}
}
close(fd);
return(0);
}
追記 2022/01/29
cmo,1^V^M^V^J
と入力し、63 6d 6f 2c 31 0d 0a
と送信、06 0d 0a
と受信できた。
an@DESKTOP-HGVMRCT:~/demo$ stty -icrnl
an@DESKTOP-HGVMRCT:~/demo$ stty -F /dev/ttyS1 speed 9600
9600
an@DESKTOP-HGVMRCT:~/demo$ ./ssample
シリアルポートを初期化しました
メインループを開始
-----------------------------------------------------------
cmo,1^V^M^V
63 6d 6f 2c 31 0d 0a
06 0d 0a
ssample.c [改]
#include <stdio.h>
#include <stdlib.h> // exit
#include <unistd.h> // read write
#include <fcntl.h> // open
#include <string.h>
#include <termios.h> // struct termios
#define DEV_NAME "/dev/ttyS1"
#define BAUD_RATE B9600
#define BUFF_SIZE 2048
char buf[BUFF_SIZE], send_buf[BUFF_SIZE];
void serial_init(int fd)
{
// termios型の構造体tioを宣言
struct termios tio;
memset(&tio, 0, sizeof(tio));
tio.c_iflag = 0;
tio.c_oflag = 0;
//文字サイズ・受信を有効にする・モデムの制御線を無視
tio.c_cflag = CS8 | CREAD | CLOCAL;
tio.c_lflag = 0;
//最小文字数
tio.c_cc[VMIN] = 1;
//タイムアウト時間
tio.c_cc[VTIME] = 0;
//入力ボーレートの設定
cfsetispeed(&tio, BAUD_RATE);
//出力ボーレートの設定
cfsetospeed(&tio, BAUD_RATE);
//デバイスに設定をする
tcsetattr(fd, TCSANOW, &tio);
}
int main(int argc, char **argv)
{
int fd; //ファイルディスクリプタ
unsigned char c;
//デバイスファイル(シリアルポート)オープン
fd = open(DEV_NAME, O_RDWR);
// fd = open(DEV_NAME, O_RDWR | O_NONBLOCK);
//シリアルポートが開けない場合
if (fd < 0)
{
printf("デバイスを開いているときにエラーが発生しました\n");
exit(1);
}
//シリアルポートの初期化
serial_init(fd);
printf("シリアルポートを初期化しました\n");
printf("メインループを開始\n");
printf("-----------------------------------------------------------\n");
while (1)
{
// 送信
size_t readBytes;
readBytes = read(STDIN_FILENO, &send_buf[0], BUFF_SIZE);
if (readBytes > 0)
{
size_t i;
printf("\x1b[36m"); //前景色をシアンに
for (i = 0; i < readBytes; i++)
{
write(fd, &send_buf[i], BUFF_SIZE);
printf("%02x ", send_buf[i]);
}
printf("\x1b[39m\n"); //前景色をデフォルトに
}
// 受信
size_t receiveBytes;
receiveBytes = read(fd, &buf[0], 3);
if (receiveBytes > 0)
{
size_t i;
printf("\x1b[32m"); //前景色を緑に
for (i = 0; i < receiveBytes; i++)
{
printf("%02x ", buf[i]);
}
printf("\x1b[39m\n"); //前景色をデフォルトに
}
}
close(fd);
return (0);
}