Forum: Mikrocontroller und Digitale Elektronik Was genau liest der Pic an RS232?


von Kai J. (Gast)


Lesenswert?

Guten Tag,

habe zwar einige Beiträge gefunden die in die Richtung gingen, aber 
nichts was mir weitergeholfen hätte.

Folgendes:

PIC wird über die rs-232 vom PC angesteuert, dazwischen sitzt ein max232 
für die pegelwandlung. der aufbau ansich ist soweit richtig und 
funktioniert auch mit anderen (test)programmen.

nun war geplant das eingangssignal am pic einzulesen, es zu verarbeiten 
und darauf hin eine ausgabe mit einer 7-segment platine zu realisieren.

die eigentliche frage ist: was genau schreibt der pic in eine variable 
(c-programmierung) wenn die eingabe über das terminal zB eine "2" war?

schreibt er da den ascii code rein als wert? oder was genau? da ich 
bislang feststellen konnte das die im terminal eingegebene 2 keine 2 in 
der variable ergibt und mein wissen anscheint auch noch nicht soweit 
ausreicht das ich da andere beurteilungen abgeben kann, frag ich hier. 
:)



hier noch ein kleiner auszug aus dem quellcode:

{
while(!PIR1bits.RCIF);
ein = RCREG; //wenn 2 im terminal eingegeben wird soll es in ein 
geschrieben werden

LATB = ausgabeB[ein]; //hier wird nun allerdings nicht die wertigkeit 
von 2
LATA = ausgabeA[ein]; //für ein angenommen, was steht da jetzt drin?
   }


ich wäre dankbar wenn mir jemand sagen könnte was nun in meiner 
variablen drin steht. :)

ich brauch auch nur die zahlen von 0-9.

MfG
Kai

von Karl H. (kbuchegg)


Lesenswert?

Kai J. schrieb:


> schreibt er da den ascii code rein als wert?

ganz genau.

> bislang feststellen konnte das die im terminal eingegebene 2 keine 2 in
> der variable ergibt

was würdest du erwarten, wenn du anstelle der Taste '2' die Taste 'U' 
drückst? 'U' ist ja in dem Sinne auch keine Zahl, wie die Taste '2' auch 
keine 2 'in deiner Variablen generiert'

von Kai J. (Gast)


Lesenswert?

Es geht mir momentan nur um die Zahlen von 0-9.

Ich habe jetzt anhand einer ascii tabelle die werte verwendet, 
allerdings ist das ergebniss das selbe

wenn ich eine 2 eingebe müsste in der variable doch eine 32 stehen oder 
seh ich das nun völlig verkehrt?

von XXXXX (Gast)


Lesenswert?

Hallo

Zeig doch mal ein bischel mehr.
Stimmt die Baudrate?

MfG
XXXXX

von Stefan P. (form)


Lesenswert?

"2" = dezimal 50 und hexadezimal 32

So würde eine Zwei in der Variable stehen wenn du "2" drückst:
ein = RCREG - 48;

von Karl H. (kbuchegg)


Lesenswert?

Stefan P. schrieb:
> "2" = dezimal 50 und hexadezimal 32
>
> So würde eine Zwei in der Variable stehen wenn du "2" drückst:
> ein = RCREG - 48;

man kanns aber auch so schreiben
1
   ein = RCREG - '0';

dann braucht man noch nicht einmal den ASCII Code selber kennen. Es 
reicht wenn ihn der Compiler weiß.

von Jens (Gast)


Lesenswert?

Kai J. schrieb:
> wenn ich eine 2 eingebe müsste in der variable doch eine 32 stehen oder

Die 32 ist aber Hex, die üblichen Variablen sind aber Dezimalzahlen. 
Somit wird aus der 32H eine 50 in dezimaler Schreibweise.

von Karl H. (kbuchegg)


Lesenswert?

Kai J. schrieb:

> wenn ich eine 2 eingebe müsste in der variable doch eine 32 stehen oder
> seh ich das nun völlig verkehrt?

'Müsste' sind ganz schlechte Voraussetzungen für Fehlersuche.
Entweder es tuts oder es tuts nicht. Aber nicht 'müsste'. Und wenn man 
es nicht weiß, dann muss man das kontrollieren.

Du musst aus dem Stadium raus, indem die Dinge rätst! Du musst Fakten 
schaffen. Und wenn das bedeutet, du musst dir einen Mechanismus 
schaffen, wie du dir den Inhalt von Variablen ansehen kannst, dann 
bedeutet es das eben.

