PIC & GSM-Modem über RS232

Gast #1811418
Lesenswert?

Hallo folks,

ich bin auf Euren Rat bzw Eure Hilfe dringend angewiesen.

ich schreibe für einen PIC16F887 ein Programm, welches mit einem 
GSM-Modem mc35i (Siemens/Cinterion) kommuniziert.

Reines Senden PIC > Modem (zB 'ATDTnnnnnnnnn') funktioniert einwandfrei.

Beim Empfang haperts jedoch gewaltig.
Hier der relevante Codeausschnitt:

rs232-settings:
  BRGH=1;        // Baudrate 9600 Bits/s @ 4MHz
  SPBRG=25;
  SYNC=0;        // USART Empfaenger enablen
  SPEN=CREN=TXEN=1;  // USART Sender enablen

wenn ich jetzt folgendes mache
PIC > Modem sendet: 'ATI[CR]'
krieg ich bei einem normalen Terminalprogramm (hyperterminal) die 
normale Antwort (drei Zeilen 'Selbstgespräche' des Modems ;.))

mit meinem Programm/schnipsel/ (im Anschluss an obiges ATI-command)

while(1) {
  if(RCIF) {          // interrupt gesetzt?
     z=RCREG;         // Empfangsregister auslesen
     lcd_dat(z);      // Ausgabe am LCD
  }

}

erhalte ich jedoch nur ZWEI buchstaben ("AT"). Das ist genau die Anzahl 
von Zeichen, die der USART aufnehmen kann, ohne ausgelesen werden zu 
müssen.

In der Doku zum USART steht weiters, dass nach dem Lesen des RCREG das 
RCIF Interruptflag gelöscht wird.
Hab auch schon versucht, nach dem Lesen von RCREG das RCIF 'händisch' im 
Prog zu löschen - erfolglos.

Kann mir jemand einen Tipp oder eine funktionierende C-routine geben?

Vielen Dank schon mal jetzt!!

Rudi Ratlos
Gast #1811435
Lesenswert?

du weisst schon, dass Deine Variable z immer den Wert des aktuell 
empfangenen Zeichens annimmt. Was "lcd_dat()" macht weiss ich nicht.
Wenn Du das Flag von Hand gelöscht hast (richtig ;-)) und Du nicht alle 
Zeichen empfängst..., hmmm wie lange dauert "lcd_dat()" ?
Gast #1811461
Lesenswert?

> du weisst schon, dass Deine Variable z immer den Wert des aktuell
> empfangenen Zeichens annimmt.

ja, dieses will ich ja auslesen. Oder willst Du mir damit etwas anderes 
sagen?

> Was "lcd_dat()" macht weiss ich nicht.

sorry, dachte, geht aus dem comment hervor. es gibt das zeichen am 
lcd-display des uC aus.

> Wenn Du das Flag von Hand gelöscht hast (richtig ;-))

wobei mir die Doku in dem Moment sagt: das RCIF ist readonly....

> und Du nicht alle Zeichen empfängst..., hmmm wie lange dauert "lcd_dat()" ?

hmm, schwer zu sagen. Bin kein timing-experte.
Sind insgesamt 18 einfache C-Zuweisungen, ein nop() in C sowie ein delay 
von 1ms.
Hilft das weiter?
Denke mal, mit den 9600 baud sollte das aber mithalten können...

LG Rudi
Gast #1811592
Lesenswert?

Danke für Dein Angebot, Michael!

Ich bin schon mal dran, das auf interrupts umzuschreiben, im Mom kämpf 
ich noch mit Compilerdirektiven, damit er die richtigen Register rettet 
(ich arbeite mit dem cc5x).

Ich komm sicher wieder auf Dich zu!

LG Rudi
Gast #1811641
Lesenswert?

Und da bin ich auch schon wieder...

meine int-routine sieht jetzt so aus:

interrupt ISR(void) {      // Interruptroutine
  int_save_registers    // W, STATUS (und  PCLATH) retten
  if(RCIF) {
     usartbuff[usartind]=RCREG;
     usartind++;
  }

    //  und hier weiterer code, der interruptmäßig abgefackelt wird....
    ...
    ...
  int_restore_registers  // W, STATUS (und PCLATH) wiederherstellen
}

also will ich bei einem INT das RCREG in den 80-stelligen usartbufffer 
schreiben...

mein hauptprogramm:

for(i=0; i<=79; i++)
  usartbuff[usartind]='.';   // usartbuffer sicherheitshalber löschen
usartind=0;                        //
rs232_print("ATI"); delay(100);   // Modeminfo abholen
for(i=0; i<=20; i++)
  lcd_string(usartbuff[usartind]);   // usartbuffer ans LCD senden

ergebnis: seltsame zeichenfolgen am display:
ART ART ART ART ART ART
ART ART ART ART ART ART

Diese Buchstabenkombi ist Teil einer Zeichenkette, die an den USART 
gesendet wird, der aber in einem anderen Programmteil liegt und 
überhaupt nicht angesprochen wird.... Merkwürdig...

kannst Du mir bitte vll. helfen?

Danke, RudiR
Gast #1811751
Lesenswert?

warum nicht gleich so ;-)
vielleicht leigt es daran, dass Deine Lcd-Ausgabe ist nicht mit dem
Empfang synchronisiert ist.
Du kannst ein Flag im INT setzen, wenn der String vom Modem
komplett eingelesen wurde. Ich meine mich zu erinnern, dass die
Strings mit Carriage Return oder ähnlichem abgeschlossen werden.
Gast #1811974
Lesenswert?

Versuchs mal so:

for(i=0; i<=79; i++)
  usartbuff[usartind]=0;   // usartbuffer sicherheitshalber löschen
usartind=0;                        //
rs232_print("ATI"); delay(1000);   // Modeminfo abholen
lcd_string(usartbuff);   // usartbuffer ans LCD senden
Gast #1812897
Lesenswert?

hallo folks,

dank Eurer Hilfe läuft das Ding jetzt zufriedenstellen.

Zusammengefassst:

Meine Interruptroutine (unverändert):

interrupt ISR(void)      // Interruptroutine
{  int_save_registers    // W, STATUS (und  PCLATH) retten
  if(RCIF)
  { usartbuff[usartind]=RCREG;
    usartind++;
  }
        ... und noch einiges anderes hier
}

Im Hauptprogramm:

for(i=0; i<=80; i++)
  usartbuff[usartind]=0;      // buff löschen

usartind=0;                     // alles im rs232-lesepuffer befindliche 
verwerfen

rs232_println("ATI");               // senden befehl an modem
delay(10000);                  // testbetrieb: 10 sec warten in schleife 
auf modemantwort

for(i=0; i<usartind; i++)
  lcd_dat(usartbuff[i]); // ausgeben des lesebuffers am  LCD > tadellos

es war tatsächlich irgendwie die zeitliche koppelung von LCD und 
rs232-interrupts..

Danke nochmals, liebe Grüße

Rudi

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren