Forum: Mikrocontroller und Digitale Elektronik ATmega8 Frequenz stimmt nicht


von Franki C. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute!

Ich arbeite mit dem USART auf dem ATMEGA8 und habe das Starterkit aus 
dem Forum 
http://www.eproo.de/index.php?module=artikel&action=artikel&id=108

Jetzt muss ich ja für eine genaue Frequenz den externen Quarz nutzen.
Habe dazu in AVR Studio unter Tools->Program AVR->Auto Connect unter 
Fuses folgende Einstellungen gemacht die auf dem Bild zu sehen sind. 
Habe auch eine Delay Time von 0 und 4 ms ausprobiert, auch mit BODEN und 
ohne auch mit CKOPT und ohne, aber der ATMEGA arbeitet immer mit einer 
Frequenz von ungefähr 1 MHz. Habe alles eigentlich so eingestellt wie es 
im Datenblatt und im Forum beschrieben wird. Wenn ich die Fuses auslese 
bleiben die Einstellungen auch drin.

von Franki C. (Gast)


Lesenswert?

Ach ja der Quarz schwingt, hab es nachgemessen...

von Floh (Gast)


Lesenswert?

Franki C. schrieb:
> aber der ATMEGA arbeitet immer mit einer
> Frequenz von ungefähr 1 MHz

Mit welcher Frequenz soll er arbeiten?
Wie hast du die Frequenz gemessen?
:-)

von Franki C. (Gast)


Lesenswert?

Also am im Starterkit ist ein 8 MHz Quarz angeschlossen an Pin 9 un 10, 
da gehört er auch hin und die möchte ich nutzen. Gemessen habe ich das 
so, dass ich ein einfaches Assemblerprogramm geschrieben habe, das am 
pin 0 von Port B ein Ein/Auschalten realisiert.Dabei jeden Zyklus 
beachtet und dadurch am Oszilloskop die Frequenz abgemessen. Bin knapp 
bei einem MHz. Wenn ich die 1 MHz in meinem USART einstelle stimmt dann 
auch die Baudrate.




#define FOSC 1322751 // Clock Speed
#define BAUD 9600
#define MYUBRR ((FOSC+(BAUD * 8))/(16*BAUD))-1

#include <avr/io.h>
#include<stdio.h>
#include <util/delay.h>

unsigned char USART_Receive( void );
void USART_Init( unsigned int);
void USART_Transmit( unsigned char);


void main( void ){

unsigned char a = 'U';

  PORTC = (0<<PC3);
  PORTC = (0<<PC2);
  USART_Init (MYUBRR);


  do{
    USART_Transmit(a);

  }while(1);



}

void USART_Init( unsigned int ubrr){

  /* Set baud rate */
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  /* Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 2stop bit */
  UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
  return(0);

}


void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = data;
}

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) );
//PORTB = UDR;
/* Get and return received data from buffer */
return UDR;

}

von MWS (Gast)


Lesenswert?

> Gemessen habe ich das so, dass ich ein einfaches Assemblerprogramm
> geschrieben habe

Schönes Assemblerprogramm, und sogar in C :D

Für einen einfachen Test per Oszi würde man einen Portpin direkt 
toggeln.
Den µC Clock wie gezeigt über das UART ermitteln zu wollen ist doch 
kompletter Unsinn.

von Karl H. (kbuchegg)


Lesenswert?

Franki C. schrieb:

> pin 0 von Port B ein Ein/Auschalten realisiert.Dabei jeden Zyklus
> beachtet und dadurch am Oszilloskop die Frequenz abgemessen. Bin knapp
> bei einem MHz. Wenn ich die 1 MHz in meinem USART einstelle stimmt dann
> auch die Baudrate.


Das hättest du auch einfacher haben können :-)

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

Hast du irgendwo eine LED drann hängen?
Dann pass dieses Programm an deine Gegebenheiten an.
1
  /*
2
  Testprogramm für CPU Takt
3
  Hier die vermeintliche Taktrate des µC eintragen
4
  */
5
  #define F_CPU 8000000
6
 
7
  #include <avr/io.h>
8
  #include <util/delay.h>
9
 
10
  /*
11
     Hier die tatsächlich verwendeten Parameter angeben
12
  */
