Forum: Compiler & IDEs UART-Fehler :(


von M@cFreak (Gast)


Lesenswert?

Hallo!

Ich möchte - so wie es im Tutorial beschrieben ist - über die RS232 von 
meinem STK500 das Zeichen "x" ausgeben.

Klappt jedenfalls nicht: Kompilierfehler: undefined UCR, UBRR, usw.

#include <inttypes.h>
#include <avr/io.h>

#define F_CPU 4000000
#define UART_BAUD_RATE 9600

int main (void)
{


UCR |= (1<<TXEN);

UBRR = F_CPU / (UART_BAUD_RATE * 16L) - 1;




while (! (USR & (1<<UDRE)))
{
}

UDR = 'x';

}


Woran kann das liegen?

Woher weiß ich die Taktfrequenz vom µC?

von Wolfram (Gast)


Lesenswert?

>Kompilierfehler: undefined UCR, UBRR, usw.
>Woran kann das liegen?
Das er UCR, UBRR nicht kennt?

von M@cFreak (Gast)


Lesenswert?

der Compiler oder der µC?

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
>
> Woran kann das liegen?

Welchen Prozessor benutzt du?

Danach holst du dir von Atmel das Datenblatt und siehst
nach, wie die bewussten Register in deinem Prozessor
heissen. Je nach AVR heissen die ein klein wenig anders.

>
> Woher weiß ich die Taktfrequenz vom µC?

Wenn du nichts gemacht hast, dann läuft der
Prozessor wahrscheinlich auf 1Mhz mit internem Takt.
Mach dich schon mal darauif gefasst, dass eine stabile
RS232 damit nicht funktionieren wird.

Der andere Fall ist: Du hast auf externen Quarz oder
Quarzoszillator umgestellt. Dann steht auf dem Quarz
bzw. Oszillator drauf, wie schnell er taktet.

von Wolfram (Gast)


Lesenswert?

>der Compiler oder der µC?
Eigentlich: DU
Lies das Datenblatt da findest du die Namen und auch ein Beispiel

von M@cFreak (Gast)


Lesenswert?

ich habe einen ATmega8515, bin mir nicht sicher, dass ich nichts 
verstellt habe. Habe nämlich schon ein paar Programme auf ihm laufen 
gehabt.

ich verwende das STK500. Da ist doch ein Quarz drauf....Weiß aber nicht 
wie der taktet

von M@cFreak (Gast)


Lesenswert?

habe es nun so abgeändert:



#include <inttypes.h>
#include <avr/io.h>

#define F_CPU 4000000
#define UART_BAUD_RATE 9600

int main (void)
{


UCSRB |= (1<<TXEN);

UBRRL = F_CPU / (UART_BAUD_RATE * 16L) - 1;




while (! (UCSRB & (1<<TXEN)))
{
}

UDR = 'x';

}


von OliverSo (Gast)


Lesenswert?

Und warum? Gehts?

Lies die Fueses aus, nimm das Datenblatt, und schau nach, mit welcher 
Taktquelle der Prozessor läuft. Alles andere ist Raterei.

Oliver

von M@cFreak (Gast)


Lesenswert?

also ich habe nun die Fuses auf "Int Osc 4 Mhz" gesetzt...

Auf welche RS232 vom STK500 muss ich meine Leitung zum Rechner 
anschließen?

von Falk B. (falk)


Lesenswert?

@ M@cFreak

>also ich habe nun die Fuses auf "Int Osc 4 Mhz" gesetzt...

Falsche Einstellung!

http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART#Senden

MFG
Falk

von Wolfram (Gast)


Lesenswert?

RS232 SPARE wenn du am PC empfangen willst. Sind die Bilder in der 
AVRStudio Hilfe noch nicht bunt genug?

von M@cFreak (Gast)


Lesenswert?

was heißt bunt genug...kannst du mir vllt. helfen, was in dem Datenblatt 
in der Tabelle "Examples of UBRR Settings for commoncly used oscillator 
frequencies" die zahlen 41 83 usw unter "U2x =1" sein sollen? ist das 
Hex, was in das Register reingeschrieben werden muss???

von Karl H. (kbuchegg)


Lesenswert?

Vergiss die Tabelle.
Du hast doch eine schöne Formel in die du nur
die Werte einsetzen musst (eigentlich macht das
sogar der Compiler) und schon kriegst du die
richtigen Werte raus.

Aber du kannst ja spasseshalber einfach mal einen
Taschenrechner nehmen und deine Zahlen einsetzen
und schaun was dabei rauskommt.
Die Zahl dann probehalber mal auf Hex umrechnen
und dann beides (dezmal und hex) mit den
Angaben im Datenblatt vergleichen.

von Christian B. (christianbeuge)


Lesenswert?

Hallo zusammen!

Also, ich habe auch kein Glück mit der UART. Ich bin leider auch 
Anfänger und hoffe, Ihr könnt mir helfen. Das mit der Taktfrequenz habe 
ich auch nicht ganz verstanden. Ja, die Formel habe ich gesehen.
[UBRR = Taktfrequenz / (16 *Baudrate)-1]

Leider weiß ich nicht, mit welcher Frequenz mein AVR Butterfly getaktet 
wird (32KHz für RTC) und ob und wie ich die Interne Taktfrequenz ändern 
kann. Liegt daran... bin Anfänger.

Wäre super, wenn Ihr mir weiterhelfen könnt...

Danke!!

Gruß Christian




#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/iom169p.h>
#include <avr/portpins.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#define BAUD 9600
#define FOSC 1843200  //Taktgeschwindigkeit 1,8 Mhz
#define MYUBRR FOSC/16/BAUD-1  //what ever that mean... Formel???

// Receive Interrupt
ISR(USART0_RX_vect ) // veraltet: SIGNAL(SIG_OVERFLOW0)

{
// ISR: Zeichen wurde empfangen
  while ( !( UCSR0A & (0x20)) ); //Warten bis alles empfangen wurde = 
UART Data empty
//  UDR0 = UDR0 + 1; // Gesendet: 0x01 Antwort: 0xFF
  UDR0 = 0x01;   // Gesendet: 0x01 Antwort: Endlosschleife 20 04 3F 20 
3F 44 80 10 20 3F 04...
  //Frage, warum bekomme ich bei 0x01 eine Endlosschleife???
}

//Zeichen wurde komplett gesendet
ISR(USART0_TX_vect ) // veraltet: SIGNAL(SIG_OVERFLOW0)
{


}

void USART_Init (unsigned int ubrr)
{
// zuerst Baudrate setzen
  UBRR0H = (unsigned char) (ubrr>>8);
  UBRR0L = (unsigned char) (ubrr);
//nun Sender und Empfänger initialisieren
  UCSR0A = 0x00;
/*
 RXC
 TXC
 UDRE
 Frame Error
 DOR
 USart Parity Error
 Double USART Transmission Speed
 MPCM: Multi processor Comm. Mode
*/

  UCSR0B = 0xF8;
/*
 RXCIE  RX Complete Interrupt Enable
 TXCIE  TX Complete Interrupt Enable
 UDRIE  USART Data Register Empty IE
 RXEN  Receiver Enable
 TXEN  Transmitter Enable
 UCSZ2  Character Size (Number of Databits
 RXB8  Receive Data Bit 8
 TXB8   Transmit Data Bit 8
*/

//Frameformat setzen: 8 Datenbits, 1 Stopbits

  UCSR0C = 0x86;

/*
 ----  No Funktion
 UMSEL USART Mode Select (Synch / ASynch)
 UMP1  Parity Mode
 UMP2  Parity Mode
 USBS  Stop Bit Select
 UCXZ1 Character Size
 UCXZ0 Character Size
 UCPOL Clock Polarity (only synch Mode)
*/
}

// UART main

int main(void)
{
  DDRD = 0xff;    //enable PortD as output
  sei();        //enable Interrupt
  USART_Init (MYUBRR);

  while (1)
  {

  };

}

von Karl H. (kbuchegg)


Lesenswert?

Christian Beuge wrote:
> Hallo zusammen!
>
> Anfänger und hoffe, Ihr könnt mir helfen. Das mit der Taktfrequenz habe
> ich auch nicht ganz verstanden. Ja, die Formel habe ich gesehen.
> [UBRR = Taktfrequenz / (16 *Baudrate)-1]

Ist nicht weiter schwer.
Eine UART arbeitet in einem fixen Zeitraster.
Dieses Zeitraster wird durch 2 Faktoren bestimmt
* zum einen die gewünschte Baudrate,
* zum anderen die fixe Taktgeschwindigkeit des Prozessors.

Stell es dir einfach so vor: Die UART muss zwischen dem
Versenden von einzelnen Bits gewisse Wartezeiten einhalten.
Zum einen bestimmt natürlich die gewünschte Baudrate wie
lange (in Zeiteinheiten) die UART 'Däumchen drehen' muss.
Zum anderen bestimmt natürlich die vorhandene Taktfrequenz
wie schnell die UART 'Däumchen drehen kann'. Ergo muss
man irgendwann mal ausrechnen, wieviele 'Däumchen gedreht
werden müssen', damit eine bestimmte Zeit vergeht.

Genau das macht die Formel.
Sie rechnet aus, wie oft die UART in einer Schleife laufen
muss, bis die für eine bestimmte Baudrate notwendige Wartezeit
zwischen 2 Bits abgelaufen ist.

>
> Leider weiß ich nicht, mit welcher Frequenz mein AVR Butterfly getaktet
> wird (32KHz für RTC) und ob und wie ich die Interne Taktfrequenz ändern
> kann. Liegt daran... bin Anfänger.

Steht im Datenblatt.
Gewöhn dich daran. Du wirst das Datenblatt noch oft brauchen.

Laut Datenblatt arbeitet dein Mega169 mit 1Mhz Taktfrequenz
(leider auf internem Oszillator. Der ist leider meist seht
ungenau. Ob damit eine vernünftige Verbindung mittels RS232
zusatande kommt, ist fraglich. Aber möglich).

>
> Wäre super, wenn Ihr mir weiterhelfen könnt...

Schreib am Anfang kein so 'kompliziertes' Programm, das mittels
Interrupt Zeichen verschickt. Machs dir einfach.
Und im übrigen solltest du dch an die Beispiele im Tutorial
halten. Angepasst an die Registernamen die auf deinem µC gelten.
1
#include <avr/io.h>
2
#include <stdint.h>
3
4
#ifndef F_CPU
5
#define F_CPU 1000000          /* Oszillator-Frequenz in Hz */
6
#endif
7
 
8
// Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)
9
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
10
 
11
#define UART_BAUD_RATE 9600
12
13
int main(void)
14
{
15
  UCSRB |= ( 1 << TXEN );   // UART TX einschalten
16
  UCSRC |= ( 3<<UCSZ0 );    // Asynchron 8N1
17
18
  // Baudrate setzen
19
  UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 );
20
  UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU );
