Forum: Mikrocontroller und Digitale Elektronik Probleme mit neuer USART-Konfiguration


von Peter R. (Gast)


Lesenswert?

Hallo,

ich hab mir letztes Jahr mal für mein Entwicklungsboard(ATMega2560) eine 
USART-Routine gebastelt, habe aber nun bei der Portierung in meine erste 
eigene Schaltung Probleme.
Ich bekomme beim Senden eines Zeichens mit USART_SEND_STRING("a") 
scheinbar nur 0-Terminierungen in meinem Terminal-Programm:

<0><0><0><0><0><0>

Dies ist mein Code:
1
/*******************************************************************************************************/
2
#ifndef usart_h
3
#define usart_h
4
/*******************************************************************************************************/
5
// Einbindung von Standardbibliotheken
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <string.h>
9
/*******************************************************************************************************/
10
// Definition der Baudrate
11
#define BAUD 9600L // das L am Ende ist wichtig, NICHT UL verwenden!
12
13
// Berechnungen:
14
// Runden
15
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
16
// reale Baudrate
17
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
18
// Fehler in Promille
19
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)
20
21
#if((BAUD_ERROR>10)||(BAUD_ERROR<-10))
22
    #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
23
#endif
24
/*******************************************************************************************************/
25
// globale Variablen für den USART
26
#define uart_buffer_size 32            // Puffergrösse in Bytes(RX und TX sind gleich groß)
27
28
volatile uint8_t uart_rx_flag=0;       // Flag 'String komplett empfangen'
29
volatile uint8_t uart_tx_flag=1;       // Flag 'String komplett gesendet'
30
char uart_rx_buffer[uart_buffer_size]; // Empfangspuffer
31
char uart_tx_buffer[uart_buffer_size]; // Sendepuffer
32
/*******************************************************************************************************/
33
// Initialisierung
34
void USART_INIT(void)
35
{
36
    UBRR0H = UBRR_VAL >> 8;
37
    UBRR0L = UBRR_VAL & 0xFF;
38
    // Aktivierung der USART-Komponenten Transmitter, Receiver und RX Complete Interrupt
39
    UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
40
  //UCSR0C |= (1<<UMSEL01)|(1<<UMSEL00); // USART in MasterSPI Mode
41
}
42
/*******************************************************************************************************/
43
void USART_SEND_STRING(char *data) // zum Senden eines Strings
44
{
45
    if(uart_tx_flag==1) // Überprüfung des uart_tx_flag
46
    {
47
        // Kopieren des Strings in den Sendepuffer...
48
        strcpy(uart_tx_buffer,data);
49
        strcat(uart_tx_buffer,"\r"); // ... und Abschließen mit RETURN
50
        // Löschen des Flag für 'Senden ist komplett'
51
        uart_tx_flag = 0;
52
        // Aktivieren des UDRE-Interrupts
53
        UCSR0B |= (1<<UDRIE0);
54
    }
55
}
56
/*******************************************************************************************************/
57
void USART_RECEIVE_STRING(char *data) // zum Empfangen eines Strings
58
{
59
    if(uart_rx_flag==1) // Überprüfung des uart_rx_flag
60
    {
61
        // String kopieren
62
        strcpy(data,uart_rx_buffer);
63
        // Flag löschen
64
        uart_rx_flag = 0;
65
    }
66
}
67
/*******************************************************************************************************/
68
// USART RX Complete Interrupt:
69
// Hier werden Daten vom PC empfangen und in einem String zwischengespeichert.
70
// Wird ein Stringterminator empfangen, wird ein Flag gesetzt,
71
// welches dem Hauptprogramm den kompletten Empfang signalisiert.
72
ISR(USART_RX_vect)
73
{
74
    static uint8_t uart_rx_cnt; // Zähler für empfangene Zeichen
75
    uint8_t data;
76
77
    // Auslesen der Daten(dadurch wird das Interruptflag gelöscht)
78
    data = UDR0;
79
80
    if(!uart_rx_flag) // Überprüfung, ob Puffer leer ist
81
    {
82
        if(data=='\r') // wenn ja, Überprüfung auf das Ende des Strings(RETURN)
83
        {
84
            // Terminierung des Strings
85
            uart_rx_buffer[uart_rx_cnt]=0;
86
            // Setzen des Flags für 'Empfangspuffer voll'
87
            uart_rx_flag=1;
88
            uart_rx_cnt=0;
89
        }
90
        else if(uart_rx_cnt<(uart_buffer_size-1))
91
        {
92
            // Speicherung der Daten im Puffer(Vermeidung eines Pufferüberlaufs durch if())
93
            uart_rx_buffer[uart_rx_cnt]=data;
94
            uart_rx_cnt++;
95
        }
96
    }
97
}
98
/*******************************************************************************************************/
99
// USART TX Data Register Empty Interrupt:
100
// Hier werden neue Daten in das UART-Senderegister geladen.
101
ISR(USART_UDRE_vect)
102
{
103
    // Zeiger auf Sendepuffer
104
    static char* uart_tx_p = uart_tx_buffer;
105
    uint8_t data;
106
107
    // zu sendendes Zeichen lesen und Erhöhung des Zeigers auf den Sendepuffer
108
    data = *uart_tx_p++;
109
110
    if(data==0) // Überprüfung auf das Ende des nullterminierten Strings
111
    {        
112
        UCSR0B &= ~(1<<UDRIE0);     // wenn ja, dann Deaktivierung des UDRE Interrupt
113
        uart_tx_p = uart_tx_buffer; // Zurücksetzung des Pointers
114
        uart_tx_flag = 1;           // Flag setzen und damit die Übertragung beeenden
115
    }
116
    else UDR0 = data;               // wenn nein, dann Senden der Daten
117
}
118
/*******************************************************************************************************/
119
#endif
120
/*******************************************************************************************************/

