Forum: Compiler & IDEs Probleme beim auslagern von Funktionen


von Harald (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich arbeite momentan das Tutorial hier im Forum durch und habe hier eine 
Frage zum Auslagern von Funktionen.

Ich habe das Tutorial über den UART mit Interrupts gelesen und habe 
angefangen mir für meine Funktionsbibliothek eine uart.c und uart.h 
anzulegen.

Dann habe ich alle Funktionen ausgelagert und den code drumherum 
geschrieben. Leider bekomme ich beim Kompilieren des Projektes einen 
Fehler, welchen man oben sehen kann.

Ich weiß nicht genau, wo mein Problem ist, da in der delay_basic.h 
nichts von dem "uart_rx_flag" drin steht.

Hier mal der Code:
1
/////////////////////////////////////Main.c
2
3
/*
4
*******************************************************************************
5
*
6
* UART Interrupt Demo
7
*
8
* ATmega32 mit 3,6864 MHz Quarz an XTAL1/XTAL2
9
*
10
* LOW Fuse Byte = 0xFF
11
*
12
* An PD2 muss eine LED mit 1-kOhm-Vorwiderstand angeschlossen werden
13
* An PD0/PD1 ist ein MAX232 angeschlosssen, um Daten vom PC zu empfangen/senden
14
*
15
*******************************************************************************
16
*/
17
// Systemtakt in Hz, das L am Ende ist wichtig, NICHT UL verwenden!
18
#define F_CPU 8000000L   
19
             
20
// "Morsedauer" für ein Bit in Millisekunden
21
#define BITZEIT 100     
22
 
23
#include <avr/io.h>
24
#include <avr/interrupt.h>
25
#include <util/delay.h>
26
#include "uart.h"
27
 
28
// lange, variable Wartezeit, Einheit in Millisekunden
29
void long_delay(uint16_t ms) {
30
    for (; ms>0; ms--) _delay_ms(1);
31
}
32
 
33
34
 
35
// Ein Byte im RS232 Format auf eine LED ausgeben
36
 
37
void morse(uint8_t data) {
38
    uint8_t i;
39
 
40
    // Startbit, immer 0
41
    PORTD &= ~(1 << PD2);           // LED aus
42
    long_delay(BITZEIT);
43
 
44
    for(i=0; i<8; i++) {
45
        if (data & 0x01)            // Prüfe Bit #0
46
            PORTD |= (1 << PD2);    // LED an
47
        else
48
            PORTD &= ~(1 << PD2);   // LED aus      
49
        long_delay(BITZEIT);        
50
        data >>= 1;                 // nächstes Bit auf Bit #0 schieben
51
    }
52
    // Stopbit, immer 1
53
    PORTD |= (1 << PD2);            // LED an
54
    long_delay(BITZEIT);
55
}
56
 
57
// Hauptprogramm
58
 
59
int main (void) {
60
 
61
    char stringbuffer[64];  // Allgemeiner Puffer für Strings
62
    uint8_t buffer_full=0;  // noch ein Flag, aber nur in der Hauptschleife
63
    char * charpointer;     // Hilfszeiger
64
    char test[7] = "Hallo";
65
// IO konfigurieren
66
 
67
    DDRB = 0xFF;
68
    DDRC = 0xFF;
69
    DDRD = 0xFF;
70
 
71
// UART konfigurieren
72
 
73
    UBRRH = UBRR_VAL >> 8;
74
    UBRRL = UBRR_VAL & 0xFF;
75
    UCSRB = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) |(1<<UDRIE); 
76
 
77
// Stringpuffer initialisieren
78
 
79
    stringbuffer[0] = '\n';
80
    stringbuffer[1] = '\r';
81
 
82
// Interrupts freigeben
83
 
84
    sei();
85
    
86
// Endlose Hauptschleife
87
 
88
    while(1) {
89
90
    put_string(test);
91
 
92
        // "Sinnvolle" CPU Tätigkeit 
93
        PORTD &= ~(1<<PD2);
94
        long_delay(300);
95
        PORTD |= (1<<PD2);
96
        long_delay(300);
97
98
    
99
        // Wurde ein kompletter String empfangen 
100
        // und der Buffer ist leer?
101
        if (uart_rx_flag==1 && buffer_full==0) {    
102
            // ja, dann String lesen, 
103
            // die ersten zwei Zeichen 
104
            // aber nicht überschreiben
105
            get_string(stringbuffer+2);             
106
            buffer_full=1;
107
        }
108
 
109
        // Ist letzte Stringsendung abgeschlossen 
110
        // und ein neuer String verfügbar?
111
        if (uart_tx_flag==1 && buffer_full==1) {    
112
            // Newline + Carrige return anfügen
113
            strcat(stringbuffer, "\n\r");           
114
            put_string(stringbuffer); // zurücksenden
115
            buffer_full=0; // Buffer ist wieder verfügbar
116
            // Alle Zeichen per LED morsen
117
            charpointer = stringbuffer;
118
            while(*charpointer) morse(*charpointer++);
119
        }
120
    }
121
}
122
 
123
124
125
126
///////////////////////////////////////////////////uart.h
127
128
#ifndef UART_H
129
#define UART_H
130
131
// Systemtakt in Hz, das L am Ende ist wichtig, NICHT UL verwenden!
132
#define F_CPU 8000000L  
133
134
#include <avr/io.h>
135
#include <avr/interrupt.h>
136
#include <string.h>
137
138
// Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
139
#define BAUD 9600L          
140
 
141
// Berechnungen
142
// clever runden
143
#define UBRR_VAL  ((F_CPU+BAUD*8)/(BAUD*16)-1)  
144
// Reale Baudrate
145
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     
146
// Fehler in Promille 
147
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) 
148
 