21
22
  while( 1 ) {
23
    //
24
    // warten bis die UART 'fertig' meldet
25
    //
26
    while (!(UCSRA & (1<<UDRE)))
27
      ;
28
29
    //
30
    // und ein Zeichen senden
31
    // 
32
    UDR = 'x';
33
  }
34
}

  

von M@cFreak (Gast)


Lesenswert?

so. Jetzt stelle ich mal mein Beispiel rein, mit dem es auf der RS232 
SPARE von meinem STK 500 ebenfalls nicht funktioniert:

Vllt. könntet ihr mir den Fehler sagen. Ich habe übrigens keinen 
externen Oscillator/Quarz, sondern den Internen auf 4 MHz in den Fuses 
gesetzt.

----------------------------------

#include <inttypes.h>
#include <avr/io.h>

#define F_CPU 4000000

/////////////////// Im Terminalprogramm wird eine Baudrate von 9600 
eingestellt

int main (void)
{



UCSRB |= (1<<TXEN);              //Senden aktivieren
UCSRC |= (1<<URSEL)|(3<<UCSZ0);  //

UBRRH = 00;                      //Baudrate einstellen
UBRRL = 25;


//UCSRA |= (1<<U2X);               //UCSRA: Bit "U2x" setzen     BRAUCHE 
ICH DAS??????


while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
{
}

UDR = 'x';             //x zum senden ins Datenregister
while (1);
}




