Forum: Mikrocontroller und Digitale Elektronik interner Takt ATMega32


von chris (Gast)


Lesenswert?

hi,
benutze dem ATMega32 mit internem Takt ( 8 Mhz )
jetzt möchte ich per serieller Schnittstelle Daten an den PC senden.
Ist der interne Takt dazu gut genug ? ....
ich hab ein Program das für den ATMega128 funktioniert,
wenn ich das änder für den ATMega32 funktionierts nicht :-( ...
hier mal nen ausschnitt ...

#include "printf.h"
   12
   13 //Installation der Seriellen Schnittstelle
   14 void IOInit (void)
   15 {
   16   // Enable TXEN in Register UCR (TX-Data Enable)
   17   UCSRB=(1 << TXEN);
   18   // set baudrate divisor
   19   UBRRL=(CPU_CLOCK / (BAUD_RATE * 16L) - 1);
   20 }
   21
   22 //
   23 // this function is used inside the standard printf function and
   24 // has to be implemented to get access to the serial port via
printf
   25 //
   26 int uart_putchar (char c)
   27 {
   28   if (c == '\n') uart_putchar('\r');
   29   // wait until character is transmitted
   30   loop_until_bit_is_set(UCSRA, UDRE);
   31   UDR = c;
   32   return 0;
   33 }
   34


    I A  main.h (c)
                                          Row 1    Col 1    1:16  Ctrl-K
H for help
    1 #ifndef _MAIN_H
    2 #define _MAIN_H
    3
    4 #include <avr/io.h>
    5
    6 #define BUTTON_PORT  PORTC
    7 #define BUTTON_DDR   DDRC
    8 #define BUTTON_PIN   PINC
    9 #define BATT_LOW     4
   10 #define BUTTON_0     5
   11 #define BUTTON_1     6
   12 #define BUTTON_2     7
   13
   14 #define LED_PORT     PORTC
   15 #define LED_DIR      DDRC
   16 #define LED_GREEN    0
   17 #define LED_RED      1
   18
   19 #define CPU_CLOCK    7372800
   20
   21 #define CPU_MICROSEC(a) ((a)*CPU_CLOCK/7000000)
   22 #define CPU_MILLISEC(a) ((a)*CPU_CLOCK/7000)
   23 #define CPU_SEC(a)      ((a)*CPU_CLOCK/7)
   24
   25 #define nop()  _asm__ __volatile_ ("nop" ::)
   26
   27 /* nop/1, subi/1, sbc/1, sbc/1, sbc/1, brcc/2 -> 7 clocks */
   28 static inline void cpu_delay(unsigned long int delay) {
   29   while ( delay-- != 0) nop();
   30 }
   31
   32 #endif
   33

bin für Tipps und Hinweise dankbar ...
  chris

von Gunter (Gast)


Lesenswert?

Hi,

hast Du auch das Calibration Byte für 8MHz gesetzt ?

Gunter

von chris (Gast)


Lesenswert?

nein,
aber wenn ich mit uisp -dprog=stk200 -dpart=atmega32 --rd_fuses mache
dann steht da:

Fuse Low Byte      = 0xe3
Fuse High Byte     = 0xd9
Fuse Extended Byte = 0xff
Calibration Byte   = 0xb4  --  Read Only
Lock Bits          = 0xff
    BLB12 -> 1
    BLB11 -> 1
    BLB02 -> 1
    BLB01 -> 1
      LB2 -> 1
      LB1 -> 1
also das mein calibrationbyte read only ist !
also muss ich das calibration byte auf 0x003 setzen für 8 Mhz ?
chris
PS : wenn ich das richtig verstanden habe wird später der wert von
meinem Calib byte ind OSCAL gelesen ...
da gibts ne tabelle wo drinn steht
7F ist 75-150 % meines taktes ?is dis schwankung net bsichen groß ?

von pebisoft (Gast)


Lesenswert?

hier ist ein code zum senden und empfangen.
zum empfangen die chars muss du noch selber sondieren, jenachdem was du
damit machen tust. baudrate kannste noch selber ändern.
ist für winavr-c.
mfg pebisoft

#define READ  1
#define WRITE 2

#define USART_BAUD_RATE   19200
#define USART_BAUD_SELECT   (F_CPU/(USART_BAUD_RATE*16l)-1)

volatile char buchstabe;

SIGNAL(SIG_UART_RECV)
{
  buchstabe=UDR;
}

void usart_init(int Enable, int Interupts)
{
  if (Enable & READ)             UCSRB = (1<<RXEN);
  if (Enable & WRITE)            UCSRB |= (1<<TXEN);

    if (Interupts & READ)             UCSRB |= (1<<RXCIE);
  if (Interupts & WRITE)            UCSRB |= (1<<TXCIE);
    UBRRL = (unsigned char)       USART_BAUD_SELECT;
}

void usart_writeChar(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE))) {}
    UDR = c;
    while(!(UCSRA & (1<<TXC))) {}
}