Habt ihr vl. eine Ahnung, was da los sein kann?

Viele Grüße und danke schon mal im Voraus

von holger (Gast)


Lesenswert?

>Habt ihr vl. eine Ahnung, was da los sein kann?

Baudrate falsch.

von Peter R. (Gast)


Lesenswert?

Hallo Holger,

die Brechnung der Baudrate kann nicht falsch sein. Ich habe diese 
Einstellung bis jetzt für alle meine Projekte hergenommen.

LG

von g457 (Gast)


Lesenswert?

> die Brechnung der Baudrate kann nicht falsch sein.

Doch, kann sie, z.B. wenn der µC mit dem falschen Takt läuft.

von Peter R. (Gast)


Lesenswert?

Der ATMega88 arbeitet aber mit den gleichen Einstellungen wie vorher 
schon mein ATmega2560.

Viele Grüße

von Peter R. (Gast)


Lesenswert?

Upps.

Ich hab' ganz die externe Beschaltung vergessen. Hat sich also 
erledigt.;-)

LG

von Peter R. (Gast)


Lesenswert?

Hallöchen,

leider hab' ich das Problem immer noch. Es werden nur Terminierungen 
bzw. '0' übertragen - aber stets mehr Zeichen(oder was das auch immer 
sein soll^^) als gesendet.

Vielleicht kennt ja jemand diese Konfiguration:

Als Programmer (und auch Kommunikationsschnittstelle zum PC) benutze ich 
das mySmartUSB_MK3 von myAVR. Und zwischen meinem MEGA und den 
Programmer(an die UART-PINs R7/R8) habe ich nun einen RS232-Baustein 
geklemmt.
Zudem ist mein MEGA (noch) nicht mit einem Quarz verbunden(läuft also 
ausschließlich über den Internen).
Die USART-Routinen samt Einstellungen MÜSSEN wie gesagt funktionieren - 
sie sind letztes Jahr durch Hilfe der Mods und des AVR-Tutorials 
entstanden und haben bisher bei allen Projekten(auf meinem damaligen 
Experimentierboard) sehr gute Dienste geleistet.

Woran könnte es denn liegen?

Viele Grüße

von holger (Gast)


Lesenswert?

CKDIV8 Fuse löschen (1 setzen).

von Peter R. (Gast)


Lesenswert?

Hallöchen Holger,

das Häkchen hab ich weggenommen. Aber was meinst du denn mit '1 setzen'?

LG

von Peter R. (Gast)


Lesenswert?

Ps.:

Jetzt werden Hyroglyphen übertragen.

Ist das gut?;-)

LG

von spess53 (Gast)


Lesenswert?

Hi