Vielen Dank

von johnny.m (Gast)


Lesenswert?

> BRAUCHE ICH DAS??????
Nein, das ist in dem Falle (für 9600 Baud) sogar falsch! U2X verdoppelt 
die Baudrate bei gleichen UBRRx-Settings. Du hast damit also 19200 Baud.

Außerdem: Bist Du sicher, dass die Einstellungen vom Hyperterminal exakt 
mit denen des Controllers übereinstimmen (Stopbits, Parity)?

Außerdem ist der interne Oszillator der AVRs für asynchrone 
Datenübertragung nicht wirklich geeignet, weil er u.U. zu ungenau ist 
und eine starke Temperaturdrift hat. Es kann Dir also auch passieren, 
dass bei korrekten Einstellungen am PC nur Murks ankommt. Wenn es 
zuverlässig laufen soll, nimm einen Quarz. Mit dem internen Oszi ist das 
alles Glückssache.

von M@cFreak (Gast)


Lesenswert?

Also. Danke erstmal für deine antwort.

Ich habe - wie du geschrieben hast - nun einen Quarz von 8 MHz. Somit 
auch 8 MHz in den Fuses eingestellt.
Jetzt kommentiere ich das mit dem U2X noch aus,....habe nun 9600 
Baudrate: Terminal-Einstellungen: Data: 8bit, Parity: none, Stop: 1 bit.

Stimmt das soweit?

danke

von M@cFreak (Gast)


Lesenswert?

...sorry, nochwas.: und ich muss natürlich auch diese "UBRRL = 25" auf 
"UBRRL = 51" stellen.

Danke!

von Karl H. (kbuchegg)


Lesenswert?

Ich kann nur sagen:

Wenn deine Taktfrequenz stimmt, dann läuft das Pgm das
ich gepostet habe einwandfrei.

Wenn das bei dir also nicht klappt, dann liegt das
* falscher Prozessor Taktfrequenz
* Kabel
* sontiges Hardwareproblem


von Wolfram (Gast)


Lesenswert?