void usart_writeString(unsigned char *string) {
    while (!(UCSRA & (1<<UDRE))) {}
  while ( *string)
    usart_writeChar(*string++);
}

das kommt in die main() :

sei();
usart_init( (READ + WRITE) , READ);
usart_writeString(string);
usart_writeString("\n\r");

von Gunter (Gast)


Lesenswert?

Hallo Chris,

ich vermute, dein ISP zeigt das Cal.Byte für 1 MHz an.
Es gibt aber noch 3 weitere (für 2,4,8 MHz).
Dies Bytes werden vom Hersteller (neben den Signatur
Bytes) in einen eigenen Adreßraum (read-only) geschrieben.
Bei einem Reset wird automatisch das 1MHz Cal.Byte gelesen
und nach OSCCAL geschrieben.
Dann ist bei 25 °C und 5,0V (!!!) +/- 3% garantiert, was
gerade so für die ser. Schnittstelle reichten würde.
Du mußt also gleich am Anfang Deines Programms OSCCAL mit
dem Wert des 8 MHz Cal.Byte überschreiben.

Sicherer bist Du, wenn Du den korrekten Wert selber ermittelst.
Der ist sicher in der Nähe des angezeigten Wertes (0xb4).
Vielleicht +/- 5,6,7,8 oder so.
Dazu gibt es App. Notes oder Du überprüfst die Baudrate mit
eine Scope und drehst solange an OSCCAL bis die Baudrate stimmt.

hth
Gunter

von chris (Gast)


Lesenswert?

sorry für die blöde Frage,
geht das so ?

unsigned int &i =0x03;   // eine Variable für eine Adresse anlegen
                             Aresse 0x03 ind die Variable
reinschreiben
OSCCAL= *i>>8;           // mit *auf den Inhalt der Adresse zugreifen
                            den Inhalt des High Byte in OSCCAL
schreiben

chris

von Gunter (Gast)


Lesenswert?

Hi,

die Cal. und Sig. Byte können nur von einem Programmer
gelesen werden (nicht vom Controller zur Laufzeit).

Gunter

von chris (Gast)


Lesenswert?

hallo Gunter,
ich hab meinem Controller mit einem stk200 Dongle (isp) programmiert
und per uisp -dpart=atmega32 -dprog=stk200 rom.hex mein Programm
übertragen.
bei uisp -h finde ich nichts von Calibration Byte lesen.
Die frage ist kann ich das Calibration Byte überhaupt mit meinem Aufban
auslesen ? ... benutze Linux ? ..
  danke
   chris

von Gunter (Gast)


Lesenswert?

Hi Chris,

da kann ich Dir leider nicht helfen -
weder mit Linux noch mit C noch mit Deinem ISP.

Ich hatte mir damals eine kleine Testschaltung gebaut,
in einer Schleife immer 0x55 oder 0xAA gesendet, die
Baudrate mit dem Scope ausgemessen und dann das Cal.Byte
leicht geändert.
Damit kommt man dann auf 1% Genauigkeit.
Die ser. SS verlangt 3%, sodaß man dann noch Reserve für
Temperaturdrift hat.

Gunter

von Christian Zietz (Gast)


Lesenswert?

In dem Sourcecode des ersten Postings ist CPU_CLOCK als 7372800
definiert. Definierst Du das noch irgendwo um? Sonst stimmt schon die
Berechnung von UBBRL nicht.

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.