13
 
14
  #define LED_PORT    PORTB
15
  #define LED_DDR     DDRB
16
  #define LED_PIN     PB0
17
 
18
  int main()
19
  {
20
    LED_DDR |= (1<<LED_PIN);
21
 
22
    while( 1 ) {
23
      LED_PORT ^= (1<<LED_PIN);
24
      _delay_ms(1000);
25
    }
26
  }

Entweder die LED ist 1 Sekunde an bzw. aus oder sie ist es nicht. Wenn 
du für F_CPU 8Mhz eingetragen hast und dein µC auch tatsächlich mit dem 
8Mhz Quarz arbeitet, dann blinkt die LED auch mit 1 Sekunde. Arbeitet 
dein µC im Wirklichkeit mit 1Mhz (obowhl es eigentlich 8 sein sollten 
und du daher auch 8000000 eingetragen hast), dann ist die LED 8 Sekunden 
an bzw. aus. Den Unterschied sieht man mit freiem Auge.

Es gibt noch einen Test. Zieh den Quarz ab. Das Blinken muss schlagartig 
aufhören, weil der µC keinen Takt mehr hat.

Solange du beide Tests nicht 100% zufriedenstellend absolviert hast, 
brauchst du gar nicht weiter mit der UART probieren. Die beiden Tests 
sind die Grundlage.

von Franki C. (Gast)


Lesenswert?

@MWS das ist auch nicht mein Assemblerprogramm.


Ok hab es ausprobiert, leuchtet 8 sec.

von Karl H. (kbuchegg)


Lesenswert?

Franki C. schrieb:
> @MWS das ist auch nicht mein Assemblerprogramm.
>
>
> Ok hab es ausprobiert, leuchtet 8 sec.

Dann läuft dein µC mit 1Mhz und du musst rausfinden warum.

von Franki C. (Gast)


Lesenswert?

Hallo!

Habe jetzt mal einen anderen µController ausprobiert (ATMEGA8A) ist ja 
eigentlich fast der gleiche... Das mit der LED klappt jetzt also bei 
F_CPU 73728 blinkt die LED 1 Sekunde an und aus. Aber wenn ich das USART 
Programm laufen lasse messen ich mit dem Osziloskop an Pin3 (TxD) für 
eine high Flanke 650µs, aber bei 9600 Baud müsste ich doch 1/9600= 104µs 
messen.


#define FOSC 7372800 // Clock Speed
#define BAUD 9600
#define MYUBRR ((FOSC+(BAUD * 8))/(16*BAUD))-1

#include <avr/io.h>
#include<stdio.h>
#include <util/delay.h>

unsigned char USART_Receive( void );
void USART_Init( unsigned int);
void USART_Transmit( unsigned char);


void main( void ){

unsigned char a = 'U';

  PORTC = (0<<PC3);
  PORTC = (0<<PC2);
  USART_Init (MYUBRR);


  do{
    USART_Transmit(a);

  }while(1);



}

void USART_Init( unsigned int ubrr){

  /* Set baud rate */
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  /* Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 2stop bit */
  UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
  return(0);

}


void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = data;
}

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) );
//PORTB = UDR;
/* Get and return received data from buffer */
return UDR;

}

von Peter (Gast)


Lesenswert?

define FOSC 7372800

define F_CPU 73728

was hast du denn für ein Quarz angeschlossen? Ich dachte es war ein 8Mhz 
Quarz.

von Franki C. (Gast)


Lesenswert?

Ja es ist ein 8 MHz Quarz, aber im Tutorial stand man sollte die Exatkte 
Frequenz einstellen, so steht die auch im Datenblatt.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

#define FOSC 7372800UL // Clock Speed
                    ^^
#define BAUD 9600UL
                 ^^

von Michael H. (michael_h45)


Lesenswert?

8MHz ist die exakte Frequenz.

von Peter (Gast)


Lesenswert?

Franki C. schrieb:
> Ja es ist ein 8 MHz Quarz, aber im Tutorial stand man sollte die Exatkte
> Frequenz einstellen, so steht die auch im Datenblatt.

die Extrakte Frequenz bei einem 8Mhz Quarz ist aber 8.000.000 Mhz.

