F_CPU bei atmega644 Standardeinstellungen

Gast #3313962
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
}
#3313973
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.
Gast #3313998
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.
Gast #3314010
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
}
#3314016
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.
Gast #3314047
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.
Gast #3314104
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;)
Gast #3314130
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.
Gast #3314166
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!
Gast #3314233
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.

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