Empfangen Sie Bytes von der UART-Kamera

Ich verwende einen dsPIC33E MUC, um eine UART-Kamera (VGA) mit 115,2 Kbps anzuschließen. Der Zweck besteht darin, ein Bild auf einer SD-Karte zu speichern.

Das Programm, das ich geschrieben habe, funktioniert gut, außer dass es sich in einer Schleife befindet, die prüft, ob der Puffer (512-Byte-Puffer ist für einen Sektor) voll ist oder nicht. Wenn der Puffer voll ist, wird er auf eine SD-Karte geschrieben. Ich frage mich, wie ich diesen Code an ein zeitkritisches Datenerfassungsprojekt anpassen kann. Da es sich um einen UART-Interrupt handelt, bin ich mir nicht sicher, ob die Verwendung eines Flags der beste Weg zum Speichern von Bildern auf einer SD-Karte ist. Hier ist der Code mit dem Schleifenprüfflag, um zu sehen, ob der Puffer voll ist.

unsigned char buff[512];//buffer to store bytes comming from the camera
unsigned int bufferPtr=0;//pointer for the buffer. It will be incremented for each byte
while(1){
    if(bufferPtr==512){Write_Sector(SectorNumber,Buff);}//if the buffer is full, Write a it to SD card
    bufferPtr=0;//reset buffer Pointer so next byte will be save to the beginning of the buffer
}

Routine unterbrechen

void ISR(){
    Uart.FlagBit=0;//clear flag bit first
    buffer[bufferPtr++]=UART_Read();//read a byte and put it into the buffer
}

Wie Sie sehen können, wartet das Programm auf die Ankunft von Bytes und speichert sie in einem Puffer. Es funktioniert sehr gut, aber ich habe eine Frage zum Timing. In Bezug auf die Schreibgeschwindigkeit benötigt es ungefähr 3,6 Sekunden für 2000 Sektoren (jeder Sektor 512 Bytes). Das Schreiben eines Sektors benötigt also 3600/2000 = 1,8 ms. Die Baudrate sagt mir, dass 115200/10=11520Byte/Sec, was 11,52 Bytes/ms bedeutet. Wie ist es möglich, einen Sektor auf die SD-Karte zu schreiben (benötigt 1,8 ms), ohne dass der UART-FIFO-Puffer überläuft? Während dieser 1,8 ms kommen 11,52 * 1,8 = 20,736 Bytes herein.

Antworten (2)

Puffer = Sektor-RAM-Puffer. UART-Puffer = interner UART-Puffer.

"Nur eine Frage der Programmierung" :-)

Ich habe mir die feinen Details Ihrer Methode oder bestimmter Geräteressourcen nicht angesehen - die folgende allgemeine Lösung gilt, solange der verfügbare Arbeitsspeicher nicht entscheidend eingeschränkt ist:

Die Ankunftsrate beträgt etwa 1.000.000/115.200 US/Bit = 8,68 US/Bit oder 87 US/Byte

Die Schreibrate der SD-Karte beträgt 1800 US/512 Bytes ~= 3,5 US/Byte.

Wenn es also keine anderen größeren Overheads gibt, haben Sie langfristig eine Schreibrate, die viel schneller ist als die Ankunftsrate. Das einzige Problem besteht darin, zu versuchen, zu gehen und Kaugummi zu kauen, während der Puffer gespeichert wird.

Wenn Sie SD schreiben und UART gleichzeitig problemlos lesen können, können Sie einen Puffer mit exakter Größe verwenden. Solange Sie das erste Byte innerhalb von 87 uS nach dem Schreiben aus dem Puffer erhalten, wird der UART niemals wissen, dass Sie dort sind.

Wenn der Code an anderer Stelle sehr zeitkritisch ist, können Sie möglicherweise Interrupts ausschalten und ein "Sprich mit mir"-Flag abrufen, wenn Sie Zeit haben. Solange Sie dies tun und reagieren können, bevor der UART-Puffer voll ist, können Sie jedes Mal gewinnen

Eine todesmutige High-Wire-Methode besteht darin, herauszufinden, wann der Puffer gerade voll genug ist, dass der UART das letzte Pufferbyte so liefert, wie es die SD-Karte benötigt, wenn Sie DANN mit der Übertragung beginnen. Viel Glück dabei. Es hat den Vorteil, dass keine zusätzlichen Pufferressourcen erforderlich sind, WENN Sie es "genau richtig" verwalten können.

Eine weitaus einfachere Methode (unter der Annahme eines Wrap-Around-Puffers) besteht darin, die Puffergröße um genügend Bytes plus etwas mehr zu erhöhen, sodass Sie, wenn der Puffer genügend Daten für einen SD-Schreibvorgang enthält, mit dem Schreiben von SD-Daten beginnen, während der UART die "extra „Pufferraum. Wenn der Buffer-Writer den oberen Rand des Puffers erreicht, startet er einfach am unteren Rand des Puffers neu, ohne zu wissen, dass Sie 512-Byte-Blöcke stehlen, wenn sie bereit sind. Dies erfordert, dass Sie die oberen und unteren Zeiger des Pufferlesers neu ausrichten und den "Puffer voll"-Zeiger oder -Zähler usw. verwalten - ist aber ansonsten "trivial einfach" [tm].

Wiederum einfacher ist es, zwei Puffer zu verwenden und den Schreiber auf den anderen umzuschalten, wenn die aktuelle Onbe voll ist. Dies verdoppelt den benötigten Puffer-RAM, was ein Problem sein kann oder auch nicht.

Nun, Code sieht fast ok aus. Aber während Sie den Puffer auf der SD-Karte speichern, werden Sie ein Problem haben, wenn ein neues Byte ankommt. Um auf der sicheren Seite zu sein, können Sie einen Ringpuffer mit einer größeren Größe des benötigten Puffers erstellen und ihn alle xy-Werte leeren.

int head = 0, tail = 0, cnt = 0;
bool overflow = false;
#define BUFFSIZE 1024
char buff [BUFFSIZE];
#define MEMBUFSIZE 512
char memoryBuff[MEMBUFSIZE];

void appendToBuff(char a_byte)
{
   buff[head++] = a_byte;
   if (head >= BUFFSIZE) {
       head = 0;
       }
   if (head == tail) {
       overflow = true;
       flushBuffer();
       }
}
void flushBuffer ()
{
    while (tail != head || overflow){
        overflow = false;
        memoryBuff[cnt++] = buff[tail++];
        if (tail >= BUFFSIZE) tail = 0;
        if (cnt >= MEMBUFSIZE) {
             Write_Sector(SectorNumber,Buff);
             cnt = 0;
             }
        }
}
void main() 
{
    while (1) {
       flushBuffer();
       }
}

Ich habe diesen Code nicht ausprobiert, also könnte er den ein oder anderen Fehler haben, aber er wird Ihnen helfen, einen Überblick darüber zu erhalten, was Sie handhaben sollten ...