von Franki C. (Gast)


Lesenswert?

Was bedeutet denn das UL in 9600UL. Ist dies wichtig?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ist

define F_CPU 73728

ein Schreibfehler und zwei Nullen fehlen? Mach einfach ein Foto des 
Quarzes mit der beschriftung. Bitte Bildformate beachten.

von Michael H. (michael_h45)


Lesenswert?

Franki C. schrieb:
> Was bedeutet denn das UL in 9600UL. Ist dies wichtig?
lass es weg.

von Michael H. (michael_h45)


Lesenswert?

Stefan B. schrieb:
> ein Schreibfehler und zwei Nullen fehlen? Mach einfach ein Foto des
> Quarzes mit der beschriftung. Bitte Bildformate beachten.
jedem hier außer dir ist klar, was hier los ist...

von Franki C. (Gast)


Lesenswert?

WOW!!! Scheint als wäre so ein UL wichtiger als man denkt ;-)
Vielen Dank für die Hilfe!!

von Aldinator (Gast)


Lesenswert?

Schon die CLKDIV8-Fuse kontrolliert? Die macht ganz fix aus einem 8MHz 
Quarz 1MHz F_CPU.

von Michael H. (michael_h45)


Lesenswert?

hat ein mega8 nicht

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Bedeutung des UL kannst du in jedem C-Buch in den ersten Kapiteln 
nachlesen ;-)

Es gibt an, dass die damit ausgezeichnete Konstante unsigned (ohne 
Vorzeichen) und long ist.

Die Kennzeichnung ist wichtig damit die folgende Berechnung

#define MYUBRR ((FOSC+(BAUD * 8))/(16*BAUD))-1

mit dem entsprechenden Wertebereich berechnet wird, statt wie üblich mit 
int Werten. Dadurch lassen sich Überläufe im Wertebereich vermeiden.

von Michael H. (michael_h45)


Lesenswert?

Franki C. schrieb:
> WOW!!! Scheint als wäre so ein UL wichtiger als man denkt ;-)
das is jetz zufall und funktioniert vmtl wegen eines überlaufs.

dein eigentlicher fehler ist nicht behoben.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Michael H. schrieb:

> Stefan B. schrieb:
>> ein Schreibfehler und zwei Nullen fehlen? Mach einfach ein Foto des
>> Quarzes mit der beschriftung. Bitte Bildformate beachten.
> jedem hier außer dir ist klar, was hier los ist...

Ich wünsche dir, dass dein Tag noch besser wird als jetzt, lieber 
Michael.

von Franki C. (Gast)


Lesenswert?

Achso, natürlich kenn ich die Bezeichnung unsigned long hätte nur nicht 
gedacht das es in diesem Fall eine Bedeutung hat, da im Datenblatt 
leider nichts davon stand.
@Michael H.:

Habe ich noch einen Fehler? Also falls du die 8Mhz meinst die habe ich 
natürlich jetzt eingestellt auf 8000000.

von Michael H. (michael_h45)


Lesenswert?

Franki C. schrieb:
> da im Datenblatt
> leider nichts davon stand.
Das ist ja auch Compiler-spezifisch und hat mit dem Controller selbst 
nichts am Hut. Der kennt nichts außer 8 bit =)

> Habe ich noch einen Fehler? Also falls du die 8Mhz meinst die habe ich
> natürlich jetzt eingestellt auf 8000000.
Alles klar - ja, das war der eigentliche Fehler.
Die Berechnung klappt auch bestens ohne die UL Tags.

von Karl H. (kbuchegg)


Lesenswert?

Michael H. schrieb:

>> Habe ich noch einen Fehler? Also falls du die 8Mhz meinst die habe ich
>> natürlich jetzt eingestellt auf 8000000.
> Alles klar - ja, das war der eigentliche Fehler.
> Die Berechnung klappt auch bestens ohne die UL Tags.

?

#define BAUD 9600
#define MYUBRR ((FOSC+(BAUD * 8))/(16*BAUD))-1

Das klappt auf einem 16-Bit int System nicht wirklich.
9600 * 8  gibt einen Overflow

