Forum: Compiler & IDEs UART initialisieren / gcc


von Stefan (Gast)


Lesenswert?

Hallo Leute,

ich versuch mit WinAVR ein Programm zu schreiben,
das mir über den UART meines ATmega32 ein paar Zeichen
zum PC sendet.

Dafür hab ich eine Funktion UART_init geschrieben die
mir den UART initialisieren soll.
Compilieren funktioniert ohne Probleme, beim debuggen
spring er allerdings nicht in UART_init. Kann es sein
das der Compiler das Unterprogramm wegoptimiert??

WAs kann ich dagegen machen? Bei Gelegenheit vielleicht
noch ein Tip ob die Übertragung auf diese Weise
funktionieren könnte!

Danke, Stefan



Hab das Programm mal drangehängt.


#include <avr/io.h>
 void UART_init(void)
 {

 // Baudrate einstellen

 sbi(UBRRH,7);        // Zugriff auf UBRRH ermöglichen
 UBRRH = (UBRRH | 0x00);
 UBRRL = 0x17;        // 9600 bps

  // Frame Format einstellen

 cbi(UCSRC,7);              // Zugriff auf UCSRC
 cbi(UCSRC,6);         // Asynchrone Übertragung
 UCSRC = (UCSRC | 0x10);     // Even Parity
 cbi(UCSRC,3);        // 1 Stop Bit
 UCSRC = (UCSRC | 0x03);    // 8 Datenbit
 cbi(UCSRB,2);

 // RxD, TxD freischalten

 sbi(UCSRB,3);        // TxD Pin freischalten
 sbi(UCSRB,4);        // RxD Pin freischalten

 }

 void send_fkt(char byte)
 {
  while ( !(UCSRA & (1<<UDRE)));
  UDR = byte;
 }

 int main(void)
 {

 UART_init;


 while(1)
    {
  send_fkt("O");    // Zeichen übertragen
  send_fkt("k");
  send_fkt(" ");
    }
 return 0;
 }

von Joerg Wunsch (Gast)


Lesenswert?

> Kann es sein das der Compiler das Unterprogramm wegoptimiert?

Sowas könnte bei -O3 Optimierung in der Tat erfolgen, bei allen
geringeren Optimierungen dagegen nicht.

Aber:

> UART_init;

Dafür hast Du keine Warnung bekommen (`statement has no effect' oder
sowas)?  Das würde mich wundern...

Du solltest Dir mal ansehen, wie man in C Funktionen aufruft. ;-)  Du
hast die Adresse der Funktion referenziert, sie aber nicht aufgerufen.
Da Du die Adresse hernach nicht benutzt, hat der Compiler das
natürlich wirklich wegoptimiert.

Hinweis: Falls Du die Optimierung ganz ausschaltest (-O0), dann
bekommst Du eine Reihe von Warnungen nicht mehr, die erst im
Optimiererlauf (Programmflußanalyse) festgestellt werden können.
`statement has no effect' könnte dazu gehören.

von Stefan (Gast)


Lesenswert?

Das mit dem Programmaufruf hatte ich schon
gefunden, war wirklich ein blöder Fehler! :-)

Allerdings ist mir das mit der Optimierung
des Compilers schon passiert, deswegen würd
mich mal interessieren wo sich das einstellen
läßt. Denk mal im makefile aber ich konnte
nichts entsprechendes finden.


Noch ne Frage zur Adressierung der UART Register.
Ich benutze eine ATmega32, soviel ich verstanden
hab liegen die Register UCSRC & UBRRH auf der
selben Adresse. Nach dem Datenblatt lassen sich
die beiden Register durch das setzen des MSB
auswählen.

Hab das folgendermaßen versucht:

cbi(UCSRC,7);
UCSCR = 0x...

sbi(UBRRH,7);
UBRRH = 0x...

aber beim debuggen bleibt das ohne Erfolg.
Wie kann ich die Register adressieren?

Ciao Stefan

von Joerg Wunsch (Gast)


Lesenswert?

> Allerdings ist mir das mit der Optimierung des Compilers schon
> passiert, ...

Was denn?

> deswegen würd mich mal interessieren wo sich das einstellen
> läßt. Denk mal im makefile aber ich konnte nichts entsprechendes
> finden.