Ich versuche nachzuvollziehen, warum du solche Probleme beim Einstieg 
hast.
Auf dieser Seite gibt es ein Tutorial da steht eine ganze Menge drin 
aber nicht speziell zum STK500 aber der Stolperstein Fuseproblematik ist 
angesprochen.

Im Datenblatt ab Seite 151 findest du C-Programmcode zur Initialisierung 
der UART und zum Senden, den kannst du übernehmen (copy und Paste)
Im AVR-Studio in der Hilfe ist die Beschreibung des STK500 und speziell
Description of User RS232 Interface da sind Bilder (ok nicht bunt) zum 
Anschluß und es steht da welche du benutzen mußt.
Dein Terminalprogramm mußt du nur auf die Werte der Verbindung 
einstellen
(Baudrate,Stopbits, Parität) Das solltest du selbst wissen wie das geht.

Bis jetzt habe ich nur die Erklärung, daß du die dir zur Verfügung 
stehenden Informationsquellen nicht ordentlich nutzt. Ändere das, sonst 
wird das ein sehr frustrierender Einstieg.

Wenn du ins Forum postest sind Sätze wie "...ebenfalls nicht 
funktioniert:"
nicht sehr hilfreich. Beschreibe was passiert, bei welchen 
Einstellungen.

von M@cFreak (Gast)


Lesenswert?

aber wenn meines richtig ist und deines richtig ist, dann müsste doch 
auch meins funktionieren und kein Unterschied von der Funktion gegeben 
sein....

Jedenfalls funktioniert die Lösung aus dem Tutorial NICHT

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
> aber wenn meines richtig ist und deines richtig ist, dann müsste doch
> auch meins funktionieren und kein Unterschied von der Funktion gegeben
> sein....
>
> Jedenfalls funktioniert die Lösung aus dem Tutorial NICHT

Doch die funktioniert.
Wenns bei dir nicht funktioniert, dann liegt der Fehler
in einem Bereich, der ausserhalb des Tutorials liegt:
* irgendwas in der Hardware
* Kabel falsch rum beschaltet
* am häufigsten aber: Die angegebene Taktfrequenz stimmt
  nicht mit der Realität überein.

Was mich zb. verblüfft ist, dass du als Anfänger in noch
nicht mal einer Stunde einen Quarz eingebaut hast und den
auch noch korrekt gefused hast.
Allerdings gibt mir der Satz zu denken:
"Somit auch 8 MHz in den Fuses eingestellt."

Das klingt nicht danach, als ob du den externen Quarz
aktiviert hast. Das hört sich eher an als ob du die CLKDIV
Fuse ausgeschaltet hast. Dein µC läuft dann zwar mit 8Mhz
aber immer noch am internen Oszillator.

von M@cFreak (Gast)


Lesenswert?

Der Quarzeinbau ist bei dem STK500 ja nur gesteckt. Ich habe also einen 
8 MHz Quarz reingesteckt. Als nächstes habe ich in meinem Programmcode
UBRRL = 51 gesetzt. Dann habe ich unter "Fuses" das Häkchen bei "Ext. 
Crystal/Resonator Medium Frequ.; Start-up time: 1K CK + 64 ms;" gesetzt, 
welches vorher bei int RC Osc. 4 MHz stand.

Dann habe ichs kompiliert, Terminal geöffnet, Auf RS232 SPARE umgesteckt 
und Nix empfangen.

so ist der Stand der dinge

von Falk B. (falk)


Lesenswert?

@ M@cFreak

>UBRRL = 51 gesetzt. Dann habe ich unter "Fuses" das Häkchen bei "Ext.
>Crystal/Resonator Medium Frequ.; Start-up time: 1K CK + 64 ms;" gesetzt,
>welches vorher bei int RC Osc. 4 MHz stand.

Hoffentlich ist auch die DIV8 Fuse NICHT programmiert.

MFG
Falk

von Wolfram (Gast)


Lesenswert?

>Dann habe ichs kompiliert, Terminal geöffnet, Auf RS232 SPARE umgesteckt
>und Nix empfangen.
Du sagst weder welche Einstellungen du im Terminal hast, noch ob du dir 
die Hilfe im AVRStudio durchgelesen hast.
Da ist nämlich auch zu sehen, daß du eine Verbindung zwischen den 
Portpins und den RX/TX Anschlüssen des STK500 machen mußt. Kann es sein 
das du dies vergessen hast?

von M@cFreak (Gast)


Lesenswert?

DIV8-Fuse?

von M@cFreak (Gast)


Lesenswert?

#include <inttypes.h>
#include <avr/io.h>

#define F_CPU 8000000

/////////////////// Im Terminalprogramm wird eine Baudrate von 9600 
eingestellt

