Hallo zusammen, ich benutze einen ATMega644 und will daten vom ADC über den UART Senden. Leider kommt da nichts an. Mit einem ATMega32 funktioniert es ohne Probleme d.h. dass mein Terminal Programm richtig geschrieben ist und der Fehler am uC liegt. Die Register hab ich auch angepasst, sodass es eigentlich auf dem AtMega644 funktionieren sollte. Hier der Code: #ifdef F_CPU #undef F_CPU #define F_CPU 16000000UL #endif #include <avr/io.h> #include <inttypes.h> #include <util/delay.h> // Diese Beispiel zeigt die Anwendung des ADC eines ATmega169 // unter Verwendung der internen Referenzspannung von nominell 1,1V. // Zur Anpassung an andere AVR und/oder andere Referenzspannungen // siehe Erläuterungen in diesem Tutorial und im Datenblatt /* ADC initialisieren */ void ADC_Init(void) { // die Versorgungsspannung AVcc als Referenz wählen: //ADMUX = (1<<REFS0); // oder interne Referenzspannung als Referenz für den ADC wählen: ADMUX = (1<<REFS1) | (1<<REFS0); // Bit ADFR ("free running") in ADCSRA steht beim Einschalten // schon auf 0, also single conversion ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler ADCSRA |= (1<<ADEN); // ADC aktivieren /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. */ (void) ADCW; } /* ADC Einzelmessung */ uint16_t ADC_Read( uint8_t channel ) { // Kanal waehlen, ohne andere Bits zu beeinflußen ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } return ADCW; // ADC auslesen und zurückgeben } void USART_Init( unsigned int baud ) { /*Set baud rate*/ UBRR0H = (unsigned char)(baud>>8); UBRR0L = (unsigned char)baud; /* Enable receiver and transmitter*/ UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* Set frame format: 8data, 2stop bit*/ UCSR0C = (1<<USBS0)|(3<<UCSZ00); } void USART_Transmit( unsigned char data ) { /* Wait for empty transmit buffer*/ while ( !( UCSR0A & (1<<UDRE0)) ); /* Put data into buffer, sends the data*/ UDR0 = data; } void uart_puts( char *s ) { /* while *s != '\0' so unequally "string-end characters (terminator) */ while (*s) { USART_Transmit(*s); s++; } } void main(void) { USART_Init(0x67); char String[16] = {"Test "}; short ADCWert; ADC_Init(); while(1) { ADCWert = ADC_Read(4); sprintf(String,"Test: %i\n", ADCWert); uart_puts(String); //USART_Transmit(S); _delay_ms(1000); } }
muss ich die Baudrate neu berechnen? am Quarz hab ich aber nichts geändert. der ATMega32 läuft bis zu 16Mhz der AtMega644 läuft bis zu 20 Mhz Ich betreibe den Controller mit 16Mhz
Hans-Peter schrieb: > muss ich die Baudrate neu berechnen? Nein. Aber diese Einstellungen:
1 | UCSR0B = (1<<RXEN0)|(1<<TXEN0); |
werden in UCSR0A gemacht.
Hans-Peter schrieb: > USART_Init(0x67); 0x67 = 103 => 16 MHz / (16*104) = ~6 kHz.
:
Bearbeitet durch User
S. Landolt schrieb: > Also ich verstehe weder vorbild noch prx. Ich auch nicht. ;-) Tippfehler im Taschenrechner. Allerdings war ein Hex-Angabe an dieser Stelle arg verdächtig. Wer macht denn sowas?
:
Bearbeitet durch User
Kannst du einen String senden , ohne das du den ADC initialisierst und die Messung startest ? Gruß JackFrost
Muss ich nur diese Einstellungen ändern? UCSR0A = (1<<RXEN0)|(1<<TXEN0); hat leider auch nichts gebracht #ifdef F_CPU #undef F_CPU #define F_CPU 16000000UL #endif #include <avr/io.h> #include <inttypes.h> #include <util/delay.h> // Diese Beispiel zeigt die Anwendung des ADC eines ATmega169 // unter Verwendung der internen Referenzspannung von nominell 1,1V. // Zur Anpassung an andere AVR und/oder andere Referenzspannungen // siehe Erläuterungen in diesem Tutorial und im Datenblatt /* ADC initialisieren */ void ADC_Init(void) { // die Versorgungsspannung AVcc als Referenz wählen: //ADMUX = (1<<REFS0); // oder interne Referenzspannung als Referenz für den ADC wählen: ADMUX = (1<<REFS1) | (1<<REFS0); // Bit ADFR ("free running") in ADCSRA steht beim Einschalten // schon auf 0, also single conversion ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler ADCSRA |= (1<<ADEN); // ADC aktivieren /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. */ (void) ADCW; } /* ADC Einzelmessung */ uint16_t ADC_Read( uint8_t channel ) { // Kanal waehlen, ohne andere Bits zu beeinflußen ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } return ADCW; // ADC auslesen und zurückgeben } void USART_Init( unsigned int baud ) { /*Set baud rate*/ UBRR0H = (unsigned char)(baud>>8); UBRR0L = (unsigned char)baud; /* Enable receiver and transmitter*/ UCSR0A = (1<<RXEN0)|(1<<TXEN0); /* Set frame format: 8data, 2stop bit*/ UCSR0C = (1<<USBS0)|(3<<UCSZ00); } void USART_Transmit( unsigned char data ) { /* Wait for empty transmit buffer*/ while ( !( UCSR0A & (1<<UDRE0)) ); /* Put data into buffer, sends the data*/ UDR0 = data; } void uart_puts( char *s ) { /* while *s != '\0' so unequally "string-end characters (terminator) */ while (*s) { USART_Transmit(*s); s++; } } void main(void) { USART_Init(0x67); char String[16] = {"Test "}; short ADCWert; ADC_Init(); while(1) { ADCWert = ADC_Read(4); sprintf(String,"Test: %i\n", ADCWert); uart_puts(String); //USART_Transmit(S); _delay_ms(1000); } }
S. Landolt schrieb: > Also ich verstehe weder vorbild noch prx. Ja, ich verstehe mich selbst auch nicht. Hans-Peter schrieb: > Muss ich nur diese Einstellungen ändern? > UCSR0A = (1<<RXEN0)|(1<<TXEN0); Bloß nicht. Mach das wieder rückgängig. Das war ein Fall von geistiger Umnachtung.
Versuch mal das, ohne den ADC ob du dann was gesendet bekommst :
1 | #ifdef F_CPU
|
2 | #undef F_CPU
|
3 | #define F_CPU 16000000UL
|
4 | #endif
|
5 | |
6 | #include <avr/io.h> |
7 | #include <inttypes.h> |
8 | #include <util/delay.h> |
9 | |
10 | |
11 | |
12 | |
13 | // Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
|
14 | // unter Verwendung der internen Referenzspannung von nominell 1,1V.
|
15 | // Zur Anpassung an andere AVR und/oder andere Referenzspannungen
|
16 | // siehe Erläuterungen in diesem Tutorial und im Datenblatt
|
17 | |
18 | /* ADC initialisieren */
|
19 | void ADC_Init(void) |
20 | {
|
21 | // die Versorgungsspannung AVcc als Referenz wählen:
|
22 | //ADMUX = (1<<REFS0);
|
23 | // oder interne Referenzspannung als Referenz für den ADC wählen:
|
24 | ADMUX = (1<<REFS1) | (1<<REFS0); |
25 | |
26 | // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
|
27 | // schon auf 0, also single conversion
|
28 | ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler |
29 | ADCSRA |= (1<<ADEN); // ADC aktivieren |
30 | |
31 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
|
32 | liest
|
33 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
|
34 | lassen" */
|
35 | |
36 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
37 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der |
38 | Konvertierung warten |
39 | }
|
40 | /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
|
41 | Wandlung nicht übernommen. */
|
42 | (void) ADCW; |
43 | }
|
44 | |
45 | /* ADC Einzelmessung */
|
46 | uint16_t ADC_Read( uint8_t channel ) |
47 | {
|
48 | // Kanal waehlen, ohne andere Bits zu beeinflußen
|
49 | ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); |
50 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
51 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung |
52 | warten
|
53 | }
|
54 | return ADCW; // ADC auslesen und zurückgeben |
55 | }
|
56 | |
57 | |
58 | void USART_Init( unsigned int baud ) |
59 | {
|
60 | /*Set baud rate*/
|
61 | UBRR0H = (unsigned char)(baud>>8); |
62 | UBRR0L = (unsigned char)baud; |
63 | /* Enable receiver and transmitter*/
|
64 | UCSR0B = (1<<RXEN0)|(1<<TXEN0); |
65 | /* Set frame format: 8data, 2stop bit*/
|
66 | UCSR0C = (1<<USBS0)|(3<<UCSZ00); |
67 | }
|
68 | |
69 | |
70 | void USART_Transmit( unsigned char data ) |
71 | {
|
72 | /* Wait for empty transmit buffer*/
|
73 | while
|
74 | ( !( UCSR0A & (1<<UDRE0)) ); |
75 | /* Put data into buffer, sends the data*/
|
76 | UDR0 = data; |
77 | }
|
78 | |
79 | void uart_puts( char *s ) |
80 | {
|
81 | /* while *s != '\0' so unequally "string-end characters (terminator)
|
82 | */
|
83 | while (*s) |
84 | {
|
85 | USART_Transmit(*s); |
86 | |
87 | s++; |
88 | }
|
89 | }
|
90 | |
91 | |
92 | void main(void) |
93 | {
|
94 | USART_Init(0x67); |
95 | char String[16] = {"Test "}; |
96 | short ADCWert; |
97 | // ADC_Init();
|
98 | ADCWert = 123; |
99 | while(1) |
100 | {
|
101 | //ADCWert = ADC_Read(4);
|
102 | |
103 | sprintf(String,"Test: %i\n", ADCWert); |
104 | uart_puts(String); |
105 | //USART_Transmit(S);
|
106 | _delay_ms(1000); |
107 | }
|
108 | |
109 | }
|
Wenn dann was kommt stimmt mit deinem ADC Teil was nicht
Und wenn dann immer noch nichts kommt, stimmen entweder Hardware oder Controller-Takt nicht.
:
Bearbeitet durch User
leider kein Erfolg :-( Trotzdem Danke mal, ich werde glaub ne Nacht drüber schlafen...
Hast du die CKDIV8 Fuse beim Atmega644 gelöscht ? Wenn nein dann läuft der ja nur mit 2 MHz Gruß JackFrost
:
Bearbeitet durch User
Hallo zusammen, nun kommen Daten an der Seriellen Schnittstelle an. Allerdings werden mir diese als nichtlesbare Zeichen dargestellt. Ich habe die Taktrate wie beschrieben auf 2 MHz gesetzt. den UART habe ich wie folgt initilaisiert: USART_Init(0xc); das bedeutet dass er nun mit 2 Mhz läuft. weiter komme ich allerdings nicht. Kann mir sonst noch jemand sagen was ich beachten sollte? vielen Dank im voraus. hier mein code: #ifdef F_CPU #undef F_CPU #define F_CPU 2000000UL #endif #include <avr/io.h> #include <inttypes.h> #include <util/delay.h> // Diese Beispiel zeigt die Anwendung des ADC eines ATmega169 // unter Verwendung der internen Referenzspannung von nominell 1,1V. // Zur Anpassung an andere AVR und/oder andere Referenzspannungen // siehe Erläuterungen in diesem Tutorial und im Datenblatt /* ADC initialisieren */ void ADC_Init(void) { // die Versorgungsspannung AVcc als Referenz wählen: //ADMUX = (1<<REFS0); // oder interne Referenzspannung als Referenz für den ADC wählen: ADMUX = (1<<REFS1) | (1<<REFS0); // Bit ADFR ("free running") in ADCSRA steht beim Einschalten // schon auf 0, also single conversion ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler ADCSRA |= (1<<ADEN); // ADC aktivieren /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. */ (void) ADCW; } /* ADC Einzelmessung */ uint16_t ADC_Read( uint8_t channel ) { // Kanal waehlen, ohne andere Bits zu beeinflußen ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } return ADCW; // ADC auslesen und zurückgeben } void USART_Init( unsigned int baud ) { /*Set baud rate*/ UBRR0H = (unsigned char)(baud>>8); UBRR0L = (unsigned char)baud; /* Enable receiver and transmitter*/ UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* Set frame format: 8data, 2stop bit*/ UCSR0C = (1<<USBS0)|(3<<UCSZ00); } void USART_Transmit( unsigned char data ) { /* Wait for empty transmit buffer*/ while ( !( UCSR0A & (1<<UDRE0)) ); /* Put data into buffer, sends the data*/ UDR0 = data; } void uart_puts( char *s ) { /* while *s != '\0' so unequally "string-end characters (terminator) */ while (*s) { USART_Transmit(*s); s++; } } void main(void) { USART_Init(0xc); char String[16] = {"Test "}; short ADCWert; // ADC_Init(); ADCWert = 123; while(1) { //ADCWert = ADC_Read(4); sprintf(String,"Test: %i\n", ADCWert); uart_puts(String); //USART_Transmit(S); _delay_ms(1000); } }
Die Fuses vom Controller, wo du die Taktquelle, Brownout usw einstellst. https://www.mikrocontroller.net/articles/AVR_Fuses Hast du an den was geändert ? Mit was programmierst du ? Was für einen ISP Programmer hast du ? Gruß JackFrost
hab ein Fehler gemacht. Das sind die Hfuses:0b10011001 und das sind die Lfuses: 0b1100010
Nach dem http://www.engbedded.com/fusecalc/ läuft der Atmega644 mit dem internen RC Oszillator und ohne die CKDIV8 Fuse. Damit solltest du den Wert für die Baudrate mit 8 MHz berechnen. Gruß JackFrost
Hallo, von C Programmierung der ATMEGA - Controller habe ich mich schon vor ein paar Jahren verabschiedet. Somit nur ein Hinweis: Unterschied der 32 hat nur einen Hardware Uart der 644 zwei. Somit ist es zwingend nötig den Controller zu sagen welcher frei gegeben wird. Mit Bascom sehr einfach im Header einzustellen. Beispiel: $baud = 19200 ‚ ist 1 $baud1 = 19200 ‚ ist 2 Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet werden aber nur stabil mit Betriebsspannung 3,3 Volt. Kommen „wüste“ Zeichen zum Terminal an,ist es erst mal ein Zeichen, UART hat Verbindung aufgebaut nur die Baudrate ist nicht synchron eingestellt. Mit freundlichen Grüßen
Fred R. schrieb: > Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet > werden aber nur stabil mit Betriebsspannung 3,3 Volt. Datenblatt sagt was anderes. – ATmega644: 0 - 10MHz @ 2.7V - 5.5V, 0 - 20MHz @ 4.5V - 5.5V
Wolfsente schrieb: > Fred R. schrieb: >> Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet >> werden aber nur stabil mit Betriebsspannung 3,3 Volt. > > Datenblatt sagt was anderes. > > – ATmega644: 0 - 10MHz @ 2.7V - 5.5V, 0 - 20MHz @ 4.5V - 5.5V Hallo, ja die Wortwahl „missachtet“ ist wohl falsch gewählt. Kenne Datenblatt und diese Info hat mich auch viele Nerven und Zeit geraubt. Im Nachhinein sieht man den Widerspruch. Schon die Bezeichnung von 0 bis xx ist doch schon sehr missverständlich. Mit 0 Takt wird wohl nichts mehr funktionieren. Hatte das gleiche Problem mit Uart Controller und Terminal. Haben einfach keine synchrone Baudrate bekommen. Obwohl das Programm „sauber“ abgearbeitet wurde. Nur durch Zufall den Controller mit 3,3 Volt betrieben und siehe da alles bestens. Als nächsten Versuch den Takt auf 8 M eingestellt. Nun ist es Wurst ob 3,3 Volt oder 5,0 Volt, es funktionier halt. Ich nenne es mal in meiner Rhetorik “ Der Controller war übertaktet“ Zu meiner Entschuldigung für Antwort(ist ja sehr wichtig für einige in diesem Forum) bin nur ein Amateur und sehr ausdauernd bei Fehlersuche. Also „basteln“ und probieren hat mehr Erfolg, als nur die Antwort zu bekommen „siehe Datenblatt“. Die meiste machen es wie auch ich. Somit wollte ich nur meine praktischen Erfahrungen vermitteln. MfG
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.