149
#if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
150
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
151
#endif
152
153
// globale Variablen für den UART
154
 
155
// Puffergrösse in Bytes, RX und TX sind gleich gross
156
#define uart_buffer_size 32             
157
 
158
char uart_rx_buffer[uart_buffer_size];      // Empfangspuffer
159
char uart_tx_buffer[uart_buffer_size];      // Sendepuffer
160
volatile uint8_t uart_rx_flag=0;            // Flag, String komplett empfangen
161
volatile uint8_t uart_tx_flag=1;            // Flag, String komplett gesendet
162
163
164
void put_string(char *daten);
165
void get_string(char *daten);
166
167
ISR(USART_RX_vect);
168
ISR(USART_UDRE_vect);
169
170
171
172
#endif
173
174
175
//////////////////////////////////////////////////////uart.c
176
177
#include "uart.h"
178
179
// einen String senden
180
// vor Aufruf der Funktion muss man prüfen, ob uart_t_flag==1 ist
181
// nur dann kann ein neuer String gesendet werden
182
 
183
void put_string(char *daten) {
184
 
185
   if (uart_tx_flag==1) {
186
      // String daten ind en Sendepuffer kopieren
187
      strcpy(uart_tx_buffer, daten);      
188
      // Flag für 'Senden ist komplett' löschen, 
189
      uart_tx_flag = 0;                    
190
      // UDRE Interrupt einschalten, los gehts
191
      UCSRB |= (1<<UDRIE); 
192
   }
193
}
194
 
195
// einen empfangenen String kopieren
196
// vor Aufruf der Funktion muss man prüfen, ob uart_rx_flag==1 ist
197
// anderenfalls ist der RX Buffer noch ungültig
198
 
199
void get_string(char *daten) {
200
 
201
   if (uart_rx_flag==1) {
202
      // String kopieren
203
      strcpy(daten, uart_rx_buffer);      
204
      // Flag löschen
205
      uart_rx_flag = 0;                    
206
   }
207
}
208
209
// UART RX complete interrupt
210
 
211
// hier werden Daten vom PC empfangen und in einem String zwischengespeichert
212
// Wird ein Stringterminator empfangen, wird ein Flag gesetzt, welches dem 
213
// Hauptprogramm den kompletten Empfang signalisiert
214
 
215
ISR(USART_RX_vect) {
216
    
217
    static uint8_t uart_rx_cnt;     // Zähler für empfangene Zeichen
218
    uint8_t data;
219
 
220
    // Daten auslesen, dadurch wird das Interruptflag gelöscht              
221
    data = UDR;
222
    
223
    // Ist Puffer frei für neue Daten? 
224
    if (!uart_rx_flag) {
225
        // ja, ist Ende des Strings (RETURN) erreicht?
226
        if (data=='\r') {
227
            // ja, dann String terminieren
228
            uart_rx_buffer[uart_rx_cnt]=0;              
229
            // Flag für 'Empfangspuffer voll' setzen
230
            uart_rx_flag=1;
231
            // Zähler zurücksetzen
232
            uart_rx_cnt=0;
233
        }
234
        else if (uart_rx_cnt<(uart_buffer_size-1)) {     
235
            // Daten in Puffer speichern
236
            // aber durch if() Pufferüberlauf vermeiden
237
            uart_rx_buffer[uart_rx_cnt]=data;          
238
            uart_rx_cnt++; // Zähler erhöhen
239
        }
240
    }
241
}
242
 
243
// UART TX data register empty interrupt
244
// hier werden neue Daten in das UART-Senderegister geladen
245
 
246
ISR(USART_UDRE_vect) {
247
    // Zeiger auf Sendepuffer
248
    static char* uart_tx_p = uart_tx_buffer;    
249
    uint8_t data;
250
 
251
    // zu sendendes Zeichen lesen, 
252
    // Zeiger auf Sendepuffer erhöhen
253
    data = *uart_tx_p++;
254
    
255
    // Ende des nullterminierten Strings erreicht?
256
    if (data==0 ) {        
257
        UCSRB &= ~(1<<UDRIE);       // ja, dann UDRE Interrupt ausschalten        
258
        uart_tx_p = uart_tx_buffer; // Pointer zurücksetzen
259
        uart_tx_flag = 1;           // Flag setzen, Übertragung beeendet
260
    }
261
    else UDR = data;                // nein, Daten senden
262
}

von Harald (Gast)


Lesenswert?

Ich habe den Fehler wohl selbst gefunden.

Man darf im Header keine Wertzuweisung unternehmen. Das sollte man in 
der .c machen.

Falls es jemandem hilft.

von Harald (Gast)


Lesenswert?

Jetzt ist mir aber noch eine Unklarheit gekommen.

Ich habe meine F_CPU 8000000L definiert. Wenn ich jetzt in meiner uart.h 
die F_CPU definiere UND in der main.c ist alles paletti. Wenn ich nur 
eine von beiden definiere bekomme ich eine Warnung, dass nicht definiert 
wurde.

Ich wurde aber aus Gründen der Bequemlichkeit und Fehleranfälligkeit 
gerne ALLE F_CPU Definitionen EINMAL im makefile machen wollen.

Wenn ich dann allerdings im makefile meine F_CPU definiere erhalte ich 
eine Fehlermeldung, dass redefined wurde.

Wenn ich jetzt aus den ganzen files meine F_CPU Definition rausnehme 
läuft aber die Berechnung von UBRR nicht mehr!

Gibt es eine Möglichkeit das alles in EINEM Rutsch zu erledigen?

Ich danke euch.

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.