>Jetzt werden Hyroglyphen übertragen.

Beim internen RC-Oszillator leicht möglich.

Ist das gut?;-)

Wenn du damit leben kannst.

MfG Spess

von Peter R. (Gast)


Lesenswert?

NEIN!;-))

Das war doch Spasssss.^^

Wie kann ich das denn ändern?

LG

von holger (Gast)


Lesenswert?

>das Häkchen hab ich weggenommen. Aber was meinst du denn mit '1 setzen'?

das Häkchen wegnehmen;)
Ohne CKDIV8 müsste F_CPU 8MHz sein.

>(an die UART-PINs R7/R8)

Der UART0 liegt aber auf den Pins 2 und 3.

von spess53 (Gast)


Lesenswert?

Hi

>Wie kann ich das denn ändern?

Du kannst ja mal versuchen mit dem OSCCAL-Register den Takt zu 
verändern.
Ist aber keine Dauerlösung.

MfG Spess

von Peter R. (Gast)


Lesenswert?

@Holger:

Hmmm... naja... er scheint ja jetzt zumindest mal 'irgendwas' zu 
übertragen^^.
Ich meinte PIN R7/R8 an meinem Programmer.

@Spess:

Werd ich gleich mal versuchen.
Es soll auch keine Dauerlösung sein. Auf meiner gebastelten Platine ist 
ja ein 20MHz-Quarz, dieser wird aber erst durch einen anderen 
Schaltkreis dazugeschaltet - dessen Programmierung ich noch nicht fertig 
habe.

LG

von holger (Gast)


Lesenswert?

>Hmmm... naja... er scheint ja jetzt zumindest mal 'irgendwas' zu
>übertragen^^.

Dann ist die Baudrate immer noch falsch oder dein
RS232-Baustein möglicherweise sogar falsch angeschlossen.

Du scheinst ja immer noch nicht zu wissen mit welchem Takt deine
CPU wirklich läuft. Mach dir erst mal ein kleines Programm das
eine LED im Sekundentakt blinken lässt. Dann sehen wir weiter.

von Dietrich L. (dietrichl)


Lesenswert?

Wo ist denn F_CPU definiert? In Deinem Code oben habe ich nichts 
gefunden.

Gruß Dietrich

von Peter R. (Gast)


Lesenswert?

