Forum: Compiler & IDEs #define Ports


von Mark P. (pisy)


Angehängte Dateien:

Lesenswert?

Hallo,
ich arbeite an einer Einzelspannungserfassung und zwar geschieht dies 
über Multiplexer, einer dieser Multiplexer wird über PB1 "enabled", dass 
muss ich jetzt ändern weil über PB1 mein PWM funktioniert.
Kurz ein Programmausschnitt:


#define aus    PORTB=0b00000000;

#define Zelle1    PORTB=0b00010000;
#define Zelle2    PORTB=0b00110000;
#define Zelle3    PORTB=0b00011000;
#define Zelle4    PORTB=0b00111000;
#define Zelle5    PORTB=0b00010100;
#define Zelle6    PORTB=0b00110100;
#define Zelle7    PORTB=0b00011100;
#define Zelle8    PORTB=0b00111100;

#define Zelle9    PORTB=0b00000010;
#define Zelle10    PORTB=0b00100010;
#define Zelle11    PORTB=0b00001010;
#define Zelle12    PORTB=0b00101010;
#define Zelle13    PORTB=0b00000110;
#define Zelle14    PORTB=0b00100110;
#define Zelle15    PORTB=0b00001110;
#define Zelle16    PORTB=0b00101110;

#define Zelle17   PORTB=0b00000001;
#define Zelle18   PORTB=0b00100001;
#define Zelle19   PORTB=0b00001001;
#define Zelle20    PORTB=0b00101001;
#define Zelle21   PORTB=0b00000101;
#define Zelle22   PORTB=0b00100101;
#define Zelle23   PORTB=0b00001101;
#define Zelle24   PORTB=0b00101101;

//---------------------------------------------------------------------- 
--
// Initialisierungen
//---------------------------------------------------------------------- 
--
void init()
{
  // Ports initialisieren
  sbi(DDRB,0);   // (Enable Zelle 17-24)
  sbi(DDRB,1);   // (Enable Zelle  9-16)
  sbi(DDRB,2);   // Multiplexer A2
  sbi(DDRB,3);   // Multiplexer A1
  sbi(DDRB,4);   // (Enable Zelle  1-8)
  sbi(DDRB,5);   // Multiplexer A0




Es geht jetzt um folgendes, ich habe die Verbindung vom Multiplexer auf 
PD7 umgelötet. Im folgenden habe ich das Bit welches den Plexer 
einschaltet mit Apostrophen markiert.

#define Zelle9    PORTB=0b000000'1'0;
#define Zelle10    PORTB=0b001000'1'0;
#define Zelle11    PORTB=0b000010'1'0;
#define Zelle12    PORTB=0b001010'1'0;
#define Zelle13    PORTB=0b000001'1'0;
#define Zelle14    PORTB=0b001001'1'0;
#define Zelle15    PORTB=0b000011'1'0;
#define Zelle16    PORTB=0b001011'1'0;

Mein Plan wäre es jetzt die Bits einzeln zu definieren und das 
"Enable"-Bit des Plexers auf PD7 zu ziehen. Ich habe leider zu wenig 
Erfahrung um es jetzt eleganter auszudrücken. Es sollte sowas werden wie 
eine Kombinations aus Bits von zwei Ports, ich hoffe ihr versteht was 
ich meine.

#define Zelle9 
PORTB&=~(1<<DDB7)|(1<<DDB6)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2)|(1<< 
DDB1)|(1<<DDB0)  && PORTD=(1<<DDD1)

Geht das so? Oder ist der Plan total verwerflich, oder gibt es noch 
andere Möglichkeiten?

Gruß

von Mark P. (Gast)


Lesenswert?

Okay es geht nicht so, habs gescoped. Wie kann ich ein Bit von einem 
anderen Port D in B einbinden

von Karl H. (kbuchegg)


Lesenswert?

Mark Pisani schrieb:

> Geht das so? Oder ist der Plan total verwerflich, oder gibt es noch
> andere Möglichkeiten?
1
#define Zelle9    do { PORTB = 0b00000000; PORTD |= 0b00000010; } while( 0 )

Ich denke aber die bessere Lösung wäre den MPlexer direkter 
anzusprechen.
1
#define MPLEX_PORT  PORTD
2
#define MPLEX_BIT   PD1
3
4
#define MPLEX_ON  do { MPLEX_PORT |= ( 1 << MPLEX_BIT ); } while( 0 )
5
#define MPLEX_OFF do { MPLEX_PORT &= ~( 1 << MPLEX_BIT ); } while( 0 )
6
7
...
8
9
#defien Zelle9   do { PORTB = 0b00000000; MPLEX_ON; } while( 0 )

bzw. aus den Zellen Makros das Setzen und Löschen der Multiplexer Bits 
rauszulassen.

von Mark P. (pisy)


Angehängte Dateien:

Lesenswert?