int main (void)
{



UCSRB |= (1<<TXEN);              //Senden aktivieren
UCSRC |= (1<<URSEL)|(1<<USBS)|(1<<UCSZ1);  //

UBRRH = 0;                      //Baudrate einstellen
UBRRL = 51;


while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
{
}

UDR = 'x';             //x zum senden ins Datenregister
while (1);
}





Hier nochmal der momentane Code

von M@cFreak (Gast)


Lesenswert?

Hier nochmal die Einstellungen im Terminal:

habe nun 9600 Baudrate: Terminal-Einstellungen: Data: 8bit, Parity: 
none, Stop: 1 bit.


Die Hilfe habe ich noch nicht durchgelesen.

Danke

von M@cFreak (Gast)


Lesenswert?

habe nun eine Leitung von RS232 SPARE zu PORTD PD0/PD1.

Geht aber trotzdem nicht.

von Karl H. (kbuchegg)


Lesenswert?

Ändere mal dein Programm um:

Lass den µC in einer Endlosschleife ständig senden
1
  while( 1 ) {
2
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
3
    {
4
    }
5
6
    UDR = 'x';             //x zum senden ins Datenregister
7
  }
8
}

Und dann begibst du dich mit einem Voltmeter auf Fehlersuche.
Du kannst auch eine LED + Vorwiderstand (330 Ohm) nehmen.
Damit überprüfst du mal direkt an den Prozessorpins (PD0,
PD1), ob der Prozessor sendet. Mit einer LED müsstest du
an einem der Pins ein deutliches Flackern sehen.

Wenn du das Flackern hast, dann verfolgst du es weiter
(über alle Verbindungen), bis du am Stecker angelangt bist.


(Led + Vorwiderstand: Ein Bein von der Led kommt an den
Prozessorpin, das andere an den Vorwiderstand. Von dort
gehts weiter zum Widerstand und das andere Bein vom Widerstand
kommt fix an Masse. Probier aber aus, ob du die Led richtig
rum gepolt hast. Wenn du das frei Led Beinchen an +5V hälts,
muss sie leuchten).



von M@cFreak (Gast)


Lesenswert?

Hier der aktuelle Code. Den obigen könnt ihr vergessen. War en Fehler 
drin.

#include <inttypes.h>
#include <avr/io.h>

#define F_CPU 8000000

/////////////////// Im Terminalprogramm wird eine Baudrate von 9600 
eingestellt

int main (void)
{



UCSRB |= (1<<TXEN);              //Senden aktivieren
UCSRC |= (1<<URSEL)|(3<<UCSZ0);  //

UBRRH = 00;                      //Baudrate einstellen
UBRRL = 51;


while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
{
}

UDR = 'x';             //x zum senden ins Datenregister
while (1);
}

von M@cFreak (Gast)


Lesenswert?

Also...ich habe nun bei meinem ATmega8515 eine Leuchtdiode wie folgt 
drangehalten:  An Pin11 (Transmit-Pin) die Anode der Diode und an Pin 20 
(mit vorwiderstand) die Katode der Diode.
Sie Leuchtet! von flackern ist nichts zu sehen.

von Stefan (Gast)


Lesenswert?

Sie kann nicht flackern. Du schickst exakt ein Zeichen 'x'. Dessen 
wackelnden Bits sind schneller weg, als du kucken kannst. Du solltest 
die Programmmodifikation von Karl heinz einbauen.

von M@cFreak (Gast)


Lesenswert?

welche Programmmodifikation denn genau? Weil alles doppelt im code zu 
haben ist auch nicht gut....

von M@cFreak (Gast)


Lesenswert?

achso, du meinst diese While-Schleife....die habe ich schon drin...

Dass er praktisch nonstop dieses Zeichen schickt: ich sagte, mit der 
"Modifikation" leuchtet meine Diode permanent. (wird wohl flackern, ist 
eben nicht zu sehen).

Habe leider kein Oszi zur verfügung.

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
> achso, du meinst diese While-Schleife....die habe ich schon drin...
>
> Dass er praktisch nonstop dieses Zeichen schickt: ich sagte, mit der
> "Modifikation" leuchtet meine Diode permanent. (wird wohl flackern, ist
> eben nicht zu sehen).
>

Dann geh mit der Baudrate runter.
300 Baud musst du sehen können.

> Habe leider kein Oszi zur verfügung.

von M@cFreak (Gast)


Lesenswert?

wie komme ich denn auf 300 Baud? die Tabelle zeigt mir die Möglichkeit 
nur bis 2400 zu gehen

von Stefan (Gast)


Lesenswert?

Aus meinen Erinnerungen zu Modemzeiten: 2400 Baud siehst du auch.

Wenn wider Erwarten nicht, dann rufe eine Warteschleife z.B. 
_delay_ms(10) nach jedem Zeichen auf.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

von M@cFreak (Gast)


Lesenswert?

ok :-) es funktioniert!

Vielen Dank!

Und was war der Fehler? --> Im Terminal-Programm anstatt COM1 war COM3 
eingestellt AAAAAAAHHHH