Ich hab jetzt mal schnell einen 16MHz Quarz dazwischengeklemmt. Sind die 
Kondensatoren am Quarz zwingend?
Es hat sich nichts geändert?!:(

LG

von Peter R. (Gast)


Lesenswert?

@Dietrich:

Hier mal meine Hauptroutine:
1
********************************************************************************************************/
2
#ifndef F_CPU
3
#define F_CPU 16000000
4
#endif
5
/*******************************************************************************************************/
6
// Einbindung von Standardbibliotheken...
7
#include <stdint.h>          // Datentypen (standardisiert)
8
#include <avr/io.h>          // Registernamen
9
#include <avr/interrupt.h>
10
#include <stdio.h>           // Rechenoperationen, etc.
11
#include <math.h>
12
//#include <string.h>        // Zeichenketten-Funktionen
13
// ... und externen Dateien
14
#include "buttons.h"
15
//#include "SPI.h"
16
#include "usart.h"
17
/*******************************************************************************************************/
18
#define RELAIS_ON_DDR  DDRD
19
#define RELAIS_ON_PORT  PORTD
20
#define RELAIS_ON    7
21
#define RELAIS_OFF_DDR  DDRB
22
#define RELAIS_OFF_PORT  PORTB
23
#define RELAIS_OFF    0
24
25
#define PWM1_DDR    DDRB
26
#define PWM1_PORT    PORTB
27
#define PWM1      1
28
/*******************************************************************************************************/
29
// Enumeration: Typen-Definition von bool(Boolean)
30
typedef enum {
31
  false = 0,
32
  true
33
} bool;
34
/*******************************************************************************************************/
35
void LED_FADING(int16_t data,int16_t mode); // zum Ein-/Ausblenden von LEDs
36
/*******************************************************************************************************/
37
// Deklaration globaler Variablen
38
volatile uint8_t sreg_local;
39
40
#define SECOND ((F_CPU/16)/1024) // Wert für 1s Durchlaufzeit im Timer1-Overflow-Interrupt
41
#define RELAIS_TIMEOUT 15        // Timeout-Wert(in ~m) für die Abschaltung des 230V-Verbrauchers
42
#define nBtnModeTimeout 300      // Timeout-Wert(in ~ms) für das 'key_press'-Ereignis
43
#define nFadingTime 200          // Ein-/Ausblendzeit(in ~ms)
44
#define DIMM_TIMEOUT 150       // Zählerschritte(keine s!), bevor von 100% wieder heruntergedimmt wird
45
46
int16_t bRelaisSignal = 0;
47
int32_t nRelaisCount = 0;
48
int16_t nBtnMode = 0;            // Programm-Modus des Tasters
49
int16_t nBtnModeCount = 0;       // Zähler für das 'key_press'-Ereignis
50
int16_t nDimmCount = 0;         // Zähler für 
51
int16_t bDimmDirection = 1;      // Dimmungrichtung(1:EIN;0:AUS)
52
int16_t bFadingSignal = 0;
53
int16_t nFadingCount = 0;        // Zähler für die Ein-/Ausblendfunktion(Fading)
54
int16_t nFadingLED = 0;
55
int16_t nSavedPWM = 50;          // Variable zur Speicherung des letzten PWM- bzw. Helligkeitswertes
56
/*******************************************************************************************************/
57
// zum Speichern und Deaktivieren der Interrupts auf globaler Ebene
58
void ISR_0()
59
{
60
    sreg_local = SREG; // Erstellung einer lokalen Sicherungskopie von SREG
61
    cli();
62
}
63
/*******************************************************************************************************/
64
// zum Laden und Aktivieren der Interrupts auf globaler Ebene
65
// (Es werden nur die Interrupts aktiviert, die auch vor dem Abschalten schon in Benutzung waren!)
66
void ISR_1()
67
{
68
    SREG = sreg_local; // Sicherungskopie von SREG laden
69
}
70
/*******************************************************************************************************/
71
// Auswertung des Timer1-Overflow-Interrupts
72
ISR(TIMER1_OVF_vect)
73
{
74
  if(bRelaisSignal != 0)
75
  {
76
    nRelaisCount++;
77
    if(bRelaisSignal == 1)
78
    {
79
      if(nRelaisCount <= SECOND/3)
80
        RELAIS_ON_PORT |= (1<<RELAIS_ON);
81
      else
82
        RELAIS_ON_PORT &= ~(1<<RELAIS_ON);
83
84
      if(nRelaisCount > ((int32_t)(SECOND*RELAIS_TIMEOUT)*60))
85
      {
86
        bRelaisSignal = 2;
87
        nRelaisCount = 0;
88
      }
89
    }
90
    else
91
    {
92
      if(nRelaisCount <= SECOND/3)
93
        RELAIS_OFF_PORT |= (1<<RELAIS_OFF);
94
      else
95
      {
96
        RELAIS_OFF_PORT &= ~(1<<RELAIS_OFF);
97
        bRelaisSignal = 0;
98
        nRelaisCount = 0;
99
      }
100
    }
101
  }
102
  /***************************************************************************************************/
103
  if(nBtnMode != 0) // sobald irgendein Programm-Modus(s. Tasterabfragen) ausgewählt wurde,...
104
  {
105
    nBtnModeCount++; // ... Start des Zählers für die 'key'-Events(Timeout)
106
107
    if(KEY_PIN & (1<<KEY1))
108
    {
109
      if(nBtnModeCount > nBtnModeTimeout && nBtnModeCount < nBtnModeTimeout*3)
110
      {
111
        switch(nBtnMode)
112
        {
113
          /*---------------------------------------------------------------------------------*/
114
          case(1): if(!(PINB & (1<<PINB1)))
115
               {
116
                 OCR1A = nSavedPWM;
117
                 TCCR1A |= (1<<COM1A1);
118
                 bRelaisSignal = 1;
119
               }
120
               else
121
               {
122
                 OCR1A = 0;
123
                 TCCR1A &= ~(1<<COM1A1);
124
               }
125
               break;
126
          /*---------------------------------------------------------------------------------*/
127
          case(2): nFadingLED = 4;
128
               if(!(PINB & (1<<PINB1)))
129
                 bFadingSignal = 1; // Signal:FadeIN
130
               else
131
                 bFadingSignal = 2; // Signal:FadeOUT
132
               break;
133
          /*---------------------------------------------------------------------------------*/
134
        }
135
        nBtnMode = 0;      // Zurücksetzung des Programm-Modus
136
        nBtnModeCount = 0; // Zurücksetzung des Zählers
137
      }
138
      if(nBtnModeCount >= nBtnModeTimeout*3)
139
      {
140
        nBtnMode = 0;      // Zurücksetzung des Programm-Modus
141
        nBtnModeCount = 0; // Zurücksetzung des Zählers
142
      }
143
    }
144
  }
145
  /***************************************************************************************************/
146
  if(bFadingSignal != 0)
147
  {
148
    nFadingCount++;
149
    
150
    if(nFadingCount <= nFadingTime)
151
      if(bFadingSignal == 1)
152
        LED_FADING(nFadingLED,1);
153
      else
154
        LED_FADING(nFadingLED,0);
155
    else
156
    {
157
      bFadingSignal = 0;
158
      nFadingCount = 0;
159
    }
160
  }
161
}
162
/*******************************************************************************************************/
163
// zum Überblenden(Ein-/Ausblenden) von LEDs
164
void LED_FADING(int16_t data,int16_t mode)
165
{
166
  int16_t tmp;
167
168
  if(mode == 1) // FadeIN
169
  {
170
    // da 'nFadingCount*(nSavedPWM/nFadingTime)' nur int-Werte verarbeiten kann, wird
171
    // hier durch Benutzung einer temporären größeren 32Bit-Variable UND der
172
    // LEFT-Shift-Operation in einem 'Vielfachen' der Ausgangswerte weitergerechnet
173
    tmp = (nFadingCount*(((int32_t)nSavedPWM << 16)/nFadingTime)) >> 16;
174
175
    if(data == 1)      TCCR0A |= (1<<COM0A1);
176
    else if(data == 2) TCCR0B |= (1<<COM0B1);
177
    else if(data == 3) TCCR2B |= (1<<COM2B1);
178
    else if(data == 4) TCCR1A |= (1<<COM1A1);
179
  }
180
  else          // FadeOUT
181
    // mit 'nSavedPWM-Zählerfaktor(s.o.)' wird hier der Zähler rückwärts ausgewertet
182
    tmp = nSavedPWM-((nFadingCount*(((int32_t)nSavedPWM << 16)/nFadingTime)) >> 16);
183
184
  // Zuweisung des PWM-Wertes an das jeweilige Compare-Register
185
  if(data == 1)     OCR0A = tmp;
186
  else if(data == 2) OCR0B = tmp;
187
  else if(data == 3) OCR2B = tmp;
188
  else if(data == 4) OCR1A = tmp;
189
190
  if(tmp == 0)
191
  {
192
    if(data == 1)      TCCR0A &= ~(1<<COM0A1);
193
    else if(data == 2) TCCR0B &= ~(1<<COM0B1);
194
    else if(data == 3) TCCR2B &= ~(1<<COM2B1);
195
    else if(data == 4) TCCR1A &= ~(1<<COM1A1);
196
  }
197
}
198
/*******************************************************************************************************/
199
int main (void)
200
{
201
  // Initialisierung des USART
202
  char stringbuffer[32];        // Definition eines allgemeinen Puffers für die Strings
203
204
    USART_INIT();                 // Grundeinstellungen des USART
205
206
  // Konfiguration der I/Os:
207
  KEY_DDR &= ~ALL_KEYS;         // Taster als Eingang
208
  KEY_PORT |= ALL_KEYS;              // Aktivierung der internen Pull-Ups
209
210
  RELAIS_OFF_DDR |= (1<<RELAIS_OFF); // Relais1 als Ausgang
211
  RELAIS_ON_DDR |= (1<<RELAIS_ON);   // Relais2 als Ausgang
212
213
  PWM1_DDR |= (1<<PWM1);         // PWM1 als Ausgang
214
    /***************************************************************************************************/
215
  // Konfiguration von Timer1 für die PWM und den allg. Zeitgeber:
216
  // Mode:Fast PWM;TOP:OCR1A;Update:BOTTOM;TOV1:TOP;Prescaler:1(FRQ@16MHz = 16MHz)
217
  TCCR1A = (1<<WGM11);
218
  TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
219
    OCR1A = 0;                    // PWM-Wert
220
  ICR1 = 1023;                  // TOP-Wert des Zählers
221
  TIMSK1 |= 1<<TOIE1;       // Aktivierung des Interrupts(Timer1 Overflow Interrupt Enable)
222
223
  // Konfiguration von Timer0 für die Tasterentprellung:
224
  TCCR0B = (1<<CS02)|(1<<CS00); // Prescaler:1024
225
  TIMSK0 |= 1<<TOIE0;        // Aktivierung des Interrupts(Timer0 Overflow Interrupt Enable)
226
  sei();              // Aktivierung der Interrupts auf globaler Ebene
227
  /***************************************************************************************************/
228
  
229
230
  while(1)
231
  {
232
    // USART-Kommunikation
233
    if(uart_rx_flag==1) // String komplett empfangen?
234
        {
235
            USART_RECEIVE_STRING(stringbuffer);   // Einlesen des Strings
236
            //SWITCHBOARD_PINS_USART(stringbuffer); // PIN-Ansteuerung
237
      //USART_SEND_STRING(stringbuffer);
238
        }
239
240
    // Abfrage der Taster:
241
    // (Für die zeitliche Signal-Verarbeitung wird bei jedem 'key_press'-Ereignis ein Zähler in
242
    // TIMER1_OVF_vect(s.o.) gestartet!)
243
    /***********************************************************************************************/
244
    if(get_key_press(1<<KEY1))
245
    {
246
      //nBtnMode++;        // Umschalten/Hochzählen des Programm-Modus
247
      //nBtnModeCount = 0; // Zurücksetzung des Zählers(s.TIMER1_OVF_vect)
248
      USART_SEND_STRING("Dynasoft' autoDesk: ...loaded.");
249
    }
250
    /***********************************************************************************************/
251
    if(get_key_short(1<<KEY1) || get_key_long_r(1<<KEY1) || get_key_rpt_l(1<<KEY1))
252
    {
253
      /*if(!(TCCR1A & (1<<COM1A1)))
254
      {
255
        TCCR1A |= (1<<COM1A1);
256
        OCR1A = 0;
257
        nSavedPWM = 0;
258
      }*/
259
      // bei COM1A1=0 auch den PIN auf 0 schalten!
260
261
      switch(nBtnMode)
262
      {
263
        /*-------------------------------------------------------------------------------------*/
264
        case(2): if(bDimmDirection == 1)
265
             {
266
               TCCR1A |= (1<<COM1A1);
267
268
               if(OCR1A < ICR1)
269
                 OCR1A += 5;
270
              else
271
              {
272
                nDimmCount++;
273
                if(nDimmCount > DIMM_TIMEOUT)
274
                   bDimmDirection = 0;
275
               }
276
             }
277
             else
278
             {
279
               if(OCR1A > 0)
280
                 OCR1A -= 5;
281
               else
282
              {
283
                OCR1A = 0;
284
                TCCR1A &= ~(1<<COM1A1);
285
                bDimmDirection = 1;
286
                nDimmCount = 0;
287
              }
288
             }
289
             nSavedPWM = OCR1A;
290
             break;
291
        /*-------------------------------------------------------------------------------------*/
292
      }
293
    }
294
  }
295
  return 0;
296
}
297
/*******************************************************************************************************/

LG

von Thomas E. (thomase)


Lesenswert?

Peter R. schrieb:
> Habt ihr vl. eine Ahnung, was da los sein kann?
Nein. Da kann man nur raten.

Du sitzt jetzt wahrscheinlich seit dem ganzen Wochenende ratlos vor 
deiner Kiste, anstatt mal nur die Übertragung zu testen.

//#define F_CPU 1000000UL
#define F_CPU 8000000UL
//#define F_CPU 16000000UL
//#define F_CPU 2000000UL

// Definition der Baudrate
#define BAUD 9600L // das L am Ende ist wichtig, NICHT UL verwenden!
// Berechnungen:
// Runden
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
// reale Baudrate
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
// Fehler in Promille
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)