von Kai J. (Gast)


Lesenswert?

ok hier mal mein der text mit dem ich bis rumexperimentiert habe.
die arrays sind für die ausgangschaltung um die segmente der 
7-segment-anzeige anzusteuern

#include <pic18fregs.h>

#include "18f1320_config.h"
#include <delay.h>   //für Zeitroutinen
#include <stdlib.h>

#pragma stack 0x80 0x32

unsigned int ausgabeB[]={64,121,36,48,25,18,2,120,0,16};
unsigned int ausgabeA[]={231,239,231,239,239,255,247,239,231,231};
unsigned char ein ,ein1;

//*********** Hauptprogramm ***************************
void main()
 {
  //*********** Variable festlegen **********************
  ein1 = 0;
  ein = 0;
  TRISB = 16;  //RB4 als Eingang, alle anderen Leitungen auf Ausgang
  TRISA = 0;    // PORTA alles auf Ausgang
  RCSTAbits.SPEN = 1;
  ADCON1bits.PCFG5 = 1;
  ADCON1bits.PCFG6 = 1;
  PIE1bits.TXIE = 0;
  PIE1bits.RCIE = 0;
  TXSTAbits.TX9 = 0;
  TXSTAbits.SYNC = 0;
  TXSTAbits.TXEN = 1;
  TXSTAbits.BRGH = 1;
  TXSTAbits.TRMT = 1;
  SPBRG = 25;
  RCSTAbits.RX9 = 0;
  RCSTAbits.CREN = 1;
  //***********************************
  while(1)          // Dauerschleife
   {
    while(!PIR1bits.RCIF);
    ein = RCREG;

    switch(ein)
     {
      case '49': ein1= 1;
                break;
/*
      case '31': ein1= 1;
                break;
      case '32': ein1= 2;
                break;
      case '33': ein1= 3;
                break;
      case '34': ein1= 4;
                break;
      case '35': ein1= 5;
                break;
      case '36': ein1= 6;
                break;
      case '37': ein1= 7;
                break;
      case '38': ein1= 8;
                break;
      case '39': ein1= 9;
                break;
*/
     }
    //delay1mtcy(1);
    //if (ein == 31) ein1 = 1;
    //ein1 = atoi(&ein);
    delay1mtcy(1);
    LATB = ausgabeB[ein1];
    LATA = ausgabeA[ein1];
   }
 }

von Karl H. (kbuchegg)


Lesenswert?

Kai J. schrieb:

