Forum: Mikrocontroller und Digitale Elektronik C515c-l putchar


von nic (Gast)


Lesenswert?

Hallo miteinander,

ich versuche grad Daten über meine Serielle Schnittstelle mittels 
printf() zu schicken. Damit er die Daten überhaupt an den Sendebuffer 
übergibt, musste ich die putchar() überschreiben. Das habe ich wie folgt 
gemacht:

char putchar (char c)  {
  while (!TI);
  TI = 0;
  return (SBUF = c);
}

Mein ganzes Programm sieht so aus:

#include <reg515c.h>
#include "lcd_c0.c"
#include "stdio.h"

void main() {
   TMOD = 0x10; // Timer 1 autoreload
   TH1 = 0xf5; // reload value for 9600 Baud
   TR1 = 1;     // Timer1 starten
   SM1=1; //|\__ Serial Channel in mode 1
   SM0=0; //|/
   lcd_init();
   lcd_clr();
   while(1) {
  TI=1;
     printf("Test");
  lcd_clr();
  lcd_str("Test");
   }
}


char putchar (char c)  {
  while (!TI);
  TI = 0;
  return (SBUF = c);
}


Nun läuft das Programm bis an die Stelle while(!TI); .
Dort bleibt es dann hängen. Kommentiere ich die Schleife aus,
schreibt er mir immer den letzten Buchstaben auf die Serielle 
Schnittstelle. Irgendwie wird das Transmit-Interrupt flag nicht gesetzt.
An was kann das liegen?

von Ralf (Gast)


Lesenswert?

Hi,

"TMOD = 0x10" konfiguriert den Timer 1 auf Mode 1, 16-Bit, nicht auf 
Mode 2, 8-Bit mit Autoreload. Das muss also 0x20 heissen.

Da es sich bei TMOD um ein Register handelt, welches zwei 
Peripherie-Einheiten bedient (Timer 0 und 1), würde ich dir empfehlen, 
die Konfiguration so vorzunehmen:

TMOD &= 0x0F;  //Alle relevanten Flags für Timer 1 löschen
TMOD |= 0x20;  //Alle nötigen Flags für Timer 1 setzen

Das sorgt dafür, dass wenn du irgendwo Timer 0 konfigurieren möchtest, 
du nicht die Konfiguration für beide in einem Rutsch machen musst. Das 
halte ich für übersichtlicher, weil dann die Konfiguration immer dort 
gemacht wird, wo sie gebraucht wird. Ist aber Geschmackssache.

Ralf

von nic (Gast)


Lesenswert?

Hallo Ralf,

danke für die Schnelle Antwort, aber das hat mein Problem leider auch 
nicht behoben. Mein TI wird irgendwie nie gesetzt und mein Programm 
bleibt in der while-Schleife in putchar() hängen...

von Andy (Gast)


Lesenswert?

Versuchs mal damit:

TI Flag in Interrupt zurücksetzen und in putchar warten,
bis letztes Byte gesendet wurde.

//************ UART Interrupt **************

void receive_Int( void ) interrupt 4
{
  if(RI==1)  // Byte empfangen
  {
    lkjafkljaskdfj........
    jadsfjaskldf........
    RI=0;
   }     // Ende von if RI ==1..


   if(TI==1) // Byte gesendet
   {
     TI=0;
   }
}

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

char putchar (char c)  {
  while (TI==1);
  return (SBUF = c);
}

von Andy (Gast)


Lesenswert?

Nicht vergessen, den IRQ auch freizugeben:

ES = 1;   // Freigabe des UART IRQ's

von Ralf (Gast)


Lesenswert?

Du darfst TI = 1 nicht in der while(1) Schleife setzen, weil es sein 
kann, dass der letzte Buchstabe noch nicht gesendet wurde. Das hilft 
zwar nicht ganz weiter, ist aber trotzdem ein Fehler. Du musst es vor 
der while Schleife setzen.

Dass TI NIE gesetzt wird, glaub ich nicht. Sobald etwas in SBUF 
geschrieben wird, wird auch etwas über die serielle rausgepustet, und am 
Ende der Übertragung das TI Flag gesetzt.

Woher weisst du denn, dass das Programm genau bei der Abfrage von TI 
hängenbleibt? Simulator?
Oder nur die Zeile auskommentiert und probiert?

Was macht denn der Compiler aus der Abfrage, also welche Assembler 
Befehle kommen denn da raus? Kannst du die mal posten?

Ralf

von noch_ein_gast (Gast)


Lesenswert?

Schau mal ins Handbuch
oder auch beispielsweise in Quellcodebeispielen nach. TI wird immer dann 
gesetzt, wenn das Zeichen gesendet wurde (vor dem Stopp-Bit).

Dann musst Du bloß in der ISR das TI rücksetzen und ggf. weitere Zeichen 
senden.
Um auf meinen Vorschreiber bezug zu nehmen... du musst nicht nur ES=1 
setzen, sondern auch EAL (enable all interrupts). Die Maskierten sind 
dabei außen vor...

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.