3

10 ~ 20 kHz のレートで 16 ビット データ パッケージを転送する SerialPort 接続を確立しようとしています。これを C++/CLI でプログラミングしています。送信者は、文字「s」を受信した後、無限の while ループに入り、常にデータと共に 2 バイトを送信します。

より単純なアプローチは完全に機能しますが、遅すぎるため、送信側の問題はほとんどありません (このアプローチでは、受信者は常に最初に「a」を送信し、次に 2 バイトで構成される 1 つのパッケージを取得します。これは速度につながります。約500Hzの)。この機能するが遅いアプローチの重要な部分は次のとおりです。

public: SerialPort^ port;

in main:
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();

and then doing as often as wanted:
port->Write("a");
int i = port->ReadByte();
int j = port->ReadByte();

これは現在、私が取り組んでいる実際のアプローチです:

static int values[1000000];
static int counter = 0;

void reader(void)
    {
        SerialPort^ port;
        Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
        StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
        port = gcnew SerialPort("COM16",384000,p,8,s);
        port->Open();
        unsigned int i = 0;
        unsigned int j = 0;
        port->Write("s"); //with this command, the sender starts to send constantly
        while(true)
        {
            i = port->ReadByte();
            j = port->ReadByte();
            values[counter] = j + (i*256);
            counter++;
        }
    }

in main:
Thread^ readThread = gcnew Thread(gcnew ThreadStart(reader));
readThread->Start();

カウンターは 18472 パッケージ/秒の速度で急速に増加しますが、値は何らかの形で間違っています。例を次に示します。値は次のようになります。最後の 4 ビットはランダムに変化します (アナログ - デジタル コンバーターの信号)。

111111001100111 

コードで指定されたスレッド化されたソリューションの値を次に示します。

1110011001100111 
1110011000100111 
1110011000100111 
1110011000100111

そのため、接続がパッケージの途中でデータを読み取っているように見えます (正確には、3 ビット遅すぎます)。私に何ができる?後で読み取りコードを編集するときにシフトエラーが悪化するかどうかわからないため、このようにパッケージを読み取っているときにこのエラーがコードの後半で修正されるという解決策は避けたいと思います。

前もって感謝します、

ニコラス

PS: これが役立つ場合は、C で記述された送信側 (AtMega168) のコードを次に示します。

uint8_t activate = 0;

void uart_puti16(uint16_t val) //function that writes the data to serial port
{

    while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
            nop(); // wait 1 cycle
            UDR0 = val >> 8; //write first byte to sending register
    while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
            nop(); // wait 1 cycle
            UDR0 = val & 0xFF; //write second byte to sending register
}

in main:
while(1)
{
        if(active == 1)
        {   
            uart_puti16(read()); //read is the function that gives a 16bit data set
        }               
}

ISR(USART_RX_vect) //interrupt-handler for a recieved byte
{
        if(UDR0 == 'a') //if only 1 single data package is requested
        {
            uart_puti16(read());
        }
        if(UDR0 == 's') //for activating constant sending
        {
            active = 1;
        }
        if(UDR0 == 'e') //for deactivating constant sending
        {
            active = 0;
        }
}
4

2 に答える 2

2

与えられた 384,000 のビット レートでは、1 秒あたり 38,400 バイトのデータ (8 ビットの実データと 2 つのフレーミング ビット)、つまり 1 秒あたり 19,200 の 2 バイト値を取得する必要があります。

両方の例でどのくらいの速さでcounter増加していますか? イベントを使用するか、直接ポーリングするかに関係なく、最新のコンピューターはその速度に追いつくことが期待されます。

機能すると述べられているより単純なアプローチを示していません。それを投稿することをお勧めします。

また、行にブレークポイントを設定します

values[counter] = j + (i*256);

そこに、検査しij. ループの最初の反復でこれらの変数に表示される値を共有します。

于 2012-07-16T23:44:19.627 に答える
0

これは、 http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y228でコードを読んだことに完全に基づく推測です。この警告が邪魔にならないので、ここに私の推測があります:

データが読み取り可能になったときにイベント ハンドラーが呼び出されていますが、使用可能なデータの2 バイトしか消費していません。イベント ハンドラーは、1024 バイトごとにのみ呼び出すことができます。または似たようなもの。プログラムを期待どおりに続行するには、イベント ハンドラーで使用可能なすべてのデータを消費する必要がある場合があります。

ハンドラーを書き直して、使用できるデータがなくなるまで読み取るループを含めてみてください。

于 2012-07-16T23:45:53.387 に答える