Bei 8000000 kann man darüber diskutieren, ob der Suffix UL sinnvoll ist 
oder nicht. Durch das UL gewinnt man auf jeden Fall noch ein Bit, 
welches im schlimmsten Fall die Overflows ein wenig hinauszögert. Bei 
den 9600 ist es aber wichtig, dass der Suffix vorhanden ist.

Da der Suffix aber auch nicht schadet, sollte deine Empfehlung sein 
"Mach sie" und nicht "Lass sie weg"

von Michael H. (michael_h45)


Lesenswert?

Karl heinz Buchegger schrieb:
>> Die Berechnung klappt auch bestens ohne die UL Tags.
> ?
Ich habs grade nochmal ausprobiert. Es geht.
Muss es natürlich nicht bei jedem Compiler, insofern...

> Da der Suffix aber auch nicht schadet, sollte deine Empfehlung sein
> "Mach sie" und nicht "Lass sie weg"
...hast du da völlig Recht.



Was mich einfach störte, war das hier:

> define F_CPU 73728
Offensichtlich völlig verkehrt.
Die Antwort darauf...
> #define FOSC 7372800UL // Clock Speed
> #define BAUD 9600UL
...was total am Thema vorbeigeht.

Ja, die Casts sind generell schon richtig; aber nur einfach so als 
Antwort darauf ohne jeglichen Text dazu ist es einfach unbrauchbar.
Sieht man auch daran, dass Franki es für die Lösung hielt, obwohl es 
ganz woanders haperte.

von Karl H. (kbuchegg)


Lesenswert?

Michael H. schrieb:
> Karl heinz Buchegger schrieb:
>>> Die Berechnung klappt auch bestens ohne die UL Tags.
>> ?
> Ich habs grade nochmal ausprobiert. Es geht.

Höchstens zufällig

9600 * 8 ergibt 76800 und ist damit ausserhalb des 16-Bit int Bereiches.
Du hast damit einen Overflow und anstelle das

  FOSC+(BAUD * 8))

korrekterweise 8076800 ergibt, wird dann für diesen Term  8012265 
ausgerechnet.

Dasselbe passiert dann nochmal bei

  16*BAUD

anstelle von korrekten 153600 setzt der Compiler dann hier 23708 ein.

> Muss es natürlich nicht bei jedem Compiler, insofern...

Wenn es ein 16-Bit Compiler ist, dann ja.
Das einzige was an dem Beispiel tatsächlich Compilerabhängig ist, ist 
die Fragestellung wie groß den ein int ist. Das ist aber auch schon das 
einzige was hier frei gestellt ist, denn anders als du das hier 
suggerierst, kann sich der Compiler die Berechnung hier keineswegs 
irgendwie aus den Fingern saugen.

> Was mich einfach störte, war das hier:
>
>> define F_CPU 73728
> Offensichtlich völlig verkehrt.

Da hast du recht

> Die Antwort darauf...
>> #define FOSC 7372800UL // Clock Speed
>> #define BAUD 9600UL
> ...was total am Thema vorbeigeht.

Sie korrigierte gleich 2 potentielle Probleme auf einmal. Aber die 
Lösung ist nicht, dass man das UL weglassen kann.
Wie sooft greifen da mehrere Probleme ineinander.

von Michael H. (michael_h45)


Lesenswert?

Karl heinz Buchegger schrieb:
>> Die Antwort darauf...
>>> #define FOSC 7372800UL // Clock Speed
>>> #define BAUD 9600UL
>> ...was total am Thema vorbeigeht.

> Sie korrigierte gleich 2 potentielle Probleme auf einmal. Aber die
Bei einem 8MHz Quarz?
F_CPU ist noch "verkehrter" gesetzt und findet gar keine weitere 
Beachtung.

> Lösung ist nicht, dass man das UL weglassen kann.
Richtig, hab ich eingestanden.

von Michael H. (michael_h45)


Lesenswert?

Michael H. schrieb:
> Ich habs grade nochmal ausprobiert.
Und dabei natürlich das L bei meiner 16 übersehen...
Okay, okay, ich caste auch...

Nichtsdestotrotz ist
> #define FOSC 7372800UL // Clock Speed
bei einem 8MHz Quarz Unsinn. Da kann es noch so schön 
nichtvorzeichenbehaftet und 32bit breit sein.

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.