>     switch(ein)
>      {
>       case '49': ein1= 1;
>                 break;


Nope.
Entweder du verwendest den ASCII Code, dann schreibst du

        case 49:  ein1 = 1;
oder wenn dir hex lieber ist
        case 0x31: ein1 = 1;

oder du lässt den Compiler den ASCII Code raussuchen

        case '1':  ein1 = 1;


aber nicht einen Mischmasch aus beidem


Die letzte Variante

     case '1':

ist die zu Bevorzugende. Es gibt keinen Grund an dieser Stelle, das du 
den Leser deines Programms in die Verlegenheit treiben musst, dass er 
erst mal in einer ASCII Tabelle deine Codes nachschlagen muss, nur um zu 
verstehen, was da passieren soll.

Von der UART kriegstr du ein Zeichen. Behandle es auch als Zeichen! Das 
Zeichen könnte 'a' oder 'A' oder 'X' oder '&' der '@' sein, je nachdem 
was der Benutzer auf der Tastatur drückt. Bei dir ist es eben '1'  weil 
du deinen Benutzer dazu anhältst, nur die Zifferntasten zu benutzen. 
Nichts desto trotz ist auch '1' oder '5' einfach nur ein Zeichen, 
genauso wie 'g' oder '?' auch nur ein Zeichen ist. Lass dich nicht davon 
täuschen, dass du mit der Taste '1' etwas spezielles verbindest. Das ist 
nur 'zufällig', dass da auf der Tastenkappe ein Symbol aufgemalt ist, 
dass wie eine Eins aussieht. Für den Rechner unterscheidet sich diese 
Taste (und der zugehörige auszusendende Code) in nichts von dem der 
anderen Tasten.

von Kai J. (Gast)


Lesenswert?

Entschuldige die Verwirrung, hatte die Varianten durchprobiert und immer 
wieder auskommentiert, hatte aber jedes mal einheitliche Wete genommen.

Die Vorgeschlagene Variante case '1' zu verwenden war die ursprüngliche 
Idee, allerdings funktioniert das so nicht, bei der Auslesung von "aus" 
gibt es den Inhalt 1 ja nicht, im Terminal (ich verwende unter linux 
gtkterm) gebe ich die 1 ein, sie wird gesendet, wird so aber nicht in 
ein geschrieben.

  while(1)          // Dauerschleife
   {
    while(!PIR1bits.RCIF);
    ein = RCREG;

    switch(ein)
     {
      case '0': ein1= 0;

      case '1': ein1= 1;

      case '2': ein1= 2;

      case '3': ein1= 3;

      case '4': ein1= 4;

      case '5': ein1= 5;

      case '6': ein1= 6;

      case '7': ein1= 7;

      case '8': ein1= 8;

      case '9': ein1= 9;
                break;
     }
    delay1mtcy(1);
    LATB = ausgabeB[ein1];
    LATA = ausgabeA[ein1];
   }

beim start wird mir die 0 angezeigt, allerdings reagiert nichts auf die 
Eingabe im Terminal.


und warum das so ist konnte mir keiner sagen...

von Karl H. (kbuchegg)


Lesenswert?

Kai J. schrieb:

> und warum das so ist konnte mir keiner sagen...

Dann solltest du als allererstes einmal kontrollieren, was dein µC 
eigentlich über die UART empfängt.

Wenn zb deine Baudrate falsch ist, oder es sonst irgendein Problem gibt, 
dann spuckt die UART auf µC Seite alles mögliche aus, nur nicht '1' wenn 
du im Terminal die Taste '1' drückst.

Also: 8 LED an einen Port klemmen und einfach mal das Byte von der UART 
direkt dort ausgeben. Das Bitmuster entziffern und mittels ASCII Tabelle 
identifizieren, ob du den ASCII Code des Zeichens kriegst, dessen Taste 
du drückst (höchst wahrscheinlich kriegst du den nämlich gar nicht)

Wie ich weiter oben schon sagte:
Nicht 'könnte' 'müsste' 'wollte' sondern Fakten schaffen.
Deine UART spuckt ein Byte aus .... welches?

Da du das nicht weißt, musst du dir einen Mechanismus ausdenken, mit dem 
du das feststellen kannst.

Alles andere ist Stochern im Nebel und funktioniert in der 
Softwareentwicklung nicht.

von Kai J. (Gast)


Lesenswert?

Dann bedanke ich mich soweit erstmal und werde schauen wie ich das 
realisiert bekomme, also zu kontrollieren was nun wirklich übertragen 
wird.

Es ist wahrscheinlich zu merken das mein Horizont in diesem Gebiet noch 
nicht wirklich gross ist. Daher auch die Unsicherheiten in meinen 
Beiträgen.

von g457 (Gast)


Lesenswert?

Deinem switch fehlen noch zwei Sachen: Erstens eine default-Klausel, die 
z.B. einen Fehlercode anzeigt (hint: abhängig vom Terminal-Programm wird 
an die Eingabe noch ein '\r', "\r\n" oder '\n' angehängt, das musst Du 
abfangen!). Zweitens musst du die einzelnen cases mit je einem break; 
abschließen, sonst läuft dir der IP bis ins letzte case hinein (hier: am 
Ende kommt ein1 == 9 bei raus).

HTH

von Kai J. (Gast)


Lesenswert?

Ich habe jetzt mal folgendes Programm in den Pic geladen und die Rx/Tx 
Pins gebrückt:

char ein;
//*********** Hauptprogramm ***************************

void main()

 {
  //*********** Variable festlegen **********************


  RCSTAbits.SPEN = 1;
  ADCON1bits.PCFG5 = 1;
  ADCON1bits.PCFG6 = 1;
  PIE1bits.TXIE = 0;
  PIE1bits.RCIE = 0;

  TRISB = 16;
  TRISA = 0;
  TXSTAbits.TX9 = 0;
  TXSTAbits.SYNC = 0;
  TXSTAbits.TXEN = 1;
  TXSTAbits.BRGH = 1;
  TXSTAbits.TRMT = 1;
  SPBRG = 25;
  RCSTAbits.RX9 = 0;
  RCSTAbits.CREN = 1;
  //***********************************

  while(1)          // Dauerschleife
   {
    while(!PIR1bits.RCIF);
    ein = RCREG;
    delay1mtcy(1);
    while(!PIR1bits.TXIF);

    TXREG=ein;
    delay1mtcy(1);

   }

 }


Das was ich über gtkterm eingebe, bekomme ich nun zurück. Sprich 
Senden/Empfangen funktioniert.
Zurück zum anfänglichen besteht weiterhin das Problem das ich die 
Eingabe die ich am Terminal tätige nicht verarbeiten kann, ausser sie 
direkt zurück zusenden. Sobald ich nun aber die Arrays auswerten möchte 
bzw die Ausgänge des Pics schalten will, hat die variable keinen 
verwertbaren Inhalt, obwohl mir durch das Programm oben ja bewiesen 
wurde das es einer ist.

Hier der letzte Stand vom Quelltext:


int ausgabe1[] = {64,121,36,48,25,18,2,120,0,16};
int ausgabe2[] = {231,239,231,239,239,255,247,239,231,231};
int ein;
//*********** Hauptprogramm ***************************

void main()

 {
  //*********** Variable festlegen **********************
  unsigned int z;
  ein = 0;
  z = 0;
  TRISB = 16;  //RB4 als Eingang, alle anderen Leitungen auf Ausgang
  TRISA = 0;    // PORTA alles auf Ausgang


  RCSTAbits.SPEN = 1;  // serieller Port aktivieren
  RCSTAbits.RX9 = 0;
  RCSTAbits.CREN = 1;

  ADCON1bits.PCFG5 = 1;
  ADCON1bits.PCFG6 = 1;

  PIE1bits.TXIE = 0;    // Interrupt nicht aktiviert
  PIE1bits.RCIE = 1;


  TXSTAbits.TX9 = 0;
  TXSTAbits.SYNC = 0;  // asynchrone mode
  TXSTAbits.TXEN = 0;
  TXSTAbits.BRGH = 1;   // Einstellung der Baudratenauswahl
  TXSTAbits.TRMT = 1;

  SPBRG = 25;    // Baudrate = 9600 bei 4MHz


  //***********************************

  while(1)          // Dauerschleife
   {
    while(!PIR1bits.RCIF);

    ein = RCREG;
    delay1mtcy(1);
    if (ein == '0') z = 0;
    if (ein == '1') z = 1;
    if (ein == '2') z = 2;
    if (ein == '3') z = 3;
    if (ein == '4') z = 4;
    if (ein == '5') z = 5;
    if (ein == '6') z = 6;
    if (ein == '7') z = 7;
    if (ein == '8') z = 8;
    if (ein == '9') z = 9;
    LATB = ausgabe1[z];
    LATA = ausgabe2[z];
   }

 }

Ich weiß das die Ausgänge angesprochen werden, da durch z = 0 beim 
einschalten auch die pins geschaltet werden die zur Bildung der 0 
benötigt werden. Lese ich die Eingabe vom terminal an der falschen 
Stelle ein? Da jegliche Eingabe bzw senden über den terminal keine 
Veränderung der Beschaltung der Ausgänge bewirkt.

Sieht vielleicht jemand einen Fehler bei den 
Konfigurationseinstellungen?


Danke schonmal und Entschuldigung für ggf. komische Schreibweisen, ist 
schon spät. ;)

