Bit Banging UART

Mein vollständiger Code befindet sich hier .

Grundsätzlich übertrage ich an ein Arduino und erhalte nicht den richtigen Wert (Sie werden feststellen, dass ich versuche, d'22' zu senden). Hier ist die Methode, bei der ich die Übertragung tatsächlich gebissen habe:

// Method for transmitting value using serial bit banging
void uart_tx_bit_bang(unsigned char val) {
    unsigned char i;
    Tx_Pin = 0;                         // Start bit
    uart_time_delay();
    for ( i = 8 ; i != 0 ; --i ) {
        if (val & 0x01) Tx_Pin = 1;   // Begin with LSB
        else            Tx_Pin = 0;
        val >>= 1;
        uart_time_delay();
        }
    Tx_Pin = 1;                         // Stop bit
    uart_time_delay();
}

Da die Verzögerung 1/Baud betragen sollte, uart_time_delay()sollte eine Verzögerung von 104 us vorliegen. Ich verwende __delay_us(104)aus den PIC-Bibliotheken. Jede Hilfe hierzu wird sehr geschätzt.

Ich bin mir sicher, dass ich an beiden Enden die richtige Baudrate verwende.

UARTs senden tatsächlich zuerst das LSB.
Dieser Code sendet LSB-first
Welchen Wert erhalten Sie? Das zu wissen, würde bei der Fehlersuche helfen.
Ich habe mehrere verschiedene Werte erhalten, nicht nur einen konsistenten Wert.
@markrages, ja du hast recht, die umgekehrte Schleifenreihenfolge und der Kommentar durch mich
Ich entschuldige mich für den Kommentar. Ich habe dies von einem anderen Bit-Banging-Verfahren übernommen und vergessen, den Kommentar zu ändern.
Hat Serial nicht invertierte Pegel? Aus dem Wiki: "Für Datenübertragungsleitungen (TxD, RxD und ihre Sekundärkanaläquivalente) ist die logische Eins als negative Spannung definiert" Dies würde jedoch nicht die Tatsache erklären, dass sich die empfangenen Daten ändern. Ich denke, das Stoppbit ist auch niedrig, wenn ich mir die Wiki-Serienspuren ansehe.
Außerdem beträgt die Verzögerung nicht genau 1/Baud, es sei denn, das Schreiben an den Port dauert nicht lange. Wenn Sie jedoch 300 Baud verwenden, ist die Befehlsausführungsgeschwindigkeit irrelevant. Mit welcher Taktrate läuft dein PIC?
Ich verwende einen internen 4-MHz-Oszillator. Und 9600Baud
Und Sie stellen eine Verbindung zu den seriellen TX / RX-Pins der Arduino-Hardware her?
Alles, was ich tue, ist die Übertragung von meinem PIC zum Arduino. Also habe ich mein Tx_Pinauf dem PIC mit Rx auf dem Arduino verbunden.
@angelatlarge nur RS-232-Pegel werden invertiert. Am Mikrocontroller sind die Pegel normale CMOS.
@markrages Ja, TTL-Pegel sind nicht invertiert (ich wollte das bearbeiten, nachdem ich noch etwas mehr gelesen hatte, aber das Zeitlimit ist abgelaufen. Deshalb habe ich nach dem Arduino gefragt: ob es etwas zwischen dem Arduino und dem PIC gibt (A max chip ? Zwei maximale Chips? unwahrscheinlich, zugegeben), dann könnten die Levels falsch sein.

Antworten (1)

Während Ihre Berechnung von 104 uS für 9600 BPS korrekt ist, wird Ihre Schleife und die verschiedenen Operationen, die sie ausführt, eine zusätzliche Verzögerung hinzufügen. Es gibt ein paar Möglichkeiten, wie Sie das Timing optimieren können:

  • Subtrahieren Sie eine Konstante von Ihrer US-Verzögerung, bis sie zu arbeiten beginnt. Es ist wahrscheinlich am besten, die minimale / maximale Anzahl zu bestimmen, mit der es funktioniert, und den mittleren Wert auszuwählen.

  • Machen Sie etwas Ähnliches mit einem Oszilloskop, um das endgültige Timing zu überprüfen, falls Sie eines zur Verfügung haben.

  • Sehen Sie sich die Assembler-Ausgabe des Compilers an und bestimmen Sie, wie viele Zyklen die Schleife benötigt.

Ich sehe auch, dass Sie die RC-Uhr verwenden. Normalerweise halte ich mein serielles Timing für einen zuverlässigen Betrieb gerne innerhalb von 2%, also überprüfen Sie auch, ob das Teil so viel Stabilität hat, wenn Sie die RC-Uhr für einen zuverlässigen Betrieb verwenden.

Danke! Ich werde einige dieser Vorschläge morgen früh ausprobieren und mich bei Ihnen melden.
Ich würde PeterJ zustimmen. Normalerweise muss ich eine externe Uhr (Quarz oder Resonator) verwenden, um eine genaue Datenübertragung zu erhalten. Außerdem fügt das bisschen Drehen innerhalb der Schleife Ihrer Verzögerung etwas Zeit hinzu.
Also ich glaube, ich habe es herausgefunden. Ich glaube nicht, dass sich meine uart_time_delay()Routine überhaupt verzögert. Ich verwende die eingebaute __delay_us()Methode. Irgendwelche Gedanken dazu? Wie kann ich eine zuverlässigere Verzögerung in C erreichen? Ich brauche 1/Baud
@WillemEllis, ich habe gerade bemerkt, dass Sie _XTAL_FREQ als 4,0 definiert haben - ich denke, es sollte in Hertz sein, also 4000000, das könnte etwas Seltsames tun.
Das war es!!! Ich bin gerade so glücklich! Ich habe die _XTAL_FREQ auf 4000000 geändert und die Baudrate auf 4800 gesenkt, und es funktioniert! Danke @PeterJ
@PeterJ, ich bin mir nicht sicher, ob es dich interessiert, aber als Belohnung hast du mir geholfen, Folgendes zu erreichen! youtube.com/watch?v=BvSl8_K2UX4