ATMega644 UART

Gast #4514755
Lesenswert?

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);
  }

}
Gast #4514924
Lesenswert?

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);
  }

}
#4514950
Lesenswert?

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
Gast #4518352
Lesenswert?

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);
  }

}
#4518617
Lesenswert?

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
Gast #4520145
Lesenswert?

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

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