Forum: Mikrocontroller und Digitale Elektronik F_CPU bei atmega644 Standardeinstellungen


von pedde (Gast)


Lesenswert?

Hallo alle miteinander,

ich wollte fragen, welchen wert F_CPU bei meinem atmega644 hat, wenn das 
Fuse bit auf Int. RC Osc gesetzt ist? Ich dachte es wäre 1000000. 
Allerdings empfange ich mit hterm nur falsche zeichen, wenn ich von 
1000000 ausgehe.

Viele Grüße
Pedde

von Cyblord -. (cyblord)


Lesenswert?

Standardantwort hier: Steht im Datenblatt. Soll ich für dich nachgucken 
oder wie?

Bei vielen AVRs ist der Int. Osc eingestellt mit 8 MHz und die CHKDIV8 
Fuse gesetzt, so dass er mit 1 MHz läuft.
Also wäre 1.000.000 richtig.

gruß cyblord

von pedde (Gast)


Lesenswert?

Hi,

ja das habe ich im Datenblatt gelesen, ich war mir nur unsicher, da die 
Kommunikation nicht funktioniert.

Stimmt dann was an meiner initilisierung nicht?
Hier mal ein Code-Ausschnitt:
1
#ifndef F_CPU
2
#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
3
#define BAUD 115200
4
#endif
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include <util/setbaud.h>
8
9
10
...
11
12
  uart_init();
13
14
    while(1)
15
    {
16
    _delay_ms(8000); //delay
17
    USART_Transmit(124);  
18
    }