von M@cFreak (Gast)


Lesenswert?

aber noch kommen komische Zeichen an, anstatt "x"

von M@cFreak (Gast)


Lesenswert?

woran kann das liegen?

wenn ich z.b. das "x" in der Schleife laufen lasse, dann kommen  "$$$$$"

von Karl H. (kbuchegg)


Lesenswert?

Dann stimmt am Timing was nicht.

Also nochmal: Taktfrequenz kontrollieren

#define F_CPU  8000000
#include <avr/io.h>
#include <utils/delay.h>

int main()
{
  int i;

  DDRB = 0xFF;  // Port B auf Ausgang oder wo du halt sonst
                // ein paar LED drann hast

  while( 1 ) {
    PORTB = 0xFF;

    for( i = 0; i < 100; ++i )
      _delay_ms( 10 );

    PORTB = 0x00;

    for( i = 0; i < 100; ++i )
      _delay_ms( 10 );
  }
}

Die Leds müssen im Sekundentakt blinken (das kann man auch
mit freiem Auge noch gut abschätzen).


von M@cFreak (Gast)


Lesenswert?

ähm, gute idee, mal das Timing zu testen. aber die <utils/delay.h> kennt 
der compiler nicht. "no such file or directory"

von M@cFreak (Gast)


Lesenswert?

ok hat sich erübrigt :)
moment...ich teste jetzt ob die led blinkt

von johnny.m (Gast)


Lesenswert?

> aber die <utils/delay.h> kennt der compiler nicht.
"util" und nicht "utils"

von M@cFreak (Gast)


Lesenswert?

die leuchten bei mir etwa 1,9 sec. Also länger als 1 secunde!

Was soll ich nun machen??

von Wolfram (Gast)


Lesenswert?

Hattest du die Taktfrequenz nicht auf 4 Mhz eingestellt?
würde den Zeitunterschied 1:2 erklären.

>Was soll ich nun machen??
Setz dich hin und lies die Doku.

von M@cFreak (Gast)


Lesenswert?

Nein die habe ich ja dazwischen wieder auf 8 MHz umgestellt.

von M@cFreak (Gast)


Lesenswert?

AHHHH, liegt wohl am Quarz, denn wenn ich den aus der Fassung ziehe, 
dann läuft im Terminal alles wie wenn er drinnensteckt. Ist also doch 
was mit der Einstellung zum Oszillator falsch

von Karl H. (kbuchegg)


Lesenswert?

Hast du debug compiliert, oder den Optimizer eingeschaltet.
Damit die delay Funktionen klappen, muss der Optimizer
eingeschaltet sein.

Im AVR Studio findest sich das im 2-ten Menüpunkt
ganz unten (hab keines da, drum kann ich nicht nachschauen
wie der heist: Irgendwas mit Project - Properties oder so
ähnlich).

Stell die Optimierung auf -Os

Wenn du dann immer noch 1.9 Sekunden hast, dann
läuft der µC offensichtlich nicht mit 8 Mhz.

von M@cFreak (Gast)


Lesenswert?

ok habe das gemacht. Schwer mit der Stoppuhr zu messen. Jedenfalls 
länger als 1 Sekunde blinken die.

von M@cFreak (Gast)


Lesenswert?

also nochmal, Karl-Heinz. Wo kann ich , dass er 8 MHz von meinem Quarz 
schwingt, einstellen. Vllt. habe ich da einen Denkfehler.

Danke

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
> ok habe das gemacht. Schwer mit der Stoppuhr zu messen.

Das brauchts auch nicht.
Meistens hat man ja ein Vielfaches.
Wenn also im Pgm 8 Mhz steht und der µC macht in Wirklichkeit
4Mhz, dann sind die Leds anstelle von 1 Sekunde deren 2
eingeschaltet.
Läuft der µC gar nur auf 1 Mhz, dann leuchten die Led
ganze 8 Sekunden statt 1

Das erkennt auch ein Blinder.

> Jedenfalls länger als 1 Sekunde blinken die.

Schlecht.

http://www.mikrocontroller.net/articles/AVR_Fuses

Da du einen Quarz benutzt ist die richtige Einstellung
bei dir "external Crystal".


von Stefan (Gast)


Lesenswert?

> ok habe das gemacht. Schwer mit der Stoppuhr zu messen.

Miss den Puls deines AVR ;-)

Setz dir eine vernünftige Zeitspanne fest z.B. 20 Sekunden. Zähle wie 
oft es in der Zeitspanne blinkt. Teile Zählwert durch Zeitspanne und du 
hast die Frequenz.

von Stefan (Gast)


Lesenswert?

Die Frequenz des Blinkens, nicht des µC ;-)

von Karl H. (kbuchegg)


Lesenswert?