#if((BAUD_ERROR>10)||(BAUD_ERROR<-10))
    #error Systematischer Fehler der Baudrate grösser 1% und damit zu 
hoch!
#endif

void USART_INIT(void)
{
    UBRR0H = UBRR_VAL >> 8;
    UBRR0L = UBRR_VAL & 0xFF;
    UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
}

int main(void)
{
  USART_INIT();
  sei();

  while(1)
  {
  }
}

ISR(USART_RX_vect)
{
   char nUdr = UDR0;
   UDR0 = nUdr;
}

Terminal ran, Taste drücken.
Taste wird quittiert: Hardware läuft.
Tsate wird nicht quittiert: Hardware läuft nicht.
Dazu gehört dann auch die Quarzgeschichte.
Teste einfach mal alle Möglichkeiten durch. Sind doch nicht viele:
1MHz, 8MHz,..,...

Das ganze String- und LED-Gedöns ist doch erstmal völlig unwichtig.

Und das macht natürlich auch Sinn:
holger schrieb:
> Du scheinst ja immer noch nicht zu wissen mit welchem Takt deine
> CPU wirklich läuft. Mach dir erst mal ein kleines Programm das
> eine LED im Sekundentakt blinken lässt. Dann sehen wir weiter.

mfg.

von Peter R. (Gast)