19
20
...
21
22
23
24
25
void uart_init()   
26
{
27
   UBRR0H = UBRRH_VALUE;
28
   UBRR0L = UBRRL_VALUE;
29
30
#if USE_2X
31
   /* U2X-Modus erforderlich */
32
   UCSR0A |= (1 << U2X0);
33
#else
34
   /* U2X-Modus nicht erforderlich */
35
   UCSR0A &= ~(1 << U2X0);
36
#endif
37
38
  /* Enable receiver and transmitter*/
39
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
40
  /* Set frame format: 8data, 2stop bit*/
41
  UCSR0C = (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
42
}
43
44
45
void USART_Transmit( unsigned char data )
46
{
47
  PORTC=0<<PC0;    //RTS Signal (auf low ziehen
48
  /* Wait for empty transmit buffer*/
49
  while( !( UCSR0A & (1<<UDRE0)) )
50
  ;
51
  /* Put data into buffer, sends the data*/
52
  while (PINC & (1<<PINC1));  // WARTEN AUF CTS SIGNAL
53
  UDR0 = data;
54
  PORTC=1<<PC0; 
55
}

von Karl H. (kbuchegg)


Lesenswert?

pedde schrieb:

> Allerdings empfange ich mit hterm nur falsche zeichen, wenn ich von

Die 1Mhz sind nicht besonders genau. Besser wäre ein Quarz.
Aber ok. Welches Zeichen siehst du denn im Hterm?

>
1
> USART_Transmit(124); 
2
>

Das Zeichen mit dem ASCII Code 124 ist ein '|'. Du kannst dir natürlich 
selbst (und deinem Leser) das Leben schwerer machen als es sein muss, 
aber einfacher ist es, wenn du davon Abstand nimmst, die ASCII Codes 
(noch dazu dezimal) selber hinzuschreiben, sondern ganz einfach
1
   USART_Transmit( 'a' );
schreibst. Dann kennt sich jeder aus, was in HTerm sichtbar sein müsste, 
auch ohne zuerst eine ASCII Tabelle konsultieren zu müssen.

von pedde (Gast)


Lesenswert?

188 als dezimal, sprich: 10111100 bzw. 0xBC

von pedde (Gast)


Lesenswert?

hab den code jetzt mal auf USART_Transmit( 'a' );  geändert,
nun empfang ich 0xA1, was allerdingsa auch das falsche zeichen ist.

von holger (Gast)


Lesenswert?

>Die 1Mhz sind nicht besonders genau. Besser wäre ein Quarz.

Selbst mit Quarz beträgt der Baudratenfehler 8.5%.
Sprich Baudrate geht nicht mit 1MHz.

von pedde (Gast)


Lesenswert?

ich hab schon andere baudraten (z.B. 9600 oder 2400) probiert, erhalte 
aber trotzdem immer einen fehler, oder funktioniert die uart 
kommunikation bei 1mhz mit keiner baudrate?

von pedde (Gast)


Lesenswert?

könnte es auch an dem FTDI FT232RL liegen, dass die Daten falsch 
ankommen?

von Karl H. (kbuchegg)


Lesenswert?

pedde schrieb:
> 188 als dezimal, sprich: 10111100 bzw. 0xBC
1
188_dez     10111100
2
124_dez     01111100


Hmm. Interessant.
Da die Übertragung mit dem LSB beginnt, sieht es danach aus, als ob 
deine Baudrate (abegeleitet aus der F_CPU) ein klein wenig zu viel 
daneben ist.

von holger (Gast)


Lesenswert?

>könnte es auch an dem FTDI FT232RL liegen, dass die Daten falsch
>ankommen?

Nee, an falscher Baudrate liegt das. Der UART selbst
arbeitet doch schon, sonst würdest du gar keine Zeichen sehen.

Zeig mal den Rest von deinem Programm. Und lass mal ne LED
im Sekundentakt blinken. Wer weiss ob deine F_CPU auch stimmt
bzw deine Fuses richtig gesetzt sind.

von pedde (Gast)


Lesenswert?

Hier mal mein gesamter code. Ist allerdings noch ein bisschen 
unstrukturiert, da ich erst angefangen hae:
1
/*
2
 * DAC.c
3
 *
4
 * Created: 29.08.2013 20:12:10
5
 *  Author: pedde
6
 */ 
7
8
9
#include <avr/io.h>
10
#ifndef F_CPU
11
#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
12
#define BAUD 9600
13
#endif
14
#include <util/delay.h>
15
#include <avr/interrupt.h>
16
#include <util/setbaud.h>
17
18
#define SAITE1 0
19
#define SAITE2 1
20
#define SAITE3 2
21
#define SAITE4 3
22
#define SAITE5 4
23
#define SAITE6 5
24
25
26
27
28
#define I_BIT 7
29
#define CHANNEL_SELECT 31
30
31
32
33
unsigned int Messergebnisse [6];
34
35
void USART_Transmit( unsigned char data );
36
void startSending();
37
void USART_Init( unsigned int baud );
38
void uart_init();
39
40
int main(void)
41
{
42
  
43
  
44
    DDRC=0; //all pins of PORTB declared as output
45
    DDRC=(0<<PC7|0<<PC6|0<<PC5|0<<PC4|0<<PC3|0<<PC2|0<<PC1|1<<PC0);  // Port0 ist ausgang
46
    PORTC=1<<PC0;
47
    //PORTD=(0<<PD0|1<<PD1);
48
  
49
  /* 
50
    ADC-Register einrichten für Sechskanäle
51
  
52
  */
53
  
54
//  ADCSRB=(0<<ADTS0);  // Trigger select bits ADTS2 ADTS1 ADTS0 Trigger Source
55
            //0 0 0 Free Running mode
56
//  ADCSRB=(0<<ADTS1);  // Trigger select bits
57
//  ADCSRB=(0<<ADTS2);  // Trigger select bits
58
  
59
  ADCSRA|=(1<<ADATE);
60
  
61
  ADMUX |= 1<<REFS0|0<<REFS1; // Auswahl der Referenzspg. AVCC with external capacitor at AREF pin
62
  
63
  ADMUX |= SAITE1;      // Kanalauswahl (Saite1 -> Kanal0)
64
  
65
  
66
67
  
68
  ADCSRA |= 1<<ADIE; // Interrupt einschalten
69
  DIDR0 = 255; //When this bit is written logic one, the digital input buffer on the corresponding ADC pin is dis-abled.
70
  
71
  //SREG |= 1<<I_BIT;  // Generelles zulassen von interupts
72
  
73
    
74
    ADCSRA |= (1<<ADEN);    // ADC einschalten
75
    ADCSRA |=1<<ADSC;
76
  //ADCSRA |= 0<<ADPS0|0<<ADPS1|0<<ADPS2;  // Input clock für dac -> when zu schnell, dann schlecht
77
  
78
  
79
  /*
80
  
81
    UART
82
    
83
  */
84
  
85
  uart_init();
86
  
87
  
88
  
89
    while(1)
90
    {
91
92
93
    
94
    _delay_ms(8000); //delay
95
    USART_Transmit(127);
96
    
97
    }
98
}
99
100
ISR(ADC_vect) 
101
{
102
  
103
  
104
  // HIER WERDEN NOCH DIE SAITEN IMPLEMENTIERT
105
  unsigned int erg = ADCL|(ADCH<<8);
106
  
107
  unsigned char channel = ADMUX&CHANNEL_SELECT;
108
  switch(channel)
109
  {
110
  
111
    case SAITE1:
112
    Messergebnisse[0]=erg;
113
    ADMUX++;
114
    break;
115
    
116
    case SAITE2:
117
    Messergebnisse[1]=erg;
118
    ADMUX++;
119
    break;
120
    
121
    case SAITE3:
122
    Messergebnisse[2]=erg;
123
    ADMUX++;
124
    break;
125
    
126
    case SAITE4:
127
    Messergebnisse[3]=erg;
128
    ADMUX++;
129
    break;
130
    
131
    case SAITE5:
132
    Messergebnisse[4]=erg;
133
    ADMUX++;
134
    break;
135
    
136
    case SAITE6:
137
    Messergebnisse[5]=erg;
138
    ADMUX&=!(CHANNEL_SELECT);
139
    startSending();
140
    break;
141
    
142
    default:
143
    break;
144
  }  
145
}  
146
147
void USART_Transmit( unsigned char data )
148
{
149
  PORTC=0<<PC0;    //RTS Signal (auf low ziehen
150
  /* Wait for empty transmit buffer*/
151
  while( !( UCSR0A & (1<<UDRE0)) )
152
  ;
153
  /* Put data into buffer, sends the data*/
154
  while (PINC & (1<<PINC1));
155
  UDR0 = data;
156
  PORTC=1<<PC0;
157
}
158
159
void startSending()
160
{
161
  //TODO
162
  
163
}
164
165
166
167
void uart_init()   
168
{
169
   UBRR0H = UBRRH_VALUE;
170
   UBRR0L = UBRRL_VALUE;
171
   /* evtl. verkuerzt falls Register aufeinanderfolgen (vgl. Datenblatt)
172
      UBRR = UBRR_VALUE;
173
   */
174
  
175
#if USE_2X
176
   /* U2X-Modus erforderlich */
177
   UCSR0A |= (1 << U2X0);
178
#else
179
   /* U2X-Modus nicht erforderlich */
180
   UCSR0A &= ~(1 << U2X0);
181
#endif
182
  
183
  
184
  
185
  
186
  /* Enable receiver and transmitter*/
187
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
188
  /* Set frame format: 8data, 2stop bit*/
189
  UCSR0C = (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
190
}

von Karl H. (kbuchegg)


Lesenswert?

pedde schrieb:
> Hier mal mein gesamter code. Ist allerdings noch ein bisschen
> unstrukturiert, da ich erst angefangen hae:

Alles schön und gut.
Aber können wir uns darauf einigen, erst mal die UART losgelöst von 
allem anderen in Gang zu bringen?

Wenn 115kBaud bei 1Mhz zu viel Abweichung haben, dann musst du dir eben 
eine Baudrate suchen, bei der die Abweichung kleiner als 3% bleibt. 
Entweder rechnen oder im Datenblatt nachsehen - da gibt es Tabellen.

von holger (Gast)


Lesenswert?

UBRR0H = UBRRH_VALUE;
   UBRR0L = UBRRL_VALUE;


Ich sehe nirgends eine Definition von UBRRH_VALUE oder UBRRL_VALUE.
Der Code dürfte so gar nicht durch den Compiler gehen.

von Karl H. (kbuchegg)


Lesenswert?

holger schrieb:

> Ich sehe nirgends eine Definition von UBRRH_VALUE oder UBRRL_VALUE.
1
#include <util/setbaud.h>

von holger (Gast)


Lesenswert?

>> Ich sehe nirgends eine Definition von UBRRH_VALUE oder UBRRL_VALUE.
>
>#include <util/setbaud.h>

Ok, hab ich noch nie benutzt.

Für 9600 Baud muss dann ein

#define USE_2X    1

oben in den Code.

Oder besser 4800 Baud nehmen. Dann gehts mit und ohne USE_2X.

von holger (Gast)


Lesenswert?

>Für 9600 Baud muss dann ein
>
>#define USE_2X    1
>
>oben in den Code.

Bevor wieder jemand meckert: macht auch setbaud.h.

Ergo F_CPU ist falsch.

von Stefan (Gast)


Lesenswert?

Mit R/C Oszillator kann man sowieso nicht erwarten, dass die UART 
Schnittstelle funktioniert.

von holger (Gast)


Lesenswert?

>Mit R/C Oszillator kann man sowieso nicht erwarten, dass die UART
>Schnittstelle funktioniert.

Table 28-10. Calibration accuracy of internal RC oscillator.
Frequency VCC Temperature Calibration accuracy
Factory calibration 8.0MHz 3V 25°C ±10%

Also das bekommen andere Hersteller besser hin;)

von Cyblord -. (cyblord)


Lesenswert?

Stefan schrieb:
> Mit R/C Oszillator kann man sowieso nicht erwarten, dass die UART
> Schnittstelle funktioniert.

Aber in Praxis funktioniert das nunmal meist. Und wenns bei einem 
Anfänger nicht tut, liegs selten am ungenauen Osc.

gruß cyblord

von holger (Gast)


Lesenswert?

>Aber in Praxis funktioniert das nunmal meist. Und wenns bei einem
>Anfänger nicht tut, liegs selten am ungenauen Osc.

Dann bleibt wohl nur noch die blinkende LED und ein Osci
oder die Soundkarte um festzustellen wo sein F_CPU nun
wirklich liegt.

Eine fehlende GND Leitung wäre noch ne Möglichkeit.

Aber eigentlich passt es ja schon fasst:

188_dez     10111100
124_dez     01111100

>hab den code jetzt mal auf USART_Transmit( 'a' );  geändert,
>nun empfang ich 0xA1, was allerdingsa auch das falsche zeichen ist.

Das kleine a ist 0x61.

0xA1  10100001
0x61  01100001

Witzigerweise scheinen nur die ersten beiden Bits verdreht zu werden.

von pedde (Gast)


Lesenswert?

also ich hab nochmal alle grounds gecheckt und es scheint mir wirklich 
so, als ob ein pin etwas wackelig verlötet war. Er hatte zwar kontakt, 
aber wohl etwas zu wenig. Auf jedenfall bekomm ich jetzt ein kleines 
'a'.

Besten Dank für eure Tipps und Hilfe!

von Stefan (Gast)


Lesenswert?

> Witzigerweise scheinen nur die ersten beiden Bits verdreht zu werden.

Das sind die höherwertigsten Bits, die als letzte übertragen werden. Was 
meine Annahme bestätigt, dass die Frequenz des Oszillators nicht genau 
genug ist.

von L. P. (lpg)


Lesenswert?

Lass den AVR mit 8MHz laufen und verwende 115200 Baud. Läuft 1A.

Lg

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.