Stefan wrote:
>> ok habe das gemacht. Schwer mit der Stoppuhr zu messen.
>
> Miss den Puls deines AVR ;-)
>
> Setz dir eine vernünftige Zeitspanne fest z.B. 20 Sekunden. Zähle wie
> oft es in der Zeitspanne blinkt. Teile Zählwert durch Zeitspanne und du
> hast die Frequenz.

Aber Achtung: Das Programm lässt die LED 1 Sekunde eingeschaltet
und 1 Sekunde ausgeschaltet. Das ergibt eine Soll-Frequenz
von 0.5 Herz.

Und weil es wichtig ist: Die Zeiten stimmen nur dann, wenn
im Compiler die Optimierung eingeschaltet ist.

von M@cFreak (Gast)


Lesenswert?

Ja die Optimierung ist eingeschaltet. Habe ich so gemacht, wie es 
Karl-Heinz beschrieben hat.

Möchte vielmehr sicher gehen, dass der Mikrocontroller "einfach" über 
den Quarz taktet. Anscheinend tut er das ja nicht, habe ja vorhin scho 
ngeschrieben, dass die Daten in das Terminal weiterhin strömen, wenn ich 
den Quarz rausziehe!


danke

von Franz-Rainer (Gast)


Lesenswert?

Hast Du auch den Jumper "OSCSEL" auf dem STK500 umgesteckt?

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
> Ja die Optimierung ist eingeschaltet. Habe ich so gemacht, wie es
> Karl-Heinz beschrieben hat.
>
> Möchte vielmehr sicher gehen, dass der Mikrocontroller "einfach" über
> den Quarz taktet. Anscheinend tut er das ja nicht, habe ja vorhin scho
> ngeschrieben, dass die Daten in das Terminal weiterhin strömen, wenn ich
> den Quarz rausziehe!
>

Oha.
Das ist aber ein deutliches Indiz dafür, dass
der µC auf 'interner Oszillator' läuft.

von M@cFreak (Gast)


Lesenswert?

ja, bloß was kann ich mehr machen, als den Haken auf "Ext. 
Crystal/Resonator" und anschließend auf "Program" zu klicken???

von Karl H. (kbuchegg)


Lesenswert?

Wenn du nach dem Programmieren die Fuses wieder einlesen
lässt, ist der Haken dann immer noch gesetzt?


Blöde Frage:
Den Haken bei 'int Oszillator' hast du weg gemacht?

von M@cFreak (Gast)


Lesenswert?

ok, hat jetzt super geklappt.

Und woran lags? An nem Jumper, der von internal Osc. am STK500 auf 
external Osc. schaltet

ES funktioniert 100 %ig :)

vielen Dank für euere Hilfe (und Geduld)!

von Franz-Rainer (Gast)


Lesenswert?

Also.. Sagte ich ja!

von M@cFreak (Gast)


Lesenswert?

und nun zum Empfangen vom terminal. Mein Ziel ist es, ein Zeichen ins 
Terminal zu schreiben und dieses dann an "PORTB" (Leuchtdioden) 
ausgeben, damit ich seh, ob was bei µC ankommt:

Würde das funktionieren?
-------------------------------------------------------------
#include <avr/io.h>


int main (void)

{
DDRB = 0xFF;

UCSRB |= (1<<RXEN);
UBRRH = 00;                      //Baudrate auf 9600 einstellen
UBRRL = 51;


while (!(UCSRA & (1<<RXC)));

PORTB = UDR;
}
----------------------------------------------------------------
Danke!

von Karl H. (kbuchegg)


Lesenswert?

Und wieder die übliche Frage:
Was funktioniert denn nicht?

('funktioniert nicht' ist keine vernünftige Fehlermeldung)


PS: Du solltest dir wirklich angewöhnen, solche
Dinge in Schleifen zu packen.

  while( 1 ) {
    // warte auf ein Zeichen
    while (!(UCSRA & (1<<RXC)));

    // und am Port das Bitmuster ausgeben
    PORTB = UDR;
  }
}


PS2: Einrückungen sind kein Luxus! Sie helfen die
Struktur eines Programmes schneller zu erfassen.

von M@cFreak (Gast)


Lesenswert?

hm ich kann schon garnichts auf mein Terminal schreiben......Muss ich 
die RS232 fürs Terminal weiterhin verwenden?

von Karl H. (kbuchegg)


Lesenswert?

M@cFreak wrote:
> hm ich kann schon garnichts auf mein Terminal schreiben.

Das ist bei Hyperterminal normal.
Da ist standardmässig das 'lokale Echo' ausgeschaltet.
Das heist: Du siehst nicht was du tippst.
Das heist aber nicht, dass die Zeichen nicht rausgehen.

Die Zeichen gehen sehr wohl raus. Das Standardverfahren
ist: Die Zeichen gehen raus und der Empfänger schickt
die empfangenenn Zeichen sofort wieder zurück. Und erst
dann zeigt das Terminal sie an.
Das hat den Vorteil, dass man eine unterbrochene Verbindung
sofort erkennt.

