Hallo, #define STX PD1 ... befindet sich in der Header - Datei Kann ich diese Variable in meinem Hauptprogramm ändern? Würde gerne PD2 zuweisen. Danke für eure Hilfe. MfG Sabine
das ist keine Variable, sonder nur eine Ersetzung Welche Sprache soll das sein? Wenn C dann so z.B. in H-Datei: extern int globaleVariable; in C-Datei: int globaleVariable = 0; void main(void) { globaleVariable = 1; }
Sabine F. schrieb: > #define STX PD1 ... befindet sich in der Header - Datei > > > > Kann ich diese Variable in meinem Hauptprogramm ändern? Würde gerne PD2 > > zuweisen. Nein, das geht definitiv nicht...
Sabine F. schrieb: > Kann ich diese Variable in meinem Hauptprogramm ändern? Das ist keine Variable, das ist eine simple Textersetzung! Einfach mal nach '#ifdef' googeln ... '#undef' ist das Zauberwort
Danke für deinen Tipp =) Ja verwende C, kann man auch die 'Ersetzung' ändern? Kann ich vom Hauptprogramm die Ersetzung in Headerdatei ändern. Möchte nämlich zu Beginn PD1 verwenden und während des Progammes möchte ich sie gerne auf PD2 setzen. Geht das?
Sabine F. schrieb: > Kann ich vom Hauptprogramm die Ersetzung in Headerdatei ändern. > Möchte nämlich zu Beginn PD1 verwenden und während des Progammes möchte > ich sie gerne auf PD2 setzen. Geht das? Du begreifst es nicht. ein define ist KEINE Variable, das ist eine Textersetzung, die vor dem compilieren durch den Präprozessor erfolgt. Zur Laufzeit kannst du nur in Variablen etwas ändern Du brauchst ein C Buch!
"Vor" dem kompilieren ist das Stichwort. Ist das Programm erst einmal auf dem Controller, lässt sich an einer festen #define Zuweisung nichts mehr ändern. (Das # Zeichen bezeichnet Präprozessoranweisungen, die bei der Erzeugung des Maschinencodes als erste behandelt werden). Warum nimmst du nicht einfach eine zweite Zeile á la "#define STX_initial PD1" hinzu, verwendest diese Zuweisung eben nur einmal beim Start und danach immer STX (dem zu PD2 zugewiesen hast)? Es gibt sicher auch noch andere Lösungen, aber deine ursprüngliche Idee ist definitiv keine davon.
Wie kann man dieses Problem sonst lösen? #define STX PD5 Möchte PD5 auf PD4 ändern können, damit ich zweimal das selbe auf zwei Software - UARTs senden kann. Wie könnte dies funktionieren?
1 | #include "main.h" |
2 | #include "suart.h" |
3 | |
4 | |
5 | |
6 | #define BIT_TIME (u8)((XTAL / BAUD) / PRESCALE)
|
7 | |
8 | |
9 | volatile u8 stx_count; |
10 | u8 stx_data; |
11 | |
12 | volatile u8 srx_done; |
13 | u8 srx_data; |
14 | u8 srx_mask; |
15 | u8 srx_tmp; |
16 | |
17 | void suart_init( void ) |
18 | {
|
19 | SBIT(PORTD,STX) = 1; |
20 | // OCR0A = TCNT0 + 1; // force first compare
|
21 | // TCCR0A = 0; // Default: Normal port operation
|
22 | TCCR0B = 1 << CS01 | 1<<CS00; // clk/64 |
23 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
24 | TIMSK0 = 1 << OCIE0A; // enable output compare interrupt |
25 | |
26 | EICRA = 1 << ISC01; // falling edge |
27 | EIMSK = 1 << INT0; // enable edge interrupt |
28 | |
29 | stx_count = 0; // nothing to sent |
30 | srx_done = 0; // nothing received |
31 | STXDDR |= 1 << STX; // TX output |
32 | }
|
33 | |
34 | |
35 | u8 sgetchar (void) // get byte |
36 | {
|
37 | while (!srx_done); // wait until byte received |
38 | srx_done = 0; |
39 | return srx_data; |
40 | }
|
41 | |
42 | |
43 | ISR (INT0_vect) // rx start |
44 | {
|
45 | OCR0B = TCNT0 + (u8)((BIT_TIME * 3) / 2);// scan 1.5 bits after start |
46 | |
47 | srx_tmp = 0; // clear bit storage |
48 | srx_mask = 1; // bit mask |
49 | if( !(SRXPIN & 1<<SRX)) { // still low |
50 | EIMSK &= ~(1 << INT0); // disable edge interrupt |
51 | TIMSK0 = 1<<OCIE0A^1<<OCIE0B; // wait for first bit |
52 | }
|
53 | TIFR0 = 1<<OCF0B; // clear pending interrupt ? why does that output compare int occur? |
54 | EIFR |= (1 << INTF0); // clear any pending edge interrupt |
55 | }
|
56 | |
57 | |
58 | ISR (TIMER0_COMPB_vect) |
59 | {
|
60 | u8 in = SRXPIN; // scan rx line |
61 | // PORTB = 0x00;
|
62 | if (srx_mask) { |
63 | if (in & 1 << SRX) |
64 | srx_tmp |= srx_mask; |
65 | srx_mask <<= 1; |
66 | OCR0B += BIT_TIME; // next bit slice |
67 | } else { |
68 | srx_done = 1; // mark rx data valid |
69 | srx_data = srx_tmp; // store rx data |
70 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
71 | TIMSK0 = 1<<OCIE0A; // enable tx and wait for start |
72 | EIFR |= (1 << INTF0); // clear any pending edge interrupt: This hinders the in0-vect from beeing triggerd again just now which may occur by falling edges in the serial data bits |
73 | EIMSK = 1 << INT0; // reenable edge interrupt |
74 | }
|
75 | // PORTB = 0x02;
|
76 | }
|
77 | |
78 | |
79 | void sputchar (u8 val) // send byte |
80 | {
|
81 | while (stx_count); // until last byte finished |
82 | stx_data = ~val; // invert data for Stop bit generation |
83 | stx_count = 10; // 10 bits: Start + data + Stop |
84 | }
|
85 | |
86 | |
87 | void sputs (u8 *txt) // send string |
88 | {
|
89 | while (*txt) |
90 | sputchar (*txt++); |
91 | }
|
92 | |
93 | |
94 | ISR (TIMER0_COMPA_vect) // tx bit |
95 | {
|
96 | u8 dout; |
97 | u8 count; |
98 | |
99 | OCR0A += BIT_TIME; // next bit slice |
100 | count = stx_count; |
101 | |
102 | if (count) { |
103 | stx_count = --count; // count down |
104 | // ??? dout = 1<<COM0A1; // set low on next compare
|
105 | dout = 0; |
106 | if (count != 9) { // no start bit |
107 | if (!(stx_data & 1)) // test inverted data |
108 | //??? dout = 1<<COM0A1^1<<COM0A0; // set high on next compare
|
109 | dout = 1; |
110 | stx_data >>= 1; // shift zero in from left |
111 | }
|
112 | // TCCR0A = dout;
|
113 | // STX = (dout == 0) ? 1 : 0;
|
114 | SBIT(PORTD,STX) = dout; |
115 | }
|
116 | }
|
Sabine F. schrieb: > Möchte PD5 auf PD4 ändern können, damit ich zweimal das selbe auf zwei > Software - UARTs senden kann. Dann brauchst du zwei Variablen.
> Möchte PD5 auf PD4 ändern können, damit ich zweimal das selbe auf > zwei Software - UARTs senden kann. > > Wie könnte dies funktionieren? Indem du das implementierst, was das logischte ist: eine 2.te Software UART HIer ist deine erste
1 | void suart_init_1( void ) |
2 | {
|
3 | SBIT(PORTD,STX_1) = 1; |
4 | // OCR0A = TCNT0 + 1; // force first compare
|
5 | // TCCR0A = 0; // Default: Normal port operation
|
6 | TCCR0B = 1 << CS01 | 1<<CS00; // clk/64 |
7 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
8 | TIMSK0 = 1 << OCIE0A; // enable output compare interrupt |
9 | |
10 | EICRA = 1 << ISC01; // falling edge |
11 | EIMSK = 1 << INT0; // enable edge interrupt |
12 | |
13 | stx_count = 0; // nothing to sent |
14 | srx_done = 0; // nothing received |
15 | STXDDR_1 |= 1 << STX_1; // TX output |
16 | }
|
und sukzessive für alle anderen Funktionen: Allem was UART spezifisch ist, verpasst du eine angehängte _1. Aus STX wird STX_1, aus suart_init wird suart_init_1, aus sputchar wird sputchar_1, etc. etc. und dann implementierst du alles nochmal, wobei du anstelle der _1 dann eben eine _2 hast. Voila: 2 Software UART, die sauber in allen Belangen voneinander getrennt sind. Edit: In den höhreren Software Schichten könnte man das auch ein wenig eleganter machen, aber im Hinblick auf deine C-Kentnisse nehme ich davon mal Abstand. Einfach realisierbar und für dich durchschaubar lautet die Devise.
Sabine F. schrieb: > Möchte PD5 auf PD4 ändern können, damit ich zweimal das selbe auf zwei > Software - UARTs senden kann. Dann schmeiß STX und SRX komplett aus der Headerdatei raus um sicherzustellen, dass sie tatsächlich auch sonst niemand benutzt. In der Implementierungsdatei schreibst du dann:
1 | #define STX PD5
|
2 | #define SRX PD6
|
3 | |
4 | // Implementierung der 1. Software-UART
|
5 | |
6 | #undef STX
|
7 | #undef SRX
|
8 | |
9 | #define STX PD4
|
10 | #define SRX PD3
|
11 | |
12 | // Implementierung der 2. Software-UART
|
13 | |
14 | #undef STX
|
15 | #undef SRX
|
Edit: unterscheidet sich von Karl-Heinz' Vorschlag nur geringfügig in der Form, die Grundzüge der Implementierung bleiben zwischen uns beiden gleich.
Wobei: Mit dieser Interrupt getriebenen SW-UART
1 | TCCR0B = 1 << CS01 | 1<<CS00; // clk/64 |
2 | // TIFR0 = 1<<ICF1; // clear pending interrupt
|
3 | TIMSK0 = 1 << OCIE0A; // enable output compare interrupt |
4 | |
5 | EICRA = 1 << ISC01; // falling edge |
6 | EIMSK = 1 << INT0; // enable edge interrupt |
könnte es interessant werden, eine 2. SW-UART aufzusetzen, die Timer-Interrupt getrieben das richtige tut und man keinen funktional gleichwertigen Timer mehr übrig hat. Insofern nehm ich meine implizite Aussage von weiter oben, das das mit kleinen Modifikationen geht, wieder zurück. Da hab ich mir das alles nicht besonders gut angesehen.
Ich will nicht zwei Uarts gleichzeitig benützen, es reicht mir auch, wenn sie hintereinander etwas senden können, sprich daten auf PD4 und dann PD5. Ist es nicht möglich PD4 mit einer Anweisung auf PD5 umschalten zu können?
Sabine F. schrieb: > Ich will nicht zwei Uarts gleichzeitig benützen, es reicht mir auch, > wenn sie hintereinander etwas senden können, sprich daten auf PD4 und > dann PD5. Ist es nicht möglich PD4 mit einer Anweisung auf PD5 > umschalten zu können? nein, dann must du UART-Routinen so umschreiben, das an allen Stellen, an denen die define's verwendet werden entweder direkt mit Variablen gearbeitet wird. Oder noch mal eine Fallunterscheidung durchgeführt wird. z.B. uint8 SRX; ... //UART A SRX=1<<PD4; if( !(SRXPIN & SRX)) //PD4 abfragen //umschalten auf UART B SRX=1<<PD6; if( !(SRXPIN & SRX)) //PD6 abfragen Sascha
Habe jetzt die Software - Uart in eine neue Klasse geschrieben und eine zusätzliche Headerdatei geschrieben. Jedoch bekomme ich beim Ausführen einen Error. make: *** [SoftwareUART.elf] Fehler 1
Die erste Header - Datei:
1 | #define SRX PD6
|
2 | #define SRXPIN PIND
|
3 | |
4 | #define STX PD5 //Pinbelegung Datasheet (OC1A) #define STX PD4
|
5 | #define STXDDR DDRD
|
6 | |
7 | extern volatile u8 srx_done; |
8 | |
9 | #define kbhit() (srx_done) // true if byte received
|
10 | |
11 | void suart_init( void ); |
12 | void sputchar( u8 val ); |
13 | u8 sgetchar( void ); |
14 | void sputs( u8 *txt ); |
15 | |
16 | struct bits { |
17 | u8 b0:1; |
18 | u8 b1:1; |
19 | u8 b2:1; |
20 | u8 b3:1; |
21 | u8 b4:1; |
22 | u8 b5:1; |
23 | u8 b6:1; |
24 | u8 b7:1; |
25 | } __attribute__((__packed__)); |
26 | |
27 | #define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
|
28 | #define SBIT(x,y) SBIT_(x,y)
|
Die zweite Header - Datei:
1 | #define SRX1 PD6
|
2 | #define SRXPIN1 PIND
|
3 | |
4 | #define STX1 PD4 //Pinbelegung Datasheet (OC1A) #define STX PD4
|
5 | #define STXDDR1 DDRD
|
6 | |
7 | extern volatile u8 srx_done1; |
8 | |
9 | #define kbhit() (srx_done1) // true if byte received
|
10 | |
11 | void suart_init1( void ); |
12 | void sputchar1( u8 val ); |
13 | u8 sgetchar1( void ); |
14 | void sputs1( u8 *txt ); |
15 | |
16 | struct bits1 { |
17 | u8 b0:1; |
18 | u8 b1:1; |
19 | u8 b2:1; |
20 | u8 b3:1; |
21 | u8 b4:1; |
22 | u8 b5:1; |
23 | u8 b6:1; |
24 | u8 b7:1; |
25 | } __attribute__((__packed__)); |
26 | |
27 | #define SBIT_1(port,pin) ((*(volatile struct bits1*)&port).b##pin)
|
28 | #define SBIT1(x,y) SBIT_1(x,y)
|
Darf ich das so machen?
Die Software - UART habe ich einfach nochmal kopiert, nun zwei getrennte Klassen. Wie könnte es sonst gehn?
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.