組み込み C を使用して、GPRS 端末用のアプリケーションを作成しようとしています。私の主な問題は、AT コマンドの操作です。シリアル回線を使って AT コマンドを送りますが、ネットワーク指向のコマンドだと応答に時間がかかることがあり、プロセッサが何もせずに待機する時間が長くなります。アイデアは、別のスレッドのように、これを同じ方法で並列に待機させることです。私のシステムはスレッドをサポートしていないため、その方法を知っている人はいますか? 5ミリ秒ごとに呼び出される割り込みがあるため、いくつかのタイマーを使用することを考えていましたが、応答を待機する必要がある秒数がわかりません。割り込みで文字列を比較して、すべてのメッセージが受信されたかどうかを確認すると、非常に非効率的ですよね?
3 に答える
各 mainLoopCycle で packetHandler を呼び出すだけです。
このハンドラーは、シリアル ポートから新しい文字が利用可能かどうかを確認します。
メッセージが完全な場合 (CR LF が検出された場合)、packetHandler は応答メッセージをビットごとに作成し、messageReceive 関数を呼び出します。それ以外の場合は、単に mainLoop に戻ります。
int main()
{
init();
for (;;)
{
packetHandler();
}
}
char msgBuffer[80];
int pos=0;
void packetHandler()
{
char ch;
while ( isCharAvailable() )
{
ch=getChar();
msgBuffer[pos++] = ch;
if ( ch == '\n' )
{
messageReceived(msgBuffer);
pos=0;
}
}
}
割り込みを使用するか、データが利用可能になったときに割り込みを行うようにシリアル インターフェイスを構成するか、FreeRTOSなどの RTOS を使用して 2 つのスレッドを実行し、1 つはメイン コード用、もう 1 つはブロックしてシリアル データを待機することができます。
更新: あなたのコメントに基づいて、データのサイズがわからないと言いますが、データを終了するバイトの割り込みハンドラー チェックで問題ありません。これは単純で一般的な例です。 MCU:
void on_serial_char()
{
//disable interrupts
disable_interrupts();
//read byte
byte = serial.read();
//check if it's the terminating byte
if (byte == END) {
//set the flag here
MESSAGE_COMPLETE = 1;
}
//add byte to buffer
buf[length++] = byte;
//enable interrupts
enable_interrupts();
}
メインループでそのフラグを確認します。
...
if (MESSAGE_COMPLETE) {
//process data
...
//you may want to clear the flag here
MESSAGE_COMPLETE = 0;
//send next command
...
}
ハードウェアドライバーにかなり近いようです。その場合、最適な方法は DMA を使用することです。MCU がサポートしている場合は、DMA ハードウェアからのフラグを使用して、受信したデータの解析をいつ開始するかを決定します。
2 番目に最適なオプションは、rx 割り込みを使用し、受信したすべてのバイトを循環バッファーなどの単純な FIFO に格納し、それらを受信したらフラグを設定することです。着信データ用に 1 つのバッファーと、受信した最新の有効なデータ用に 1 つのバッファーが必要になる場合があります。