So schwer zu finden?  Im Standard-WinAVR-Template gibt's extra
einen Makro OPT dafür, einschließlich Kommentar.

Oder <werbung>
http://www.sax.de/~joerg/mfile/
</werbung>

> Hab das folgendermaßen versucht:

> sbi(UBRRH,7);
> UBRRH = 0x...

Nun, das kann nicht gehen.  Überleg doch mal, Dein Schreibzugriff auf
UBRRH würde doch das zuvor geschriebene Bit 7 wieder überschreiben.

Ganz davon abgesehen: Du hast die Werte von Bit 7 vertauscht.  Bit 7
low selektiert UBRRH, Bit 7 high selektiert UCSRC.

Aber die Sache ist viel einfacher, als es sich auf den ersten Blick
liest: die zulässigen Vorteilerwerte in UBRRH sind allesamt so klein,
daß beim Schreiben von UBRRH Bit 7 sowieso immer low ist.  Wenn Du
beim Beschreiben dieser Adresse dagegen UCSRC meinst, dann mußt Du
stets auch »| _BV(URSEL)« mit reinnehmen.  Lesen ist etwas
komplizierter, siehe Datenblatt.  Allerdings solltest Du normalerweise
keinen Grund haben, eins dieser Register zu lesen, da Du ja deren
Inhalt normalerweise schon kennen solltest.

von funker (Gast)


Lesenswert?

Bevor der Beitrag auf der nächsten Seite verschwunden ist:

Probiere auch schon länger das UART beim 8515 in C-Code zum laufen
bringen, mit dem STK500:

#include <avr/io.h>

void send(char zeichen);

int main()
{
 sbi(UCR,3);        // TX aktivieren
 outp(25,UBRR);      // 4MHz -> 9600 bps

 for(;;)
 {
  send('T');
  send('e');
  send('s');
  send('t');
  send('!');
 }
}


void send(char zeichen)
{

while ( !( USR & (1<<UDRE)) )
  {
UDR = zeichen;
  }
}


Sendet leider nichts ans Terminal, darum wollte ich mal fragen ob meine
send-Funktion bzw. das USR richtig ist.

Das Assembler-Beispiel aus dem Tut habe ich mit dem 4433 auch
ausprobiert, funktioniert auch, leider nicht immer. Manchmal muss ich
erst den Reset-Taster drücken, dass "merkwürdige" Zeichen wieder
"Test!" ergeben - mit dem STK-Board.

von funker (Gast)


Lesenswert?

hat sich auch schon wieder erledigt, warum verstehe ich zwar nicht, habe
die funktionen nach avrfreak design geschrieben - jetzt gehts:

#include <avr/io.h>


void InitUART(unsigned char baudrate){
  UBRR = baudrate;
  UCR |= (1<<TXEN);
}


void transmit(unsigned char data){
  while(! (USR & (1<<UDRE)))
  ;
  UDR = data;
}


main(void){
  InitUART(25);
  while(1){
  transmit('a');
  transmit('b');
  }

}

von Rahul Ghose (Gast)


Lesenswert?

Kleiner Hinweis (da ich auch das Problem hatte):
Das STK500 verwendet einen Takt von 3,69MHz für den
"Slave"-Controller. Zumindest war das beim mitgelieferten at90s8515
so.
Einstellen kannst du die Frequenz im AVR-Studio bzw. mit
STK500-Plug-in.
Schönen Gruß
Rahul

von OldBug (Gast)


Lesenswert?

@funker:

void transmit(unsigned char data){
  while(! (USR & (1<<UDRE)))
  ;
  UDR = data;
}

Hier wird eine while-Schleife so lange ausgeführt (und NICHTS gemacht),
so lange die Bedingung "1" ergibt. Du könntest das ";" nach
Assembler in ein NOP übersetzen.

void send(char zeichen)
{

while ( !( USR & (1<<UDRE)) )
  {
UDR = zeichen;
  }
}

Hier wird in dieser while-Schleife Ständig das an die Funktion
übermittelte "zeichen" in UDR geschrieben.

So wäre das richtig (nur, um sicher zu stellen, daß das auch korrekt
verstanden wird :):

void send(char zeichen)
{

while ( !( USR & (1<<UDRE)) )
  {
     /* NOP ;) */
  }
UDR = zeichen;
}


Gruß,
Patrick...

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.