Lesenswert?

@Thomas:

Damit hab' ich's jetzt getestet...

#include <stdint.h>          // Datentypen (standardisiert)
#include <avr/io.h>          // Registernamen
#include <avr/interrupt.h>

#define F_CPU 1000000UL
//#define F_CPU 8000000UL
//#define F_CPU 16000000UL
//#define F_CPU 2000000UL

#define BAUD 9600
#include <util/setbaud.h>

void USART_INIT(void)
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

  #if USE_2X
    /* U2X-Modus erforderlich */
    UCSR0A |= (1 << U2X0);
  #else
     /* U2X-Modus nicht erforderlich */
     UCSR0A &= ~(1 << U2X0);
  #endif

    UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
}


ISR(USART_RX_vect)
{
   char nUdr = UDR0;
   UDR0 = nUdr;
}

int main(void)
{
  DDRC &= ~(1<<PC0);         // Taster als Eingang
    PORTC |= (1<<PC0);
  DDRB |= (1<<PB1);

  USART_INIT();
  sei();

  while(1)
  {
    if(!(PINC & (1<<PINC0)))
    {
      while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich 
*/
        {
        }

        UDR0 = 'x';
    }
  }
}


Es hat sich aber nicht viel dabei geändert. Das Terminal spuckt nur 
Buchstabensalat aus.:(

Wie soll das denn mit dem Sekundentakt aussehen???????????????????

Viele Grüße

von holger (Gast)


Lesenswert?

>Damit hab' ich's jetzt getestet...
>
>#define F_CPU 1000000UL

DU HAST DIE CKDIV8 FUSE DOCH GERADE A SO UMGESTELLT
das deine scheiss CPU mit 8MHz läuft. Warum zum Teufel
stellst du jetzt 1MHz im Code ein?

von fdssd (Gast)


Lesenswert?

er weiß immernoch nicht das beim AVR der UART takt aus dem CPU takt 
erechnet wird
leider mit schrägen teilern


stimmt der ECHTE CPU takt  nicht mit der definition in der SW zusammen 
kommt eben scheiße bei raus


deswegn gibts sogar  BAUDRATENQUARZE

von fdssd (Gast)


Lesenswert?

nochmal :   der echte CPUtakt wird durch den externen Quarz oder durch 
den internen 8MHz RC bestimmt
( bzw dieser takt /8 wenn die CLKDIV8 Fuse gesetzt ist )


dein F_CPU ist nur für die berechnung innerhlab der SW
und bestimmt NICHT den CPU takt

von Peter R. (Gast)


Lesenswert?

Hey Mädls,

ihr müßt ja ned gleich so ordinär werden.^^
Ich habe mit F_CPU genau aus dem selben Grund herumprobiert, warum ich 
auch HIER poste - weil ich ein Neuling mit µC bin. Und ich habe bis dato 
gedacht, dass F_CPU den Takt physikalisch verändert.

Ich hab jetzt einen 20MHz-Quarz und zwei 22pF große Kondensatoren 
angeschlossen, F_CPU auf 20Mhz umgestellt und CLKDIV8 ist ebenfalls 
draußen.
Ist die FUSE 'SUT_CKSEL' noch wichtig, dort steht jetzt noch 'Int. Osc 
8MHz'?
1
#include <stdint.h>          // Datentypen (standardisiert)
2
#include <avr/io.h>          // Registernamen
3
#include <avr/interrupt.h>
4
5
#define F_CPU 20000000
6
7
#define BAUD 9600
8
#include <util/setbaud.h>
9
10
void USART_INIT(void)
11
{
12
    UBRR0H = UBRRH_VALUE;
13
    UBRR0L = UBRRL_VALUE;
14
15
  #if USE_2X
16
    /* U2X-Modus erforderlich */
17
    UCSR0A |= (1 << U2X0);
18
  #else
19
     /* U2X-Modus nicht erforderlich */
20
     UCSR0A &= ~(1 << U2X0);
21
  #endif
22
23
    UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
24
}
25
26
27
ISR(USART_RX_vect)
28
{
29
   char nUdr = UDR0;
30
   UDR0 = nUdr;
31
}
32
33
int main(void)
34
{
35
  DDRC &= ~(1<<PC0);         // Taster als Eingang
36
    PORTC |= (1<<PC0);
37
  DDRB |= (1<<PB1);
38
39
  USART_INIT();
40
  sei();
41
42
  while(1)
43
  {
44
      while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich                   */
45
        {
46
        }
47
48
49
    if(!(PINC & (1<<PINC0)))
50
    {
51
      
52
 
53
        UDR0 = 'ö';
54
    }
55
  }
56
}

Bis jetzt kommt trotzdem nur Datenschrott an.

Viele Grüße

von Krapao (Gast)


Lesenswert?

> Ist die FUSE 'SUT_CKSEL' noch wichtig, dort steht jetzt noch 'Int. Osc
> 8MHz'?

Ja. Und das versucht man dir die ganze Zeit zu erklären. Du kannst das 
aber auch nachlesen: 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment#Erg.C3.A4nzende_Hinweise_zur_Taktversorgung_.28kann_.C3.BCbersprungen_werden.29 
und im Datenblatt sowieso

von Thomas E. (thomase)


Lesenswert?

Peter R. schrieb:
> Ist die FUSE 'SUT_CKSEL' noch wichtig, dort steht jetzt noch 'Int. Osc
> 8MHz'?
Damit teilst du dem Controller, also diesem kleinen schwarzen Ding 
itself, mit, wo er sich seinen Takt herholen soll. Momentan nimmt er 
seinen internen 8-MHZ-Oszillator. Damit er den Quarz nimmt, stellst du 
ein:
Full Swing Oscillator... Crystal...
Nimm' die letzte der 3 Optionen, die da angeboten werden.

Damit: #define F_CPU 20000000UL
sagst du dem Compiler mit welchem Takt die CPU läuft. Damit der seine 
Zeitberechnungen richtig durchführen kann.

#define F_CPU 20000000UL Da gehört immer ein "UL" hinter.
Dann weiss der Compiler, daß die Zahl ein "unsigned long" ist. Sonst 
hält er das für integer und verrechnet sich.

Das muss beides korrekt eingestellt werden.

mfg.

von Peter R. (Gast)


Lesenswert?

Hallo,

es scheint jetzt wirklich zu gehen.;-) Danke!

Es geht sogar mit dem int.OSC und ohne das 'UL'(ich werd es aber stets 
verwenden^^). Lebenswichtig sind wohl nur SUT_CKSEL, CLKDIV8 und 
natürlich die richtige Verwendung von F_CPU^^.

Habt DANK! Vielen DANK!

LG

von Ingo (Gast)


Lesenswert?

Peter R. schrieb:
> Es geht sogar mit dem int.OSC und ohne das 'UL'(ich werd es aber stets
> verwenden^^). Lebenswichtig sind wohl nur SUT_CKSEL, CLKDIV8 und
> natürlich die richtige Verwendung von F_CPU^^

Na bitte... Fast alle USART Probleme kommen von falschen 
Geschwindigkeitseinstellungen.

Ingo

von Peter R. (Gast)


Lesenswert?

Aber "... man schließt nur EINMAL seinen ERSTEN µC an.";-)

So einen Fehler mache ich kein zweites Mal.^^

Viele Grüße

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.