Man kann allerdings auf den meisten Terminals auch ein
sog. 'lokales Echo' einschalten. Dann schreibt das Terminal
mit, was es so rausgeschickt hat.

von M@cFreak (Gast)


Lesenswert?

ja, aber es leuchten trotzdem keine LEDs, nachdem ich etwas eingegeben 
habe. Habe auch "local Echo" aktiviert

von Karl H. (kbuchegg)


Lesenswert?

Moment:
Du hast 'lokal Echo' aktiviert und siehst immer noch nicht
was du tippst?
Ja: Schalte das Hardwarehandshaking im Hyperterminal aus.

von M@cFreak (Gast)


Lesenswert?

Ich sehe schon, was ich schreibe, aber es kommt anscheinend nicht beim 
µC an, da keine LEDs leuchten. Wird wohl noch ein Fehler in der Software 
sein?!

von Karl H. (kbuchegg)


Lesenswert?

Probier das mal aus:
1
#include <avr/io.h>
2
#include <stdint.h>
3
4
#ifndef F_CPU
5
#define F_CPU 8000000          /* Oszillator-Frequenz in Hz */
6
#endif
7
 
8
// Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)
9
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
10
 
11
#define UART_BAUD_RATE 9600
12
13
int main(void)
14
{
15
  char c;
16
17
  UCSRB |= ( 1 << TXEN ) | ( 1 << RXEN );
18
  UCSRC |= ( 1 << URSEL) | ( 3<<UCSZ0 );    // Asynchron 8N1
19
20
  // Baudrate setzen
21
  UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 );
22
  UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU );
23
24
  while( 1 ) {
25
    // warte auf ein Zeichen
26
    while (!(UCSRA & (1<<RXC)))
27
      ;
28
29
    // das Zeichen holen
30
    c = UDR;
31
32
    // warten bis die UART 'fertig' meldet
33
    while (!(UCSRA & (1<<UDRE)))
34
      ;
35
36
    // und das Zeichen zurückschicken
37
    UDR = c;
38
  }
39
}

  

von M@cFreak (Gast)


Lesenswert?

Aber was ist dann in meinem Code anders als in deinem???

von M@cFreak (Gast)


Lesenswert?

Es müsste doch genau so funktionieren ...

von Stefan (Gast)


Lesenswert?

Tut er aber anscheinend nicht. Und das kann verschiedene Ursachen haben.

Der Vorschlag von Karl heinz (1) läuft darauf hinaus, einen anderen - 
bekannt zuverlässigen - Code einzusetzen, um die grundsätzliche Funktion 
der Entwicklungsumgebung zu testen.

Ich sehe als Schwachpunkt deines Codes (2) die mehrfach angesprochene 
fehlende Endlosschleife. Dein Code ist ruckizucki fertig und main() wird 
verlassen.

U.U. so schnell, dass PORTB zwar gesetzt wird aber der µC sich einen 
Mückenwimpernschlag später schon in einen undefinierten Zustand verrannt 
hat.

(1) Beitrag "Re: UART-Fehler :("
(2) Beitrag "Re: UART-Fehler :("

von Karl H. (kbuchegg)


Lesenswert?

Stefan wrote:
> Tut er aber anscheinend nicht. Und das kann verschiedene Ursachen haben.
>

Ich denke mal die Hauptursache ist das fehlende

  UCSRC |= ( 1 << URSEL) | ( 3<<UCSZ0 );    // Asynchron 8N1


aber um ehrlich zu sein bin ich jetzt zu faul im
Datenblatt nachzusehen, wofür die UCSZ0 und UCSZ1 Bits
gut sind (Was URSEL macht weiss ich auswendig :-)

Das ist meine Standard-UART-Initialisierung. Wenn ich eine
UART brauche, dann hole ich mir den Code mit Cut&Paste
in das aktuelle Projekt und fertig. Von dem Code weiss
ich dass er funktioniert und ich sehe wirklich keinen
Sinn darin, jedesmal wieder für dieselbe Funktionalität
die Bits aus dem Datenblatt raussuchen zu müssen.

Aus demselben Grund bin ich auch gegen die Zuweisung von 51
an das Baudratenregister allergisch. Ich setzte einfach
die Formel mittels Cut&Paste ein, achte darauf dass der
F_CPU Wert stimmt und mach ein #define für die gewünschte
Baudrate.
Ich mach mir doch nicht die Finger mit schnöden
Taschenrechnertricks ( FOSC/16/BAUD-1 selber ausrechnen, igitt)
oder raussuchen aus Tabellen schmutzig.
Diese 'Drecksarbeit' überlasse ich dem Compiler. Ich kümmere
mich lieber darum wo die Daten herkommen, die über
die UART müssen.

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.