Wie kann die Interrupt-gesteuerte UART-Übertragung PIC24H gedrosselt werden?

8

Ich übertrage Daten von meinem PIC24H Mikrocontroller über 460Kbaud UART zu einem Bluetooth Funkmodul. Unter den meisten Bedingungen funktioniert dieser Fluss gut und das Bluetooth-Modul verwendet CTS- und RTS-Leitungen, um die Flusskontrolle zu verwalten, wenn die internen Datenpuffer voll sind. Es gibt jedoch einen Fehler in dem Bluetooth-Modul, der es zurücksetzt, wenn Daten kontinuierlich ohne Unterbrechungen an es gesendet werden, was passiert, wenn meine Daten in einem anderen Engpass gesichert werden.

Es wäre schön, wenn das Modul richtig funktioniert hätte, aber das liegt außerhalb meiner Kontrolle. So scheint es, dass meine einzige Option ist, einige Daten Drosselung an meinem Ende zu tun, um sicherzustellen, dass ich die Grenzen des Datendurchsatzes nicht überschreite (was ich ungefähr durch Experimente weiß).

Meine Frage ist, wie Sie die Drosselung der Datenrate implementieren können.

Meine aktuelle UART-Implementierung ist ein RAM-Ring-FIFO-Puffer mit 1024 Byte Länge, in den die Hauptschleife Daten schreibt. Ein Peripherie-Interrupt wird vom PIC ausgelöst, wenn das letzte Byte von der UART-Hardware gesendet wurde und mein ISR das nächste Byte aus dem Puffer liest und es an die UART-Hardware sendet.

Hier ist eine Idee des Quellcodes:

uart_isr.c

%Vor%

uart_methods.c

%Vor%

Bearbeiten
Es gibt zwei Möglichkeiten, wie die Drosselung implementiert werden könnte, wie ich es sehe:

  1. Erzwingen Sie eine Zeitverzögerung zwischen dem zu schreibenden UART-Byte, das den Datendurchsatz begrenzt.

  2. Halten Sie eine laufende Anzahl von Bytes, die über einen bestimmten Zeitraum übertragen werden, und wenn die maximale Anzahl von Bytes für diese Zeitspanne überschritten wird, erstellen Sie eine etwas längere Verzögerung, bevor Sie mit der Übertragung fortfahren.

Jede Option würde theoretisch funktionieren, es ist die Implementierung, über die ich mich wundere.

    
CodeFusionMobile 06.07.2011, 21:02
quelle

4 Antworten

2

Vielleicht ist ein Quotenansatz das, was Sie wollen. Verwenden Sie einen periodischen Interrupt der relevanten Zeitskala, fügen Sie eine Quote von "Bytes, die übertragen werden sollen" zu einer globalen Variablen hinzu, bis zu einem Punkt, an dem Sie nicht über eine Ebene gehen, die für die entsprechende Überschwemmung angepasst wurde. Dann überprüfe einfach, ob es eine Quote gibt, bevor du ein Byte senden kannst. Bei einer neuen Übertragung wird es zu einer anfänglichen Überschwemmung kommen, aber später begrenzt die Quote die Übertragungsrate.

%Vor%     
chip_wrangler 12.07.2011, 06:38
quelle
2

Wenn Sie einen freien Timer haben oder wenn Sie einen vorhandenen verwenden können, könnten Sie eine Art "Entprellen" der gesendeten Bytes durchführen.

Stellen Sie sich vor, Sie hätten diese globale Variable, byte_interval , und Sie haben einen Zeitgeber, der alle Mikrosekunden überläuft (und die ISR auslöst). Dann könnte es in etwa so aussehen:

%Vor%

Und dann könnten Sie in der "putchar" -Funktion Folgendes haben:

%Vor%

Es tut mir leid, dass ich nicht viel in Ihren Code geschrieben habe, damit ich genauer darauf eingehen kann. Das ist nur eine Idee, ich weiß nicht, ob es für dich passt.

    
Vinicius Kamakura 06.07.2011 21:13
quelle
1

Erstens gibt es zwei Arten der seriellen Ablaufsteuerung, die häufig verwendet werden.

Sie sagen, CTS ist eingeschaltet, aber Sie möchten vielleicht sehen, ob XON / XOFF auf irgendeine Weise aktiviert werden kann.

Ein anderer Ansatz, wenn Sie es konfigurieren können, ist einfach eine niedrigere Baudrate zu verwenden. Dies hängt natürlich davon ab, was Sie am anderen Ende der Verbindung konfigurieren können, aber es ist normalerweise der einfachste Weg, um Probleme zu beheben, wenn Geräte nicht in der Lage sind, Übertragungen mit höherer Geschwindigkeit zu bewältigen.

    
Roddy 11.07.2011 15:44
quelle
1

Timer-Ansatz, der Tx zu einer bestimmten Zeit eine Verzögerung hinzufügt:

  • Konfigurieren Sie einen freilaufenden Timer mit einer geeigneten periodischen Rate.
  • Schalten Sie im Timer ISR ein Bit in einer globalen Statusvariablen (delayBit)
  • um
  • Wenn in der UART-ISR die VerzögerungBit hoch ist und die VerzögerungPostedBit niedrig ist, dann verlasse die TX-ISR, ohne das TX-Interrupt-Flag zu löschen, und setze ein Bit in einer globalen Statusvariablen (delayPostedBit). Wenn VerzögerungBit niedrig ist, deaktivieren Sie VerzögerungPostedBit. Das Ergebnis ist, dass eine Verzögerung gleich einer ISR-Planwartezeit verursacht wird, da der ISR erneut eingegeben wird. Dies ist keine Verzögerung bei Besetztwartezeit und wirkt sich nicht auf das Timing des restlichen Systems aus.
  • Passen Sie die Zeit des Timers an, um in geeigneten Intervallen Latenz hinzuzufügen.
Jonathan Cline IEEE 14.07.2011 17:48
quelle