von Ohforf S. (ohforf)


Lesenswert?

Kai J. schrieb:
> Ich weiß das die Ausgänge angesprochen werden, da durch z = 0 beim
> einschalten auch die pins geschaltet werden die zur Bildung der 0
> benötigt werden.

Das verstehe ich nicht -
Die Zeile :
while(!PIR1bits.RCIF);
wartet doch erstmal auf Daten von der seriellen... ?

Übrigens, was für ein Pic ist es ?
Und wie sehen die Config-Bits aus ?
Ich leg die immer im Sourcecode fest... geht aber auch anderswo.
Da könnte der Wurm drin sein, z.B. dass dich der Watchdog beisst.

von Kai J. (Gast)


Lesenswert?

So, es funktioniert alles und eigentlich waren die ganzen Mühen hier 
umsonst.
Es lag an der Versuchsplatine, die ich für das Projekt von der Schule 
gestellt bekommen habe und wir auch auf Anfrage keine Pläne dafür 
bekommen haben.
Der zuletzt gepostete Quelltext arbeitet richtig.

von John (Gast)


Lesenswert?

Hallo Kai,
hier noch ein Tip.
Du kannst in Windows jedes beliebige Byte eingeben (im HypterTerminal 
senden).
Das funktioniert so:
 - Alt-Taste drücken und halten
 - Zahl mit den Zehnerblock (!) in Dezimal eingeben
   (1 bis 3 Stellen, 0-255)
 - Alt-Taste loslassen

Gruß
John

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.