Integerwerte über serielle Kommunikation in PIC zu PIC senden?

Ich muss ganzzahlige Werte von einem PIC zu einem anderen über die serielle Schnittstelle übergeben

für char kann ich den folgenden Code verwenden

char data1='a';
TXREG=data1;                                     
while(PIR1.TXIF==0); 

aber wenn ich versuche, eine Variable vom Typ int zu übergeben, gibt sie ein ASCII-Äquivalent zurück.

Gibt es trotzdem die Daten als Integer statt als Char-Typ zu erhalten?

Was meinst du mit "Variable vom Typ int übergeben"? Versuchen Sie, einen Wert größer als 8 Bit über das UART-Peripheriegerät zu senden? Wenn ja, zeigen Sie Ihren Code.
Nein. Ich muss int-Werte von 0 bis 64 senden. Das fällt nur unter 8-Bit. Der Code ist oben gezeigt. Ich habe versucht, die Variable vom Typ int dort zu übergeben, wie ich in den Fragen angegeben habe.
Wie bestätigen Sie, dass das ASCII-Äquivalent des Werts beim empfangenden PIC ankommt?
Durch Übertragen der empfangenen Daten sehen Sie dann die Ausgabe von meinem PC über die serielle Schnittstelle
Ah, Sie zeigen die Daten auf einem Terminal-Emulator an. Das ist eine wichtige Information, die Sie bei Ihrer Frage ausgelassen haben. Also, zur Verdeutlichung, wenn Sie den numerischen Wert 55 (zum Beispiel) senden, sehen Sie eine „7“ auf Ihrem Computerbildschirm?
Ja! Aber das ist nicht genau das Problem. Ich möchte, dass die Daten am empfangenden Ende in dieselben int-Typ-Daten decodiert werden, die zum Zeitpunkt der Übertragung vorhanden waren.
Ok, wenn Sie also die Nummer 55 senden, wenn Sie "55" auf Ihrem Computerbildschirm sehen möchten? Oder geht es Ihnen nur um die zwischen den beiden PICs übertragene Nummer?
@DanLaks nein, ich mache mir nur Sorgen um die Zahl, die zwischen zwei Bildern übertragen wird ... ich habe den Computerbildschirm nur verwendet, um zu sehen, welche Daten übertragen werden ...

Antworten (3)

Sie senden bereits ganzzahlige Werte über den UART mit dem angezeigten Code. Ihr Problem besteht anscheinend darin, Ganzzahlen zu senden, die mehr als 8 Bit breit sind.

Der UART sendet von Natur aus nur 8-Bit-Bytes (in der gängigsten Konfiguration) gleichzeitig. Wenn Sie eine breitere Ganzzahl senden möchten, müssen Sie mehr als ein Byte senden, um diese Ganzzahl darzustellen. Beispielsweise könnten Sie entscheiden, dass alle Multibyte-Ganzzahlen in der Reihenfolge der kleinsten bis höchstwertigen Bytes gesendet werden sollen. Wenn Sie eine 16-Bit-Ganzzahl senden müssen, senden Sie zuerst die niedrigen 8 Bits und dann die hohen 8 Bits. Der empfangende PIC macht das Umgekehrte. Es empfängt zuerst die niedrigen 8 Bits, dann die hohen 8 Bits und schreibt diese nacheinander in den Speicher, sodass der Rest des Systems auf den Wert als 16-Bit-Ganzzahl zugreifen kann.

24-Bit-Ganzzahlen werden zum Beispiel auf die gleiche Weise gesendet, außer dass 3 Bytes statt 2 benötigt werden. 32-Bit-Ganzzahlen erfordern das Senden von 4 Bytes.

Beachten Sie, dass nichts davon etwas mit dem Senden von numerischen Werten zu tun hat, die auf einem Terminalemulator angezeigt werden sollen. Terminals zeigen Zeichen an. Jedes mögliche Zeichen hat einen vordefinierten Binärcode. Sie senden das Byte, das den Code für ein Zeichen enthält, und dieses Zeichen wird auf dem Terminal angezeigt. Der Code für den Buchstaben „A“ ist beispielsweise 65. Wenn Sie das Byte 65 senden, zeigt ein Terminal „A“ an. Ebenso bewirkt das Senden von 48, dass das Terminal "0" anzeigt. Suchen Sie nach etwas namens ASCII-Code. Das sagt Ihnen, was die Byte-Werte für jedes der Zeichen sind, die das Terminal anzeigen kann.

