Linuxシステムでは、bashを使用してマイクロコントローラからいくつかの文字列データを送受信しようとしています。
この時点で、私のマイクロコントローラのコードは次のようになります。
void UART_help_cmd_handler()
{
printf("Available commands:\n");
printf("search - starts search and returns device addresses\n");
printf("help - prints this help\n");
// these characters can't stop cat
EUSART2_Write(0);
EUSART2_Write(0x03);
EUSART2_Write(0x04);
}
これはLinux側です:
#!/bin/bash
echo -ne '\x02help\x03' > /dev/ttyUSB0; cat /dev/ttyUSB0;
私も次のことを試しました。
echo -ne '\x02help\x03' > /dev/ttyUSB0; stdbuf -i 0 -o 0 cat /dev/ttyUSB0
問題は、cat
マイクロコントローラ側で停止できないことです。
マイクロコントローラで文字転送を試みて、-1
0x03を使ってみました。
答え1
わかりました。目的の動作(uartとbash間のコマンド - >応答)を得るために、次のように書いています。
マイクロコントローラ側:
void UART_help_cmd_handler()
{
// this delay prevents buffer overflow on linux side if bash is too slow
// see "However" section below
__delay_ms(100);
printf("Available commands:\n");
printf("search - starts search and returns device addresses\n");
printf("help - prints this help\n");
// second newline to mark end of transmission
// that cat command can read
printf("\n");
}
**顔を打つ**
#!/bin/bash
# send-command-read-response.sh
# send command
# (in my case microcontroller needs 0x02 byte to find start of command
$ and 0x03 byte for end of command
echo -ne "\x02${1}\x03" > /dev/ttyUSB0;
# read lines one by one until "" (empty line)
file="/dev/ttyUSB0"
terminator=""
while IFS= read line
do
if [ "$line" = "$terminator" ]; then
break
else
echo "$line"
fi
done <"$file"
しかし:
- マイクロコントローラの反応が非常に速い場合 - 場合によっては、bashはハードウェアのuartバッファがいっぱいになる前にそれを消費するのに十分な速い「読み取り」コマンドを実行できないため、ダーティディレイを追加する必要があります。
ハードウェアフロー制御が利用可能な場合は、「高速マイクロコントローラの応答」の問題が解決する可能性がありますが、わかりません。
bashでタイムアウトを処理する方法が見つかりません(マイクロコントローラが何らかの理由で応答しない場合)。
ついに
- @mosvyが私の質問に対するコメントに書いたように、bashはシリアル通信に適したツールではありません。
- ハードウェアフロー制御が可能であれば、bashは双方向シリアル通信を処理できると思います。タイムアウトを設定できますが、
stty
それを実装するには余りにも多くの努力が必要になるようです。 - タイムアウトやその他のエラーを処理する簡単なアプリケーションを作成しました。
Bashスクリプトを受け入れるいくつかの大きなWebアプリケーションでは、bashスクリプトを置き換える必要がありますが、追加のバイナリは「うれしくはありません」。そのため、C/C++ アプリケーションを避けようとしています。