Hi,
hat bestens funktioniert danke.
Aber noch ist das ganze nicht einwandfrei.
Die Spannungen an Zelle 1 und Zelle 11-16 werden nicht richtig 
ausgegeben. Zelle1 zeigt einen zu hohen Wert an 11-16 0. Mir ist 
aufgefallen, dass der PWM über Timer 1 Port B1 und B2 braucht. Das ist 
natürlich doof wenn ich die Bits z.B. mit dem Muster 0b01000111 
beschreibe oder gar mit 0b00000000 lösche. Ich bringe den Controller ja 
intern irgendwie durcheinander.
Also habe ich das Programm umgeschrieben, jetzt setze ich jedes Bit 
einzeln. Und lösche die dannach wieder, ähnlich wie Karl oben 
beschrieben hat.
Trotzdem hab ich wie gesagt die Fehler in der Ausgabe, vielliecht fällt 
einem ja noch was auf. Bin auch schon auf der Suche:
1
#define aus PORTD&=~(1<<DDD7)|(1<<DDD6);
2
#define aus2 PORTB&=~(1<<DDB7)|(1<<DDB6)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2);
3
4
#define Zelle1    do {PORTB=(1<<DDB4);} while (0)//PORTB=0b00010000;
5
#define Zelle2    do {PORTB=(1<<DDB5)|(1<<DDB4);} while (0)//PORTB=0b00110000;
6
#define Zelle3    do {PORTB=(1<<DDB3)|(1<<DDB4);} while (0)//PORTB=0b00011000;
7
#define Zelle4    do {PORTB=(1<<DDB3)|(1<<DDB3)|(1<<DDB4);} while (0)//PORTB=0b00111000;
8
#define Zelle5    do { PORTB=(1<<DDB4); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00010100
9
#define Zelle6    do { PORTB=(1<<DDB5)|(1<<DDB4); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00110100
10
#define Zelle7    do { PORTB=(1<<DDB4)|(1<<DDB3); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00011100
11
#define Zelle8    do { PORTB=(1<<DDB5)|(1<<DDB4)|(1<<DDB3); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00111100
12
13
#define Zelle9    do { PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00000010;//
14
#define Zelle10    do { PORTB = (1<<DDB5); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00100010;//
15
#define Zelle11    do { PORTB = (1<<DDB3); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00001010;// 
16
#define Zelle12    do { PORTB = (1<<DDB5)|(1<<DDB3); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00101010;//
17
#define Zelle13    do { PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00000110;//
18
#define Zelle14    do { PORTB = (1<<DDB5); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00100110;//
19
#define Zelle15    do { PORTB = (1<<DDB3); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00001110;//
20
#define Zelle16    do { PORTB = (1<<DDB3)|(1<<DDB5); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00101110;//
21
22
#define Zelle17   do {PORTB=(1<<DDB0); } while( 0 )//0b00000001;
23
#define Zelle18   do {PORTB=(1<<DDB5)|(1<<DDB0); } while( 0 )//0b00100001;
24
#define Zelle19   do {PORTB=(1<<DDB3)|(1<<DDB0); } while( 0 )//0b00001001;
25
#define Zelle20    do {PORTB=(1<<DDB5)|(1<<DDB3)|(1<<DDB0); } while( 0 )//0b00101001;
26
#define Zelle21   do {PORTB=(1<<DDB0); PORTD = (1<<DDD6); } while( 0 )//0b00000101;
27
#define Zelle22   do {PORTB=(1<<DDB5)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00100101;
28
#define Zelle23   do {PORTB=(1<<DDB3)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00001101;
29
#define Zelle24   do {PORTB=(1<<DDB5)|(1<<DDB3)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00101101;
30
31
void init()
32
{
33
  // Ports initialisieren
34
  sbi(DDRB,0);   // (Enable Zelle 17-24)
35
  //sbi(DDRB,1);   // (Enable Zelle  9-16)
36
  //sbi(DDRB,2);   // Multiplexer A2 
37
  sbi(DDRB,3);   // Multiplexer A1 
38
  sbi(DDRB,4);   // (Enable Zelle  1-8)
39
  sbi(DDRB,5);   // Multiplexer A0#
40
  sbi(DDRD,6);  // Multiplexer A2
41
  sbi(DDRD,7);  // (Enable Zelle 9-16)
42
43
  // Port Belegung Regelung
44
  //DDRB|=(1<<DDB1);  // PWM
45
  DDRC&=~(1<<DDC2);  // Lem Strom Pidsense
46
  DDRC&=~(1<<DDC0);  // Lem Strom Pidsense
47
  //----------------------------------------------------------
48
49
  // UART initialisieren
50
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
51
  UCSRB = 8 + 16;           //Sender enable UCSRB / UCR bei z.B.: 2313
52
}
53
54
int set_output(int celnumber)
55
{
56
  switch (celnumber)
57
  {
58
59
    case 1: do 
60
    {
61
    Zelle1; aus;aus2;
62
    }
63
    while(0);// Zelle1;
64
    break;
65
66
    case 2: do 
67
    {
68
    Zelle2; aus;aus2;
69
    }
70
    while(0);//Zelle2;
71
    break;
72
73
    case 3: do 
74
    {
75
    Zelle3; aus;aus2;
76
    }
77
    while(0);//Zelle3;
78
    break;
79
80
    case 4: do 
81
    {
82
    Zelle4; aus;aus2;
83
    }
84
    while(0);//Zelle4;
85
    break;
86
87
    case 5: do 
88
    {
89
    Zelle5; aus;aus2;
90
    }
91
    while(0);//Zelle5;
92
    break;
93
94
    case 6: do 
95
    {
96
    Zelle6; aus;aus2;
97
    }
98
    while(0);//Zelle6;
99
    break;
100
101
    case 7: do 
102
    {
103
    Zelle7; aus;aus2;
104
    }
105
    while(0);//Zelle7;
106
    break;
107
108
    case 8: do 
109
    {
110
    Zelle8; aus;aus2;
111
    }
112
    while(0);//Zelle8;
113
    break;
114
115
    case 9: do 
116
    {
117
    Zelle9; aus;aus2;
118
    }
119
    while(0);//Zelle9;
120
    break;
121
122
    case 10: do 
123
    {
124
    Zelle10; aus;aus2;
125
    }
126
    while(0);//Zelle10;
127
    break;
128
129
    case 11: do 
130
    {
131
    Zelle11; aus;aus2;
132
    }
133
    while(0);//Zelle11;
134
    break;
135
136
    case 12: do 
137
    {
138
    Zelle12; aus;aus2;
139
    }
140
    while(0);//Zelle12;
141
    break;
142
143
    case 13: do 
144
    {
145
    Zelle13; aus;aus2;
146
    }
147
    while(0);//Zelle13;
148
    break;
149
150
    case 14: do 
151
    {
152
    Zelle14; aus;aus2;
153
    }
154
    while(0);//Zelle14;
155
    break;
156
157
    case 15: do 
158
    {
159
    Zelle15; aus;aus2;
160
    }
161
    while(0);//Zelle15;
162
    break;
163
164
    case 16: do 
165
    {
166
    Zelle16; aus;aus2;
167
    }
168
    while(0);//Zelle16;
169
    break;
170
171
    case 17: do 
172
    {
173
    Zelle17; aus;aus2;
174
    }
175
    while(0);//Zelle17;
176
    break;
177
178
    case 18: do 
179
    {
180
    Zelle18; aus;aus2;
181
    }
182
    while(0);//Zelle18;
183
    break;
184
185
    case 19: do 
186
    {
187
    Zelle19; aus;aus2;
188
    }
189
    while(0);//Zelle19;
190
    break;
191
192
    case 20: do 
193
    {
194
    Zelle20; aus;aus2;
195
    }
196
    while(0);//Zelle20;
197
    break;
198
199
    case 21: do 
200
    {
201
    Zelle21; aus;
202
    }
203
    while(0);//Zelle21;
204
    break;
205
206
    case 22: do 
207
    {
208
    Zelle22; aus;aus2;
209
    }
210
    while(0);//Zelle22;
211
    break;
212
213
    case 23: do 
214
    {
215
    Zelle23; aus;aus2;
216
    }
217
    while(0);//Zelle23;
218
    break;
219
220
    case 24: do 
221
    {
222
    Zelle24; aus;aus2;
223
    }
224
    while(0);//Zelle24;
225
    break;
226
227
    default: do
228
    {
229
      aus;
230
    }
231
    while (0);
232
233
    break;
234
235
  }
236
  //end switch

Für Tips oder Hilfen wäre ich sehr dankbar.
Quelltext im Anhang

von Sven P. (Gast)


Lesenswert?

Je nachdem, wo und wie du das benutzt, würde ich mal ganz furchtbar 
stark über inline-Funktionen nachdenken...

von Mark P. (Gast)


Lesenswert?

Was meinst du mit Inline Funktionen?
Ich bin noch Frischling mit GCC
Auf jeden Fall liegt es wohl daran, dass Pin D7 nicht auf high gezogen 
wird. Hab ich mit dem Scope eben gemessen, aber ich benutze D7 doch 
nirgendwo anders

von Oliver (Gast)


Lesenswert?

Welcher Prozessor?

Oliver

von Mark P. (Gast)


Lesenswert?

ATMege8 ext Quarz 14745600

von Karl H. (kbuchegg)


Lesenswert?

Mir ist noch nicht wirklich klar, wie dein Multiplexer funktioniert.

In set_output setzt du erst einige Port Bits, nur um sie gleich darauf 
wieder zu löschen. Woher weiß jetzt eigentlich der Multiplexer, was denn 
nun gilt?

Erwartet hätte ich, dass du den Multiplexer einstellst, dann die Messung 
machst und dann den Multiplexer ev. wieder löscht (wozu eigentlich?)

Und diese Bitorgie da oben samt dem Mega-switch. Schön ist was anderes. 
Das kann man doch auch einfacher lösen (wobei ich deinem Fall gar nicht 
mehr so sicher bin, ob das Aufdröseln in Bitnamen so schlau ist. 
Übersichtlich, im Sinne von "Auf einen Blick erkennbar wo die 
Unterschiede liegen" ist das nicht. Da würde ich 2 Arrays benutzen, was 
dann auch den Vorteil hat, dass sich der ganze switch in Luft auflöst 
und durch 2 Arrayzugriffe ersetzt wird.

von Klaus F. (kfalser)


Lesenswert?

> Für Tips oder Hilfen wäre ich sehr dankbar.

Warum gibst Du das Ganze nicht in eine Tabelle?

z.B.
uint8_t Zelle[MAXZEILEN] = { 0b0001010, 0b000100.. .... usw };

und dann
PORTB = Zelle[celnumber];

Das ist ziemlich sicher scheller, und in jedem Falle übersichtlicher.

Dein Code enthält viele Dinge, die man so nicht machen sollte :
- Defines und Macros werden immer groß geschrieben (Konvention), also 
wenn schon ZELLE1, ZELLE2 usw.
- Man unterscheidet zwischen Macros und Defines
Defines verwendet man um Konstanten zu definieren und Macro als eine Art 
Funktionen.
In deinem Fall wird im #define Code ausgeführt, es sollte also wie ein 
Macro ausschauen, auch wenn es keine Parameter hat.
Du solltest also wenn schon

#define ZELLE1() PORTB = 0b000001000

schreiben.

Das selbe gilt für die Macros "aus", "aus2", also AUS(), AUS2()

- Die Direction Ports Register DDR brauchen nicht immer umgesetzt zu 
werden. Man initialisiert sie 1x am Anfang des Programmes als Ausgang 
oder Eingang, je nach Hardware. Die einzige Ausnahme ist wenn man 
wirklich an einem Port einmal etwas einlesen und dann wieder was 
auslesen muß, also so eine Art Bus.

- sbi ist obsolet

von Mark P. (Gast)


Lesenswert?

Ich habe noch nit mit einer Tabelle gearbeitet in C.
Tut mir leid, wenn ich mich ein bisschen doof stelle, aber ich bin ja 
lernwillig.
Ist das dann so gemeint? Bei 24 Zellen einen Array zu erstellen

unit8_t Zelle[23] = {Adresse1, Adresse2, Adresse3,....Adressen24};??

Wenn ja wie schreibe ich so ein Array über mehrere Zeilen, dass wird ja 
ziemlich lang? Und vor allem wie bringe ich dann die Pinne von PortD mit 
rein?


Dann soll ich:

PORTB = Zelle[celnumber];

Ich denke mal über einen Counter durchzählen, nur hab ich ja Bits auf 
PortB und D darin, was das ganze ja nicht einfacher macht.
Müsste ich dann zwei Tabellen erstellen, eine für PORTB und eine für 
PORTD?

Angenommen es ist dann so eingestellt im den Durchlauf, dann kann ich 
immer noch über result=spannung(); mein Ergebnis abspeichern?

von Karl H. (kbuchegg)


Lesenswert?

Mark P. schrieb:
> Ich habe noch nit mit einer Tabelle gearbeitet in C.

Dann wirds Zeit.

uint8_t a[24];

stellt dir ein Feld von 24 Variablen bereit, die durch eine Nummer 
unterschieden werden.

  a[0], a[1], a[2], ... a[23]

zähl nach. Sind genau 24 Stück.

Der Clou besteht jetzt darin, dass man in der Verwendung dieses Feldes 
die Nummern nicht als Zahl angeben muss, sondern man einen beliebigen 
arithmetischen Ausdruck benutzen kann, dessen Ergebnis nur im Bereich 0 
bis 23 liegen muss.

> Tut mir leid, wenn ich mich ein bisschen doof stelle, aber ich bin ja
> lernwillig.

Du solltest dir ein Buch zulegen.

> Ist das dann so gemeint? Bei 24 Zellen einen Array zu erstellen
>
> unit8_t Zelle[23] = {Adresse1, Adresse2, Adresse3,....Adressen24};??
>
> Wenn ja wie schreibe ich so ein Array über mehrere Zeilen, dass wird ja
> ziemlich lang?

Und was ist dein switch-case? Ist der vielleicht nicht lang?

> Und vor allem wie bringe ich dann die Pinne von PortD mit
> rein?

Du machst ein zweites Array.
Eines, in dem die Bits für PortB sind. Eines in dem die Bits für PortD 
sind. (Wenn du noch nie mit Arrays gearbeitet hast, dann sind 
wahrscheinlich Strukturen für dich auch ein böhmisches Dorf. Also jag 
ich dich da nicht auch noch rein).

Aber du sollst, nein du musst, schleunigst ein C-Buch lesen. Das hat 
doch keinen Sinn ein vernünftiges Porgramm zu schreiben, wenn du dein 
Werkzeug und seine Möglichkeiten gar nicht kennst.

von Peter D. (peda)


Lesenswert?

Das ist einfach nur grauenhaft, da sieht doch keiner mehr durch.

Du mußt doch nur die Bits umsortieren:
1
#include <io.h>
2
3
#define move_bit(src,srcn,dst,dstn) \
4
                if( src & 1<<srcn ) \
5
                  dst |= 1<<dstn;   \
6
                else                \
7
                  dst &= ~(1<<dstn);
8
9
10
void set_output(uint8_t celnumber)
11
{
12
  celnumber--;
13
  move_bit( celnumber, 0, PORTB, 5 );
14
  move_bit( celnumber, 1, PORTB, 3 );
15
  move_bit( celnumber, 2, PORTB, 2 );
16
  move_bit( celnumber, 3, PORTD, 7 );
17
  move_bit( celnumber, 4, PORTB, 0 );
18
  if( celnumber < 8 )
19
    PORTB |= 1<<4;
20
  else
21
    PORTB &= ~(1<<4);
22
}


Peter

von Karl H. (kbuchegg)


Lesenswert?

Kannst du mal ein paar Worte (Schaltbild) zu deinem Multiplexer 
verlieren? In deinem Programm wackelst du zwar mit einige Pins rum an 
denen der Multiplexer hängt, aber so richtig Sinn ergibt das nicht.

von Oliver (Gast)


Lesenswert?

>Mir ist
>aufgefallen, dass der PWM über Timer 1 Port B1 und B2 braucht.

Der Timer KANN PB0 und PB1 ansteuern, macht das ber nur, wenn du das 
auch entsprechend konfigurierst.

>Das ist
>natürlich doof wenn ich die Bits z.B. mit dem Muster 0b01000111
>beschreibe oder gar mit 0b00000000 lösche. Ich bringe den Controller ja
>intern irgendwie durcheinander.

Wenn die Pins über den Timer angesteuert werden, kannst du in das 
PORT-Register schreiben, was du willst, das stört nicht. Ausserdem 
kannst du gar nicht kontrollieren, ob der Compiler aus deinen #defines 
nun einzelne SBI-Befehle macht, oder ganze Bytes per OUT in das 
PORT-Register schreibt (letzteres macht der nämlich in deinem Fall).
1
#define aus PORTD&=~(1<<DDD7)|(1<<DDD6);
2
#define aus2 PORTB&=~(1<<DDB7)|(1<<DDB6)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2);

Da fehlen jeweils Klammern. Der Operator ~ wird sonst nur auf die erste 
Klammer angewendet.
1
#define aus PORTD&=~((1<<DDD7)|(1<<DDD6));
2
#define aus2 PORTB&=~((1<<DDB7)|(1<<DDB6)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2));

Und noch was:

Das ist der Code, den der Compiler für eine Zeile
1
ZelleXX; aus;aus2;
generiert (im Original sind da noch ein paar rjmps's dazwischen, aber am 
Problem ändert das nichts)
1
ldi  r24, 0x01  ; 1
2
out  0x18, r24  ; 24
3
ldi  r24, 0x40  ; 64
4
out  0x12, r24  ; 18  
5
6
in  r24, 0x12  ; 18
7
andi  r24, 0x3F  ; 63
8
out  0x12, r24  ; 18
9
in  r24, 0x18  ; 24
10
andi  r24, 0x03  ; 3
11
out  0x18, r24  ; 24

In dem Beispiel wird also erst Post B auf 0x01 gesetzt, damit fühlt sich 
Zelle 17 angesprochen. Zwei Takte später wird dann PORTD auf 0x40 
gesetzt, das spricht jetzt Zelle 13 an (wenn ich das richtig nachgesehen 
habe).

Zelle 13 bleibt jetzt weitere zwei Takt aktiv, dann wird PORTD schon 
wieder zurückgesetzt (ob da jetzt eine gültige Kombination für eine 
andere Zelle rauskommt, habe ich nicht geprüft), und weitere zwei Takt 
später wird dann auch PORTB zurückgesetzt.

Sinnvoll ist das irgendwie alles nicht.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Peter Dannegger schrieb:
> Das ist einfach nur grauenhaft, da sieht doch keiner mehr durch.
>
> Du mußt doch nur die Bits umsortieren:

Kann auch ein Problem bei ihm sein.
Aber schau dir mal seine Ur-Defines an.
Da ist keine Systematik erkennbar. Die Nummerierung der Zellen und die 
zugehörigen Bitmuster folgen keinem erkennbarem Schema (oder ich habs 
nur nicht gesehen)

Kann natürlich auch Layoutgründe haben, dass die Zellennummer und die 
Adressgenerierung keine logischen Zusammenhang haben.

von Peter D. (peda)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber schau dir mal seine Ur-Defines an.
> Da ist keine Systematik erkennbar.

Aus dem 2. Programm nicht, aber ganz oben hat er einige Kommentare:

Mark Pisani schrieb:
>   // Ports initialisieren
>   sbi(DDRB,0);   // (Enable Zelle 17-24)
>   sbi(DDRB,1);   // (Enable Zelle  9-16)
>   sbi(DDRB,2);   // Multiplexer A2
>   sbi(DDRB,3);   // Multiplexer A1
>   sbi(DDRB,4);   // (Enable Zelle  1-8)
>   sbi(DDRB,5);   // Multiplexer A0
>
> Es geht jetzt um folgendes, ich habe die Verbindung vom Multiplexer auf
> PD7 umgelötet.

Er meint damit, PB1 ist nun PD7.


Peter

von Mark P. (Gast)


Lesenswert?

Ich sag sofort was zu den Plexern,
es sieht so aus, ich sollte nur eine Regelung in C schreiben, klar hatte 
ich C in den Vorlesungen, aber nur eben die Grundgerüste und es ist doch 
anders an Controllern zu arbeiten, als in der Windows oder Linux 
Konsole.
Die Einzelspannungserfassung sollte funktionieren, alles was ich machen 
sollte war eine Regelung schreiben, die die Spannung kontrolliert. Die 
Regelung funktioniert auch.
Dummerweise muss ich bei einer Regelstrecke ja auch den Istwert 
verändern, dass geht eben nur über eine PWM. Daher waren dann die Pinne 
B0 und B1 belegt und dann ging das Dilemma los.
Ich bin hier in etwas reingeraten was nicht so einfach ist und ich muss 
in 2 Monaten mit allem fertig sein.
Welche C spezifischen Bücher gibt es denn speziell für Controller, hat 
einer Literaturtips?

Also ich habe 6 Multiplexer, die jeweils in 2er Gruppen verschaltet 
sind. Es wird von 2 Eingängen die Differenzspannung über Invertierer auf 
den Controller geleitet. Der der die Platine gelayoutet hat, der is 
heute nicht da, habe dem aber schon gesagt das ich den Plan gerne hätte.
Brauch ich ja auch so oder so.

Ich habe mal in meinem Pearl Harbour Programm einfach die "aus" 
Funktionen gelöscht, jetzt lese ich nur noch in 4 Zellen eine andere 
Spannung. Wenn ich das wenigstens so zum laufen bekommen würde, dann 
hätt ich diesen zeitlichen Druck weg und ich könnte mich um Schönheit 
kümmern.

Danke nochmal für alles.

von Karl H. (kbuchegg)


Lesenswert?

Peter Dannegger schrieb:
> Karl heinz Buchegger schrieb:
>> Aber schau dir mal seine Ur-Defines an.
>> Da ist keine Systematik erkennbar.
>
> Aus dem 2. Programm nicht, aber ganz oben hat er einige Kommentare:

Hab ich gesehen. Auch im Programm gibt es am Anfang einen Kommentar der 
die Pinbelegung zeigt.
Aber das passt alles nicht zu den #defines. Die sind ein heilloses 
Durcheinander.

Ich denke, es wird Zeit ein Schaltbild zu sehen.
Hast du rausgefunden, wie dieser Multiplexer angesteuert wird? Wo wie 
das jetzt im Programm ist: Ich kann mir nicht vorstellen, dass das so 
stimmt. Aus dem Bauch heraus ist das doch meist ein 2-stufiger Prozess: 
Adresse anlegen - Enablen. Nur kann ich das so im Pgm nirgends auch nur 
ansatzweise erkennen.

von Karl H. (kbuchegg)


Lesenswert?

Mark P. schrieb:

> Welche C spezifischen Bücher gibt es denn speziell für Controller, hat
> einer Literaturtips?

Wenn du mit Arrays Schwierigkeiten hast, dann ist das nichts µC 
spezifisches. Das sind C-Grundlagen und überall gleich.

µC spezifisch ist nur, welche Ports es gibt, welche Sonderfunktionen 
dein µC zur Verfügung stellt und welche Bits man wo setzen muss, damit 
eine Sonderfunktion ausgelöst wird.

Alles andere kann man sehr gut mit Standard-C erschlagen.

> Also ich habe 6 Multiplexer, die jeweils in 2er Gruppen verschaltet
> sind. Es wird von 2 Eingängen die Differenzspannung über Invertierer auf
> den Controller geleitet. Der der die Platine gelayoutet hat, der is
> heute nicht da, habe dem aber schon gesagt das ich den Plan gerne hätte.
> Brauch ich ja auch so oder so.

Den brauchst du auf jeden Fall!
Was sind das für Multiplexer? (IC-Bezeichnung)
Wenigstens so ungefähr wirst du ja wohl wissen, wie der am µC 
angeschlossen ist. Interessant sind die Ax und die Enable-Leitungen. 
Sind nur 6 Leitungen, die kann man auch mit einem Ohmmeter durchmessen.

> Ich habe mal in meinem Pearl Harbour Programm einfach die "aus"
> Funktionen gelöscht, jetzt lese ich nur noch in 4 Zellen eine andere
> Spannung. Wenn ich das wenigstens so zum laufen bekommen würde, dann
> hätt ich diesen zeitlichen Druck weg und ich könnte mich um Schönheit
> kümmern.

Du musst deine Ansteuerung ziemlich sicher aufdröseln.

Zuerst legst du die Adressbits an, welcher MUX-Eingang durchgeschaltet 
werden soll.
Und erst dann toggelst du mit den Enable Bits. So quasi: Baustein - 
jetzt gilts! Das was jetzt an den Adressbits anliegt, ist der Eingang 
den ich haben will.

Die Details hängen vom Baustein ab. Aber irgendwie so wirds gehen.

von Peter D. (peda)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber das passt alles nicht zu den #defines. Die sind ein heilloses
> Durcheinander.

Aber er sagt ja auch, daß diese nicht funktionieren.
Warum sollten sie dann stimmen?

So schreibt man einfach keinen Code (wenn man will, daß er 
funktioniert).
Auch nicht als Anfänger.


Peter

von Mark P. (Gast)


Lesenswert?

Also, der Layouter ist beim Arzt bekomme später das Layout.
DG408 ist der Plexer.

Ich beuge mich erstmal der Kritik und werde jetzt solange ich das Layout 
nicht habe versuchen die ganze Sache eleganter zu schreiben.

Poste später das Layout sofern es mir möglich ist hier

von Karl H. (kbuchegg)


Lesenswert?

OK. Eines noch vorweg:
Welche Pinbelegung gilt jetzt wirklich?
Welcher Pin an PORTB/PORTD macht was?

von Karl H. (kbuchegg)


Lesenswert?

Mark P. schrieb:

> Ich beuge mich erstmal der Kritik und werde jetzt solange ich das Layout
> nicht habe versuchen die ganze Sache eleganter zu schreiben.

Wenn du schon dabei bist:

Gemeinhin wird bei 0 zu zählen angefangen.
Dein erster ADC Kanal ist daher Kanal 0 und nicht 1

von Karl H. (kbuchegg)


Lesenswert?

Wenn ich mal das Makro von PeDa benutze, dann sollte das im wesentlichen 
so aussehen
1
#define ADDR_0_PORT   PORTB
2
#define ADDR_0_PIN    PB5
3
4
#define ADDR_1_PORT   PORTB
5
#define ADDR_1_PIN    PB3
6
7
#define ADDR_2_PORT   PORTD
8
#define ADDR_2_PIN    PD6
9
10
#define ENABLE_0_PORT PORTB
11
#define ENABLE_0_PIN  PB4
12
13
#define ENABLE_1_PORT PORTD
14
#define ENABLE_1_PIN  PD7
15
16
#define ENABLE_2_PORT PORTB
17
#define ENABLE_2_PIN  PB0
18
19
#define move_bit(src,srcn,dst,dstn) \
20
                 if( src & (1<<srcn) ) \
21
                  dst |= 1<<dstn;   \
22
                else                \
23
                  dst &= ~(1<<dstn)
24
25
void setAddress( uint8_t addr )
26
{
27
  move_bit( addr, 0, ADDR_0_PORT, ADDR_0_PIN );
28
  move_bit( addr, 1, ADDR_1_PORT, ADDR_1_PIN );
29
  move_bit( addr, 2, ADDR_2_PORT, ADDR_2_PIN );
30
}
31
32
int main()
33
{
34
  ....
35
36
  count = 0;
37
38
  while( 1 )
39
  {
40
     ....
41
42
     //
43
     // Fuer die Multiplexer die Adresse setzen
44
     setAddress( count );
45
46
     // und den richtigen Multiplexer zum Durchschalten bewegen
47
     // der Multiplexer reagiert, sobald sein Enable Pin auf 1 gesetzt wird
48
     // je nach Kanal daher einfach den richtigen Enable Pin auswählen
49
     if( count < 8 )
50
       ENABLE_0_PORT |= ( 1 << ENABLE_0_PIN );
51
52
     else if( count < 16 )
53
       ENABLE_1_PORT |= ( 1 << ENABLE_1_PIN );
54
55
     else
56
       ENABLE_2_PORT |= ( 1 << ENABLE_2_PIN );
57
58
     // Multiplexer hat jetzt den Eingang durchgeschaltet ->
59
     // Spannung messen
60
     result = spannung();
61
62
     // und den Multiplexer wieder wegschalten
63
     // der Einfachheit halber werden alle 3 abgeschaltet. Geht genauso
64
     // schnell, als wie wenn man mittels if den richtigen raussucht.
65
     ENABLE_0_PORT &= ~( 1 << ENABLE_0_PIN );
66
     ENABLE_1_PORT &= ~( 1 << ENABLE_1_PIN );
67
     ENABLE_2_PORT &= ~( 1 << ENABLE_2_PIN );
68
69
     // mach was mit der gemessenen Spannung
70
     sprintf( c_buffer, "Kanal %d: %d\r\n", count + 1, result );
71
     printf( c_buffer );
72
73
     // und weiter gehts zum nächsten Kanal
74
     count++;
75
     if( count == 24 )
76
       count = 0;
77
   }
78
}

von Mark P. (Gast)


Lesenswert?

Ich habe ein wenig experimentiert, vielleicht ist es dann einfacher 
nachzuvollziehen. Das ist hier der Ursprung:
1
#define aus    PORTB=0b00000000;
2
3
#define Zelle1    PORTB=0b00010000;
4
#define Zelle2    PORTB=0b00110000;
5
#define Zelle3    PORTB=0b00011000;
6
#define Zelle4    PORTB=0b00111000;
7
#define Zelle5    PORTB=0b00010100;
8
#define Zelle6    PORTB=0b00110100;
9
#define Zelle7    PORTB=0b00011100;
10
#define Zelle8    PORTB=0b00111100;
11
12
#define Zelle9    PORTB=0b00000010;
13
#define Zelle10    PORTB=0b00100010;
14
#define Zelle11    PORTB=0b00001010;
15
#define Zelle12    PORTB=0b00101010;
16
#define Zelle13    PORTB=0b00000110;
17
#define Zelle14    PORTB=0b00100110;
18
#define Zelle15    PORTB=0b00001110;
19
#define Zelle16    PORTB=0b00101110;
20
21
#define Zelle17   PORTB=0b00000001;
22
#define Zelle18   PORTB=0b00100001;
23
#define Zelle19   PORTB=0b00001001;
24
#define Zelle20    PORTB=0b00101001;
25
#define Zelle21   PORTB=0b00000101;
26
#define Zelle22   PORTB=0b00100101;
27
#define Zelle23   PORTB=0b00001101;
28
#define Zelle24   PORTB=0b00101101;
29
30
#include <avr\io.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
35
volatile uint32_t mittelwert; //merker der letzten Zellspannung
36
volatile int fallunterscheidung;
37
//------------------------------------------------------------------------
38
// Initialisierungen
39
//------------------------------------------------------------------------
40
void init()
41
{
42
  // Ports initialisieren
43
  sbi(DDRB,0);   // (Enable Zelle 17-24)
44
  sbi(DDRB,1);   // (Enable Zelle  9-16)
45
  sbi(DDRB,2);   // Multiplexer A2 
46
  sbi(DDRB,3);   // Multiplexer A1 
47
  sbi(DDRB,4);   // (Enable Zelle  1-8)
48
  sbi(DDRB,5);   // Multiplexer A0
49
  //----------------------------------------------------------
50
51
  // UART initialisieren
52
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
53
  UCSRB = 0x08;           //Sender enable UCSRB / UCR bei z.B.: 2313
54
}
55
//----------------------------------------------------------------------
56
void putChar(unsigned char data)
57
{
58
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
59
  while (!(UCSRA&32));
60
  //sende
61
  UDR=data;
62
}
63
//----------------------------------------------------------------------
64
65
void initADC()
66
{
67
  ADCSRA=0b11000111;      //0b11000011, ADC-Clock, ADC ON
68
}
69
70
unsigned char spannung(void)    //Auswertung ADC...
71
{
72
  sbi  (ADCSRA,6);    // restart ADC
73
  while (ADCSRA & 0x40)
74
  {
75
  }      //ende warteschleife für AD-Wandlung
76
77
  return (unsigned char) ((ADC/4) && 255);
78
}
79
80
int set_output(int celnumber)
81
{
82
  switch (celnumber)
83
  {
84
85
    case 1: Zelle1;
86
    break;
87
88
    case 2: Zelle2;
89
    break;
90
91
    case 3: Zelle3;
92
    break;
93
94
    case 4: Zelle4;
95
    break;
96
97
    case 5: Zelle5;
98
    break;
99
100
    case 6: Zelle6;
101
    break;
102
103
    case 7: Zelle7;
104
    break;
105
106
    case 8: Zelle8;
107
    break;
108
109
    case 9: Zelle9;
110
    break;
111
112
    case 10: Zelle10;
113
    break;
114
115
    case 11: Zelle11;
116
    break;
117
118
    case 12: Zelle12;
119
    break;
120
121
    case 13: Zelle13;
122
    break;
123
124
    case 14: Zelle14;
125
    break;
126
127
    case 15: Zelle15;
128
    break;
129
130
    case 16: Zelle16;
131
    break;
132
133
    case 17: Zelle17;
134
    break;
135
136
    case 18: Zelle18;
137
    break;
138
139
    case 19: Zelle19;
140
    break;
141
142
    case 20: Zelle20;
143
    break;
144
145
    case 21: Zelle21;
146
    break;
147
148
    case 22: Zelle22;
149
    break;
150
151
    case 23: Zelle23;
152
    break;
153
154
    case 24: Zelle24;
155
    break;
156
157
    default: aus;
158
    break;
159
160
  }
161
  //end switch
162
163
}

Das funktioniert auch so einwandfrei.
Zu den Ports und den Bitbelegungen, Zelle 1-8 hat immer Bit 5 gesetzt, 
dass ist das Enable für den Multiplexer die anderen 3 sich 
verschiebenden Bits sind die Logikpinne des Plexers. Bei Zelle 9-16 ist 
Bit 1 ist das Enable Bit und bei den letzten 0.
Jetzt habe ich ja bereits gesagt, dass ich das PWM-Signaldauerhaft 
brauche um eine Lastsenke, die die Spannungen regeln soll anzusteuern. 
Das wiederum heisst Pin B1 und B2 sind dauerhaft am arbeiten. 
Dummerweise brauche ich diese aber für das Enable Bit vom Plexer Zelle 
9-16 aus diesem Grund habe ich zum Enablen PD7 benutzt, habe es auch 
hardwaretechnisch geändert und umgelötet. Gleiches gilt für die Logiken 
die auf PB2 liegen, diese habe ich jetzt auf PD6 gelegt.
Also alles was ich ändern musste war das Enables und die Logik. Deswegen 
habe ich die PORTD Bits eingefügt.

Wie ihr mitbekommen habt bin ich noch ein Anfänger. Deswegen würde ich 
es gerne weiterhin mit meinem Programm versuchen. Ich habe es jetzt so 
umgeschrieben, ich hoffe ich habe die Regeln eingehalten, die Zelle 
fange ich trotzdem bei 1 an zu Zählen, weil die Beschriftung auf der 
Zelle auch 1 ist und nicht 0.
1
#define MPLEX_B_OFF()  PORTB=0b00000000;
2
#define MPLEX_D_OFF() PORTD=0b00000000;
3
4
#define ZELLE1()   PORTB=0b00010000;
5
#define ZELLE2()   PORTB=0b00110000;
6
#define ZELLE3()   PORTB=0b00011000;
7
#define ZELLE4()   PORTB=0b00111000;
8
#define ZELLE5()   PORTB=0b00010100;
9
#define ZELLE6()   PORTB=0b00110100;
10
#define ZELLE7()   PORTB=0b00011100;
11
#define ZELLE8()   PORTB=0b00111100;
12
13
#define ZELLE9()  do { PORTB = 0b00000000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00000010;//
14
#define ZELLE10()   do { PORTB = 0b00100000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00100010;//
15
#define ZELLE11()   do { PORTB = 0b00001000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00001010;// 
16
#define ZELLE12()   do { PORTB = 0b00101000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00101010;//
17
#define ZELLE13()   do { PORTB = 0b00000100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00000110;//
18
#define ZELLE14()   do { PORTB = 0b00100100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00100110;//
19
#define ZELLE15()   do { PORTB = 0b00001100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00001110;//
20
#define ZELLE16()   do { PORTB = 0b00101100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00101110;//
21
22
#define ZELLE17()  PORTB=0b00000001;            
23
#define ZELLE18()  PORTB=0b00100001;            
24
#define ZELLE19()  PORTB=0b00001001;            
25
#define ZELLE20()  PORTB=0b00101001;            
26
#define ZELLE21()  do { PORTB=0b00000001; PORTD = 0b01000000;  } while( 0 )  
27
#define ZELLE22()  do { PORTB=0b00100001; PORTD = 0b01000000;  } while( 0 )
28
#define ZELLE23()  do { PORTB=0b00001001; PORTD = 0b01000000;  } while( 0 )
29
#define ZELLE24()  do { PORTB=0b00101001; PORTD = 0b01000000;  } while( 0 )
30
31
// Globale Variablen
32
33
volatile uint32_t mittelwert; //merker der letzten Zellspannung
34
volatile int fallunterscheidung;
35
volatile int16_t i_pidsetpoint=0;  //Sollwert
36
volatile int i_abbruch;        //Abbruchkriterium für Timer
37
volatile int16_t i_pidsense=0;          //gucken ob global nötig ist
38
volatile int16_t i_hold_value;    //Backupvariable für Setpoint, kann ggf gelöscht werden
39
40
//------------------------------------------------------------------------
41
// Initialisierungen
42
//------------------------------------------------------------------------
43
void init()
44
{
45
  // Ports initialisieren
46
  sbi(DDRB,0);   // (Enable Zelle 17-24)
47
  //sbi(DDRB,1);   // (Enable Zelle  9-16)
48
  //sbi(DDRB,2);   // Multiplexer A2 
49
  sbi(DDRB,3);   // Multiplexer A1 
50
  sbi(DDRB,4);   // (Enable Zelle  1-8)
51
  sbi(DDRB,5);   // Multiplexer A0#
52
  sbi(DDRD,6);  // Multiplexer A2
53
  sbi(DDRD,7);// (Enable Zelle 9-16)
54
55
  // Port Belegung Regelung
56
  //DDRB|=(1<<DDB1);  // PWM
57
  DDRC&=~(1<<DDC2);  // Lem Strom Pidsense
58
  DDRC&=~(1<<DDC0);  // Lem Strom Pidsense
59
  //----------------------------------------------------------
60
61
  // UART initialisieren
62
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
63
  UCSRB = 8 + 16;           //Sender enable UCSRB / UCR bei z.B.: 2313
64
}
65
66
void initADC()
67
{
68
  ADCSRA=0b11000111;      //0b11000011, ADC-Clock, ADC ON
69
}
70
71
unsigned char spannung(void)    //Auswertung ADC...
72
{
73
  sbi  (ADCSRA,6);    // restart ADC
74
  while (ADCSRA & 0x40)
75
  {
76
  }      //ende warteschleife für AD-Wandlung
77
78
  return (unsigned char) (ADC/4);
79
}
80
81
int set_output(int celnumber)
82
{
83
  switch (celnumber)
84
  {
85
86
    case 1: ZELLE1();
87
    break;
88
89
    case 2: ZELLE2();
90
    break;
91
92
    case 3: ZELLE3();
93
    break;
94
95
    case 4: ZELLE4();
96
    break;
97
98
    case 5: ZELLE5();
99
    break;
100
101
    case 6: ZELLE6();
102
    break;
103
104
    case 7: ZELLE7();
105
    break;
106
107
    case 8: ZELLE8();
108
    break;
109
110
    case 9: ZELLE9();
111
    break;
112
113
    case 10: ZELLE10();
114
    break;
115
116
    case 11: ZELLE11();
117
    break;
118
119
    case 12: ZELLE12();
120
    break;
121
122
    case 13: ZELLE13();
123
    break;
124
125
    case 14: ZELLE14();
126
    break;
127
128
    case 15: ZELLE15();
129
    break;
130
131
    case 16: ZELLE16();
132
    break;
133
134
    case 17: ZELLE17();
135
    break;
136
137
    case 18: ZELLE18();
138
    break;
139
140
    case 19: ZELLE19();
141
    break;
142
143
    case 20: ZELLE20();
144
    break;
145
146
    case 21: ZELLE21();
147
    break;
148
149
    case 22: ZELLE22();
150
    break;
151
152
    case 23: ZELLE23();
153
    break;
154
155
    case 24: ZELLE24();
156
    break;
157
158
    default: 
159
    MPLEX_B_OFF();
160
    MPLEX_D_OFF();
161
    break;
162
}
163
}


Lese ich die Spannungen im ersten Programm aus erhalte ich einen Wert 
zwischen 28-30 auf allen Zellen. Ändere ich die Adressen der beiden Bits 
lese ich auf Zelle 1 und 17-20 werde von 42-42 die anderen bleiben bei 
Werten zwischen 28-30.
Das ist das einzige Problem, davon ab das es aussieht wie Kraut und 
Rüben.
Tut mir leid für die Länge des Beitrags, ich hab gelesen das man es 
besser in Txt usw packen soll.

von Oliver (Gast)


Lesenswert?

>Lese ich die Spannungen im ersten Programm aus erhalte ich einen Wert
>zwischen 28-30 auf allen Zellen.

Wenn du auf allen Kanälen das gleiche misst, woher weisst du dann, ob 
tatsächlich der gewünschte Multiplexer-Kanal aktiv ist?

Oliver

von Mark P. (Gast)


Lesenswert?

Weil ich Kurzschlussbrücken zwischen den einzelnen Eingängen mache.
Dann kommt ja zwangläufig eine 0 raus.

von Peter D. (peda)


Lesenswert?

Mark P. schrieb:
> Ich habe ein wenig experimentiert, vielleicht ist es dann einfacher
> nachzuvollziehen.

Nein, es ist immer noch viel zu viel unnützer Schreibaufwand und damit 
viel Code und viel Fehlerquellen.

> fange ich trotzdem bei 1 an zu Zählen, weil die Beschriftung auf der
> Zelle auch 1 ist und nicht 0.

Die Beschriftung ist wurscht, davon weiß Dein Programm nichts.
Aber wenn Du intern von 0 zählst, wird die Dekodierung extrem einfacher 
(siehe mein Code). Deshalb habe ich erstmal eins abgezogen.


> Tut mir leid für die Länge des Beitrags, ich hab gelesen das man es
> besser in Txt usw packen soll.

*.TXT ist Humbug.
Dein Programm heißt *.C, also postet man auch das *.C.
Und wenns mehrere Quellen sind, packt man die in ein *.ZIP.


Peter

von Mark P. (Gast)


Lesenswert?

Ich kann dein Programm aber nicht nachvollziehen, weil es wohl zu hoch 
für meine primitiven Kenntnise ist, was keinen Falls ironisch gemeint 
ist. Ich sehe auch jetzt erst, dass Karl das Programm ausgeweitet hat.
Ich setze mich jetzt damit mal auseinander.
ABer was bedeutet das

#define move_bit(src,srcn,dst,dstn) \
                 if( src & (1<<srcn) ) \
                  dst |= 1<<dstn;   \
                else                \
                  dst &= ~(1<<dstn)

von Mark P. (Gast)


Lesenswert?

[c]
#define ADDR_0_PORT   PORTB
#define ADDR_0_PIN    PB5 //A0

#define ADDR_1_PORT   PORTB
#define ADDR_1_PIN    PB3 //A1

#define ADDR_2_PORT   PORTD
#define ADDR_2_PIN    PD6 //A2

#define ENABLE_0_PORT PORTB
#define ENABLE_0_PIN  PB4 //Zelle 1-8

#define ENABLE_1_PORT PORTD
#define ENABLE_1_PIN  PD7 //Zelle 9-16

#define ENABLE_2_PORT PORTB
#define ENABLE_2_PIN  PB0 //Zelle 17-24

#define move_bit(src,srcn,dst,dstn) \
                 if( src & (1<<srcn) ) \
                  dst |= 1<<dstn;   \
                else                \
                  dst &= ~(1<<dstn)

void setAddress( uint8_t addr )
{
  move_bit( addr, 0, ADDR_0_PORT, ADDR_0_PIN );
  move_bit( addr, 1, ADDR_1_PORT, ADDR_1_PIN );
  move_bit( addr, 2, ADDR_2_PORT, ADDR_2_PIN );
}

int main()
{
  ....

  count = 0;

  while( 1 )
  {
     ....

     //
     // Fuer die Multiplexer die Adresse setzen
     setAddress( count );

//??Wenn der Counter bis 24 zählt, woher weiss er dann welches move_bit 
er benutzen soll? oder bewegt der alle Bits und ich raff es nur nicht 
weil ich die Funktion darüber wohl nicht verstanden habe?


     // und den richtigen Multiplexer zum Durchschalten bewegen
     // der Multiplexer reagiert, sobald sein Enable Pin auf 1 gesetzt 
wird
     // je nach Kanal daher einfach den richtigen Enable Pin auswählen
     if( count < 8 )
       ENABLE_0_PORT |= ( 1 << ENABLE_0_PIN );

     else if( count < 16 )
       ENABLE_1_PORT |= ( 1 << ENABLE_1_PIN );

     else
       ENABLE_2_PORT |= ( 1 << ENABLE_2_PIN );

     // Multiplexer hat jetzt den Eingang durchgeschaltet ->
     // Spannung messen
     result = spannung();

     // und den Multiplexer wieder wegschalten
     // der Einfachheit halber werden alle 3 abgeschaltet. Geht genauso
     // schnell, als wie wenn man mittels if den richtigen raussucht.
     ENABLE_0_PORT &= ~( 1 << ENABLE_0_PIN );
     ENABLE_1_PORT &= ~( 1 << ENABLE_1_PIN );
     ENABLE_2_PORT &= ~( 1 << ENABLE_2_PIN );

     // mach was mit der gemessenen Spannung
     sprintf( c_buffer, "Kanal %d: %d\r\n", count + 1, result );
     printf( c_buffer );

     // und weiter gehts zum nächsten Kanal
     count++;
     if( count == 24 )
       count = 0;
   }
}
[c/]


Bis auf den einen Teil kann ich dem folgen

von Karl H. (kbuchegg)


Lesenswert?

Mark P. schrieb:
> Ich kann dein Programm aber nicht nachvollziehen, weil es wohl zu hoch
> für meine primitiven Kenntnise ist, was keinen Falls ironisch gemeint
> ist. Ich sehe auch jetzt erst, dass Karl das Programm ausgeweitet hat.
> Ich setze mich jetzt damit mal auseinander.
> ABer was bedeutet das
>
> #define move_bit(src,srcn,dst,dstn) \
>                  if( src & (1<<srcn) ) \
>                   dst |= 1<<dstn;   \
>                 else                \
>                   dst &= ~(1<<dstn)

Das ist ein Makro.
Das Makro überträgt die aktuelle Bitstellung (also 0 oder 1) von src 
(und dort ist es das Bit mit der Nummer srcn) nach dst (und dort in die 
Bitposition dstn)

src    Abkürzung für 'source', also Quelle
dst    Abkürzung für 'destination', also Ziel

Nimm eine der Makroverwendungen aus meinem Programm her

  ...
  move_bit( addr, 0, ADDR_0_PORT, ADDR_0_PIN );
  ...

Jetzt spielen wir Präprozessor und führen die Textersetzung durch den 
#define durch

src wird zu addr
srcn wird zu 0
dst wird zu ADDR_0_PORT
dstn wird zu ADDR_0_PIN

dann steht da

     ...
     if( addr & (1<<0) )
       ADDR_0_PORT |= 1<<ADDR_0_PIN;
     else
       ADDR_0_PORT &= ~(1<<ADDR_0_PIN);
     ...

jetzt kommen noch die #define für ADDR_0_PORT bzw. ADDR_0_PIN dazu. Auch 
hier wieder die textuelle Einsetzung:

     ...
     if( addr & (1<<0) )
       PORTB |= 1<<PB5;
     else
       PORTB &= ~(1<<PB5);
     ...

Wenn also in addr das Bit 0 gesetzt ist, wird am PORTB das Bit PB5 
ebenfalls gesetzt. Ist in addr das Bit 0 nicht gesetzt, wird PORTB/PB5 
ebenfalls auf 0 gesetzt.

Im Endeffekt sorgt der Code also dafür, dass PORTB/PB5 denselben Zustand 
hat wie das 0-te Bit in addr. Und darum hat PeDa das Makro auch move_bit 
genannt, weil es so aussieht als ob das Bit addr/0 nach PORTB/PB5 
'verschoben' wird. Alles andere drumherum ist nur ein bischen 
Präprozessor Makulatur, damit man von der Zählvariable leicht steuern 
kann an welchen PORT / Pin das 0-te Bit der Zählvariable ausgegeben 
werden soll.


Und nein: Mit 1 zu zählen anzufangen ist keine gute Idee! Gewöhn dich 
daran, dass bei 0 angefangen wird! Das vereinfacht eine Menge Dinge. Bei 
der Ausgabe für den Benutzer kann man immer noch 1 dazuzählen bzw. bei 
Eingaben 1 abziehen. Aber programmintern ist Zählbeginn immer 0!

von Karl H. (kbuchegg)


Lesenswert?

Mark P. schrieb:
>      //
>      // Fuer die Multiplexer die Adresse setzen
>      setAddress( count );
>
> //??Wenn der Counter bis 24 zählt, woher weiss er dann welches move_bit
> er benutzen soll? oder bewegt der alle Bits und ich raff es nur nicht
> weil ich die Funktion darüber wohl nicht verstanden habe?

Die Funktion setAddress nimmt einfach die untersten 3 Bits aus count und 
gibt sie gemäss den PORT/PIN #defines an den richtigen Prozessorpins 
aus.

Deine Hardware ist (hoffentlich) so gebaut, dass die ersten 8 Kanäle auf 
Multiplexer 0 liegen, die nächsten auf Multiplexer 1, und die letzten 8 
Kanäle liegen auf Multiplexer 2

Mit 3 Bits hat man genau 8 unterscheidbare Zustände

0, 1, 2, 3, 4, 5, 6, 7

Zähl nach, sind genau 8 Stück

   dezimal     A2  A1  A0
    0           0   0   0
    1           0   0   1
    2           0   1   0
    3           0   1   1
    4           1   0   0
    5           1   0   1
    6           1   1   0
    7           1   1   1

und da sich setAdress nur um die untersten 3 Bits kümmert, geht die 
Tabelle dann so weiter

    8           0   0   0
    9           0   0   1
   10           0   1   0
   11           0   1   1
   12           1   0   0
   13           1   0   1
   14           1   1   0
   15           1   1   1

   16           0   0   0
   17           0   0   1
   ...

Die Zählerstellungen für 0, 8, 16  erzeugen in den Adressbits identische 
Zustände. Das ist auch so gewollt, denn Kanal 0 ist Channel 0 am 
Multiplexer 0, Kanal 8 ist Channel 0 am Multiplexer 1 und Kanal 16 ist 
Channel 0 am Multiplexer 2

Die einzelnen Multiplexer sehen also bei deinen Kanalnummern 0, 8 und 16 
jeweils eine identische 3-Bit Adresse. Der nachfolgende Code in der 
Hauptscheilfe sorgt dann über die ENABLE Bits dafür, dass sich jeweils 
der richtige Multiplexer um die Auswertung der Adresse annimmt: Einer 
der 3 Multiplexer schaltet seinen angeforderten Eingang auf den ADC, 
alle anderern halten sich raus.

von Mark P. (Gast)


Lesenswert?

Wow, danke. Das war echt so erklärt, dass ich es verstanden habe;)
Ja dann mal ran an die Buletten, werde versuchen es umzusetzten.

von Mark P. (Gast)


Lesenswert?

Hallo, ich habe es hinbekommen:)
Danke nochmal für die ganze Hilfe.

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.