ATmega8 Frequenz stimmt nicht

Gast #1902740
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.
Angehängte Dateien:
Gast #1902845
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;

}
Gast #1902904
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.
#1902916
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.
Gast #1920884
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;

}
Persönliche Seite #1920910
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.
Gast #1920922
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.
#1920924
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.
#1920948
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"
#1920972
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.
#1920981
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.
#1921023
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.

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