Forum: Mikrocontroller und Digitale Elektronik Variable in der Headerdatei


von Sabine F. (Gast)


Lesenswert?

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

von Children (Gast)


Lesenswert?

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

von Udo S. (urschmitt)


Lesenswert?

Was willst du erreichen?

von cskulkw (Gast)


Lesenswert?

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...

von Ralf G. (ralg)


Lesenswert?

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

von Sabine F. (Gast)


Lesenswert?

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?

von Udo S. (urschmitt)


Lesenswert?

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!

von Guest (Gast)


Lesenswert?

"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.

von Sabine F. (Gast)


Lesenswert?

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
}

von Ralf G. (ralg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Sabine F. (Gast)


Lesenswert?

Vielen Dank, werde es versuchen.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Sabine F. (Gast)


Lesenswert?

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?

von Sascha W. (sascha-w)


Lesenswert?

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

von Sabine F. (Gast)


Lesenswert?

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

von Sabine F. (Gast)


Lesenswert?

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?

von Sabine F. (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.