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ß
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:
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
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.
> 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
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?
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.
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.
>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).
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
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.
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
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.
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.
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.
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
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
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
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.
UCSRB=8+16;//Sender enable UCSRB / UCR bei z.B.: 2313
64
}
65
66
voidinitADC()
67
{
68
ADCSRA=0b11000111;//0b11000011, ADC-Clock, ADC ON
69
}
70
71
unsignedcharspannung(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(unsignedchar)(ADC/4);
79
}
80
81
intset_output(intcelnumber)
82
{
83
switch(celnumber)
84
{
85
86
case1:ZELLE1();
87
break;
88
89
case2:ZELLE2();
90
break;
91
92
case3:ZELLE3();
93
break;
94
95
case4:ZELLE4();
96
break;
97
98
case5:ZELLE5();
99
break;
100
101
case6:ZELLE6();
102
break;
103
104
case7:ZELLE7();
105
break;
106
107
case8:ZELLE8();
108
break;
109
110
case9:ZELLE9();
111
break;
112
113
case10:ZELLE10();
114
break;
115
116
case11:ZELLE11();
117
break;
118
119
case12:ZELLE12();
120
break;
121
122
case13:ZELLE13();
123
break;
124
125
case14:ZELLE14();
126
break;
127
128
case15:ZELLE15();
129
break;
130
131
case16:ZELLE16();
132
break;
133
134
case17:ZELLE17();
135
break;
136
137
case18:ZELLE18();
138
break;
139
140
case19:ZELLE19();
141
break;
142
143
case20:ZELLE20();
144
break;
145
146
case21:ZELLE21();
147
break;
148
149
case22:ZELLE22();
150
break;
151
152
case23:ZELLE23();
153
break;
154
155
case24: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.
>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
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
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)
[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
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!
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.