0

写真をプログラミングしていて、データを送信しようとしているときにシリアルポートにデータを送信すると、プログラムがロックされると診断しました(テストすると、Pythonコードとハイパーターミナルの両方がクラッシュします)。ハイパーターミナルで動作し、ゆっくりと入力し(ストローク間で> .5秒)、キーボードをバッシングするとクラッシュしました。したがって、0.5秒より長いtime.sleepを導入しましたが、それでも機能していません。

これがテストコードです。

import serial
import time

ser = serial.Serial("COM1")
ser.baudrate=2400

while 1:
    for i in range(23):
        ser.write(0x41)       
        time.sleep(.5)
        print("ok")

    rec = ser.read()
    rec2 = ser.read()
    rec3 = ser.read()
    print(rec)
    print(rec2)
    print(rec3)

    for i in range(23):
        data = ser.read()
        print(data)
        print("ok")
    time.sleep(5)

データ受信機能。以前は、charを受信するたびに「ok」が送信されていました(これにより、3回の反復後にフリーズすることがわかります)。それが問題の原因であるかどうかを確認するためにループの外に持ってきましたが、そうではありませんでした。このコードでは「ok」をまったく送信していません。

unsigned char receiveData(unsigned char *rxData, int length){
  // 1. Flag bit, RCIF, will be set when reception is complete and an interrupt will be generated if enable bit, RCIE, was set.
 char send[3] = "ok";

 int index = 0;

 if(rxData==(void*)0 || rxInitialized==FALSE) return FAILURE;
 while(index<length){
  while(PIR1bits.RCIF==0);       
  rxData[index]= RCREG;
  Delay1KTCYx(5);
  index++;
 }
    configureTransmission();
    sendData(send,3);

  // 2. Read the RCSTA register to get the 9th bit (if enabled) and   determine if any error occurred during reception.
  // 3. Read the 8-bit received data by reading the RCREG register.
  // 4. If any error occurred, clear the error by clearing enable bit   CREN.
 return SUCCESS;
}
4

2 に答える 2

2

(この回答は、特定のレジスタの名前が示唆するPIC16を使用していることを前提としています。)

要するに、バッファ オーバーフローとそのループのバグが組み合わさったように見えますreceiveData。3 文字が連続して送信された後にフリーズするという事実は、マニュアルの p117 で説明されている可能性があります。

2 バイトのデータが受信されて RCREG FIFO に転送され、3 番目のバイトが RSR レジスタへのシフトを開始する可能性があります。

これで魔法の 3 が説明できます。

PIC コードをステップ実行して、次のシナリオを検討してください (ほんの一例)。初めて:

// One character already in RCREG - RCIF set
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF clear
rxData[index]= RCREG;
// While waiting here, two more characters are received - RCIF set
Delay1KTCYx(5);
index++;

2回目:

// RCIF set from before
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF STILL set, ONE character remains in UART FIFO!
rxData[index]= RCREG;
// While waiting here, three more characters are received
// RCIF set, RCREG fills up and the third character is discarded!
Delay1KTCYx(5);
index++;

これで、残りのループは まで RCREG からの読み取りを続けますがindex == length、UART FIFO がいっぱいになったときに一部の文字が破棄されたため、そこに到達することはなく、フリーズしたように見えます!

さらに可能性が高いのは、その関数に到達する前に文字を受信して​​いるため、そこに到達する前に UART FIFO がいっぱいになることです。

これにはいくつかの方法があります。

  1. これを割り込みで行うと、着信文字をバッファーに移動するのが少し速くなります。
  2. からの読み取りにループを使用しますRCREGwhile(RCIF) rxData[index]= RCREG;これにより、UART バッファーから読み取るときにバッファーを空にすることができますが、この関数の外部またはその遅延中のオーバーフローは停止しません。
  3. フラグを確認してください。OERRフラグが設定されている場合は、何か問題が発生したと想定して最初からやり直してください。
  4. 有効なコマンドがいつ開始または停止するかを示す停止文字または開始文字 (行末、句読点など) を用意します。スタート キャラクターが 2 つ出てストップ キャラクターがない場合、またはその他の紛らわしい組み合わせが表示された場合は、状態が悪いと想定して最初からやり直してください。

いくつかの追加のアドバイス: PIC コード内のすべての欠落した文字やこのような問題を考慮して補正しようとすると、完全に狂ってしまう可能性がありますが、最終的には別の通信エラーになります。PIC コードの優先事項は、エラーからの迅速な回復とロックアップの防止です。エラー検出と正常な回復は、はるかに簡単なクライアント コードで処理する必要があります。

于 2010-11-19T00:43:01.403 に答える
1

PIC からの通信は、シリアルポートのRTS/CTS ラインを利用していますか? おそらくPICは何らかのフロー制御を期待しており、フロー制御なしでデータを送信するのが速すぎます。PICの制限を読み、必要に応じてフロー制御を有効にしてポートを開きます。

于 2010-11-18T23:43:52.320 に答える