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
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
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 | }
|
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.
hab den code jetzt mal auf USART_Transmit( 'a' ); geändert, nun empfang ich 0xA1, was allerdingsa auch das falsche zeichen ist.
>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.
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?
könnte es auch an dem FTDI FT232RL liegen, dass die Daten falsch ankommen?
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.
>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.
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 | }
|
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.
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.
holger schrieb: > Ich sehe nirgends eine Definition von UBRRH_VALUE oder UBRRL_VALUE.
1 | #include <util/setbaud.h> |
>> 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.
>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.
Mit R/C Oszillator kann man sowieso nicht erwarten, dass die UART Schnittstelle funktioniert.
>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;)
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
>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.
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!
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.