Hier ist ein Beispiel, um all dies zu veranschaulichen. Angenommen, Sie wollten den 16-Bit-Ganzzahlwert 9525 senden. Konvertieren wir das in HEX, damit wir die einzelnen Bytes leicht sehen können: 2535h. Sie haben sich zuvor entschieden, Multi-Byte-Werte in der Reihenfolge Low-to-High-Byte zu senden. Die zwei Bytes, die Sie senden, sind daher 35h und 25h in dieser Reihenfolge. Diese haben die Dezimalwerte 53 und 37. Sie senden diese Bytes, und der andere PIC empfängt 53 und 37. Beachten Sie, dass (37 * 256) + 53 = 9525 ist, was der Wert ist, den Sie senden.

Wenn diese Bytes von einem Terminal abgefangen würden, würden Sie alle Zeichen erhalten, die 53 und 37 zugeordnet sind, was zufällig "5" und "%" sind. Das Terminal zeigt also "5%" an, wenn Sie 9525 senden. Wenn Sie möchten, dass das Terminal "9525" anzeigt, müssen Sie die Bytewerte für die Zeichen "9", "5", "2" und " 5". Das sind zufällig 57, 53, 50 und 53. Das ist viel komplizierter, da der PIC die Dezimalziffern der binären Ganzzahl herausfinden, sie in die Zeichencodes für diese Ziffern umwandeln und diese dann senden muss.

Im Allgemeinen ist es viel einfacher, jede Art von Benutzeroberflächenkonvertierung auf dem PC durchzuführen und den PIC native Binärdateien senden und empfangen zu lassen. Das Konvertieren der binären Ganzzahl 9525 in die Zeichen "9525" ist für den PC trivial, kann jedoch auf einem kleinen PIC einen erheblichen Coderaum und Zyklen erfordern.

Olin, wow, du gibst dir wirklich Mühe in diese Erklärungen. Wie auch immer, wenn ich mich mit einem Kanal befassen muss, der einige Geräte hat, die Daten übersetzen, wie Modems oder RS-zu-Ethernet-Konverter usw., sende ich oft ein Byte b mit zwei Zeichen als 'A'+(b>> 4) und 'a'+(b&0xf). 0 ist also "Aa", 1 ist "Ab", 16 ist "Ba" usw. Es ist einfach zu übersetzen und das Großbuchstaben- vs. Kleinbuchstaben-Bit (Bit 5) dient als rudimentäres Synchronisierungsbit, damit die Kommunikation unterbrochen wird, sind zumindest die Bytes korrekt ausgerichtet. Ich erwarte keinen Applaus, aber bei mir hat es funktioniert...
@PkP Das ist eigentlich eine wirklich schlaue Art, es zu tun. Sie haben im Grunde Ihr eigenes Bit-Level-Paket mit einer erkennbaren Startsequenz erstellt. Sie könnten mehr Daten einfügen, indem Sie sie als zwei 7-Bit-Werte codieren, wobei das 8. Bit des ersten Bytes das "Start"-Bit ist.
@Olin danke, das ist eine wirklich nette Erklärung ... übrigens muss ich nur 8-Bit-Ganzzahlwerte senden ... kannst du mir Sende- / Empfangscodes zeigen, weil ich anscheinend nirgendwo zu finden bin!
@SurajBhawal Ich habe meine Antwort aktualisiert, um mit 8-Bit-Werten statt mit 16 umzugehen.
@Suraj: 8-Bit-Werte passen in einzelne Bytes, also senden Sie sie einfach.
@Olin Ich habe kein Problem damit, die Nummer zu senden ... das Problem ist, dass ich die Daten auf dem anderen Bild nicht empfangen kann.

Wenn Sie einen einzelnen 8-Bit-Wert von einem UART an einen anderen Computer senden, handelt es sich nur um einen Binärwert. Nehmen wir an, Sie hätten eine Zahl wie 52.

char data = 52;        // or char data = 0x34;

und die Daten über den UART gesendet;

TXREG = data;
while(PIR1.TXIF==0);

Wenn Sie ein Terminalprogramm wie RealTerm angeschlossen haben, richten Sie es so ein, dass es Ihre Daten empfängt, und stellen Sie die Anzeige als auf Hex[Leerzeichen] ein, es zeigt den Wert hexadezimal wie folgt an:

34

da hex 34 (3*16 + 4) dasselbe wie 52 ist. Wenn Sie die Anzeige auf ASCII ändern, würde sie stattdessen nur eine 4 anzeigen, da der ASCII-Code für 4 0x34 ist, was eine falsche Darstellung für den Wert ist, der war gesendet.

Als nächstes können Sie den 8-Bit-Wert in Hex senden, jeweils ein 4-Bit-Nibble:

char data = 52;    // or char data = 0x34;

TXREG = (data & 0xf0) >> 4;
while(PIR1.TXIF==0);

TXREG = data & 0x0f;
while(PIR1.TXIF==0);

Dies könnte in eine Schleife gesteckt werden, aber auf diese Weise ist es einfacher zu sehen.

Um die Zeichen anzuzeigen, müssen Sie RealTerm erneut in den Hex[Leerzeichen]-Modus versetzen. Die Nibbles werden dann auf dem Bildschirm als 03 04 angezeigt. Da dies keine richtigen ASCII-Ziffern sind, werden sie unter der ASCII-Anzeigeeinstellung nicht richtig angezeigt.

Wenn Sie tatsächliche ASCII-Zeichen sehen möchten, müssen Sie jedem Wert ein Zeichen „0“ (0x30) hinzufügen, wie folgt:

char nibble;
nibble = ((data & 0xf0) >> 4) + '0';

Dies funktioniert jedoch nur für die Werte 0-9; Hex-Werte AF werden nicht korrekt angezeigt, da 9 und A im ASCII-Alphabet nicht nebeneinander stehen. Sie müssen also eine if-Anweisung hinzufügen, um dies zu handhaben:

char data = 52;    // or char data = 0x34;
char nibble;

nibble = ((data & 0xf0) >> 4) + '0';
if (nibble > '9') nibble += 'A' - '9';
TXREG = nibble;
while(PIR1.TXIF==0);

nibble = (data & 0x0f) + '0';
if (nibble > '9') nibble += 'A' - '9';
TXREG = nibble;
while(PIR1.TXIF==0);

Jetzt werden die Ziffern auf dem ASCII-Display als 34 angezeigt.

Es gibt noch eine weitere Möglichkeit, dies zu tun, nämlich den Wert als Dezimalzeichen zu senden. Das erfordert eine Umwandlung von der Binärzahl 52 (oder 0x34) in eine äquivalente Zeichenfolgendarstellung der Dezimalzahl, in diesem Fall „52“. In C gibt es mehrere Möglichkeiten, dies zu tun, eine davon ist itoa (Ganzzahl in ASCII) und die andere ist sprintf. Beide benötigen ein wenig Bibliothekscode, was je nach Flash-Größe Ihres Mikrocontrollers ein Problem sein kann oder auch nicht.

Hier ist, wie man es mit sprintf macht:

char buf[5];    
char data = 52;       // or char data = 0x34;
unsigned char i;

sprintf(buf,"%d",data);

i = 0;
while (buf[i]!='\0')
{
    TXREG = buf[i++];
    while(PIR1.TXIF==0);
}

printf wandelt den Wert in data in dezimal um (wegen %d) und speichert ihn als ASCII-Zeichen im Zeichen-Array buf. Die maximale Größe der Zahl beträgt vier Zeichen, da eine vorzeichenbehaftete 8-Bit-Zahl von -127 bis 128 gehen kann. C-Strings werden mit '\0' (Null) abgeschlossen, sodass das Array fünf Elemente haben muss. Die While-Schleife sendet dann Zeichen aus, bis das Nullzeichen erreicht ist.

Um einen ganzzahligen Wert über den UART zu senden, müssen Sie 2 Bytes senden. Zum Beispiel:

int data = 0x1234;
TXREG = data & 0xff;
while(PIR1.TXIF==0); 
TXREG = (data >> 8) & 0xff;
while(PIR1.TXIF==0);
Ich dachte, das OP war anfangs auch verwirrt, aber aufgrund der Diskussion in den Kommentaren scheint dies nicht der Fall zu sein. Er/Sie zeigt die Werte auf einem Terminal-Emulator an, der die übertragenen Werte in ASCII-Symbole umwandelt.