mikrocontroller.net

Forum: Compiler & IDEs #define Ports


Autor: Mark Pisani (pisy)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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ß

Autor: Mark P. (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark Pisani schrieb:

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

Ich denke aber die bessere Lösung wäre den MPlexer direkter 
anzusprechen.
#define MPLEX_PORT  PORTD
#define MPLEX_BIT   PD1

#define MPLEX_ON  do { MPLEX_PORT |= ( 1 << MPLEX_BIT ); } while( 0 )
#define MPLEX_OFF do { MPLEX_PORT &= ~( 1 << MPLEX_BIT ); } while( 0 )

...

#defien Zelle9   do { PORTB = 0b00000000; MPLEX_ON; } while( 0 )

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

Autor: Mark Pisani (pisy)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
#define aus PORTD&=~(1<<DDD7)|(1<<DDD6);
#define aus2 PORTB&=~(1<<DDB7)|(1<<DDB6)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2);

#define Zelle1    do {PORTB=(1<<DDB4);} while (0)//PORTB=0b00010000;
#define Zelle2    do {PORTB=(1<<DDB5)|(1<<DDB4);} while (0)//PORTB=0b00110000;
#define Zelle3    do {PORTB=(1<<DDB3)|(1<<DDB4);} while (0)//PORTB=0b00011000;
#define Zelle4    do {PORTB=(1<<DDB3)|(1<<DDB3)|(1<<DDB4);} while (0)//PORTB=0b00111000;
#define Zelle5    do { PORTB=(1<<DDB4); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00010100
#define Zelle6    do { PORTB=(1<<DDB5)|(1<<DDB4); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00110100
#define Zelle7    do { PORTB=(1<<DDB4)|(1<<DDB3); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00011100
#define Zelle8    do { PORTB=(1<<DDB5)|(1<<DDB4)|(1<<DDB3); PORTD = (1<<DDD6); } while (0)  //PORTB=0b00111100

#define Zelle9    do { PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00000010;//
#define Zelle10    do { PORTB = (1<<DDB5); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00100010;//
#define Zelle11    do { PORTB = (1<<DDB3); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00001010;// 
#define Zelle12    do { PORTB = (1<<DDB5)|(1<<DDB3); PORTD = (1<<DDD7); } while( 0 ) //PORTB=0b00101010;//
#define Zelle13    do { PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00000110;//
#define Zelle14    do { PORTB = (1<<DDB5); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00100110;//
#define Zelle15    do { PORTB = (1<<DDB3); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00001110;//
#define Zelle16    do { PORTB = (1<<DDB3)|(1<<DDB5); PORTD = (1<<DDD7)|(1<<DDD6); } while( 0 ) //PORTB=0b00101110;//

#define Zelle17   do {PORTB=(1<<DDB0); } while( 0 )//0b00000001;
#define Zelle18   do {PORTB=(1<<DDB5)|(1<<DDB0); } while( 0 )//0b00100001;
#define Zelle19   do {PORTB=(1<<DDB3)|(1<<DDB0); } while( 0 )//0b00001001;
#define Zelle20    do {PORTB=(1<<DDB5)|(1<<DDB3)|(1<<DDB0); } while( 0 )//0b00101001;
#define Zelle21   do {PORTB=(1<<DDB0); PORTD = (1<<DDD6); } while( 0 )//0b00000101;
#define Zelle22   do {PORTB=(1<<DDB5)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00100101;
#define Zelle23   do {PORTB=(1<<DDB3)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00001101;
#define Zelle24   do {PORTB=(1<<DDB5)|(1<<DDB3)|(1<<DDB0); PORTD = (1<<DDD6);} while( 0 )//0b00101101;

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#
  sbi(DDRD,6);  // Multiplexer A2
  sbi(DDRD,7);  // (Enable Zelle 9-16)

  // Port Belegung Regelung
  //DDRB|=(1<<DDB1);  // PWM
  DDRC&=~(1<<DDC2);  // Lem Strom Pidsense
  DDRC&=~(1<<DDC0);  // Lem Strom Pidsense
  //----------------------------------------------------------

  // UART initialisieren
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
  UCSRB = 8 + 16;           //Sender enable UCSRB / UCR bei z.B.: 2313
}

int set_output(int celnumber)
{
  switch (celnumber)
  {

    case 1: do 
    {
    Zelle1; aus;aus2;
    }
    while(0);// Zelle1;
    break;

    case 2: do 
    {
    Zelle2; aus;aus2;
    }
    while(0);//Zelle2;
    break;

    case 3: do 
    {
    Zelle3; aus;aus2;
    }
    while(0);//Zelle3;
    break;

    case 4: do 
    {
    Zelle4; aus;aus2;
    }
    while(0);//Zelle4;
    break;

    case 5: do 
    {
    Zelle5; aus;aus2;
    }
    while(0);//Zelle5;
    break;

    case 6: do 
    {
    Zelle6; aus;aus2;
    }
    while(0);//Zelle6;
    break;

    case 7: do 
    {
    Zelle7; aus;aus2;
    }
    while(0);//Zelle7;
    break;

    case 8: do 
    {
    Zelle8; aus;aus2;
    }
    while(0);//Zelle8;
    break;

    case 9: do 
    {
    Zelle9; aus;aus2;
    }
    while(0);//Zelle9;
    break;

    case 10: do 
    {
    Zelle10; aus;aus2;
    }
    while(0);//Zelle10;
    break;

    case 11: do 
    {
    Zelle11; aus;aus2;
    }
    while(0);//Zelle11;
    break;

    case 12: do 
    {
    Zelle12; aus;aus2;
    }
    while(0);//Zelle12;
    break;

    case 13: do 
    {
    Zelle13; aus;aus2;
    }
    while(0);//Zelle13;
    break;

    case 14: do 
    {
    Zelle14; aus;aus2;
    }
    while(0);//Zelle14;
    break;

    case 15: do 
    {
    Zelle15; aus;aus2;
    }
    while(0);//Zelle15;
    break;

    case 16: do 
    {
    Zelle16; aus;aus2;
    }
    while(0);//Zelle16;
    break;

    case 17: do 
    {
    Zelle17; aus;aus2;
    }
    while(0);//Zelle17;
    break;

    case 18: do 
    {
    Zelle18; aus;aus2;
    }
    while(0);//Zelle18;
    break;

    case 19: do 
    {
    Zelle19; aus;aus2;
    }
    while(0);//Zelle19;
    break;

    case 20: do 
    {
    Zelle20; aus;aus2;
    }
    while(0);//Zelle20;
    break;

    case 21: do 
    {
    Zelle21; aus;
    }
    while(0);//Zelle21;
    break;

    case 22: do 
    {
    Zelle22; aus;aus2;
    }
    while(0);//Zelle22;
    break;

    case 23: do 
    {
    Zelle23; aus;aus2;
    }
    while(0);//Zelle23;
    break;

    case 24: do 
    {
    Zelle24; aus;aus2;
    }
    while(0);//Zelle24;
    break;

    default: do
    {
      aus;
    }
    while (0);

    break;

  }
  //end switch

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

Autor: Sven P. (haku) Benutzerseite
Datum:

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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Prozessor?

Oliver

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ATMege8 ext Quarz 14745600

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist einfach nur grauenhaft, da sieht doch keiner mehr durch.

Du mußt doch nur die Bits umsortieren:

#include <io.h>

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


void set_output(uint8_t celnumber)
{
  celnumber--;
  move_bit( celnumber, 0, PORTB, 5 );
  move_bit( celnumber, 1, PORTB, 3 );
  move_bit( celnumber, 2, PORTB, 2 );
  move_bit( celnumber, 3, PORTD, 7 );
  move_bit( celnumber, 4, PORTB, 0 );
  if( celnumber < 8 )
    PORTB |= 1<<4;
  else
    PORTB &= ~(1<<4);
}



Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).
#define aus PORTD&=~(1<<DDD7)|(1<<DDD6);
#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.
#define aus PORTD&=~((1<<DDD7)|(1<<DDD6));
#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
ZelleXX; aus;aus2;
generiert (im Original sind da noch ein paar rjmps's dazwischen, aber am 
Problem ändert das nichts)
ldi  r24, 0x01  ; 1
out  0x18, r24  ; 24
ldi  r24, 0x40  ; 64
out  0x12, r24  ; 18  

in  r24, 0x12  ; 18
andi  r24, 0x3F  ; 63
out  0x12, r24  ; 18
in  r24, 0x18  ; 24
andi  r24, 0x03  ; 3
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mal das Makro von PeDa benutze, dann sollte das im wesentlichen 
so aussehen
#define ADDR_0_PORT   PORTB
#define ADDR_0_PIN    PB5

#define ADDR_1_PORT   PORTB
#define ADDR_1_PIN    PB3

#define ADDR_2_PORT   PORTD
#define ADDR_2_PIN    PD6

#define ENABLE_0_PORT PORTB
#define ENABLE_0_PIN  PB4

#define ENABLE_1_PORT PORTD
#define ENABLE_1_PIN  PD7

#define ENABLE_2_PORT PORTB
#define ENABLE_2_PIN  PB0

#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 );

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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein wenig experimentiert, vielleicht ist es dann einfacher 
nachzuvollziehen. Das ist hier der Ursprung:
#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;

#include <avr\io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

volatile uint32_t mittelwert; //merker der letzten Zellspannung
volatile int fallunterscheidung;
//------------------------------------------------------------------------
// 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
  //----------------------------------------------------------

  // UART initialisieren
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
  UCSRB = 0x08;           //Sender enable UCSRB / UCR bei z.B.: 2313
}
//----------------------------------------------------------------------
void putChar(unsigned char data)
{
  //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
  while (!(UCSRA&32));
  //sende
  UDR=data;
}
//----------------------------------------------------------------------

void initADC()
{
  ADCSRA=0b11000111;      //0b11000011, ADC-Clock, ADC ON
}

unsigned char spannung(void)    //Auswertung ADC...
{
  sbi  (ADCSRA,6);    // restart ADC
  while (ADCSRA & 0x40)
  {
  }      //ende warteschleife für AD-Wandlung

  return (unsigned char) ((ADC/4) && 255);
}

int set_output(int celnumber)
{
  switch (celnumber)
  {

    case 1: Zelle1;
    break;

    case 2: Zelle2;
    break;

    case 3: Zelle3;
    break;

    case 4: Zelle4;
    break;

    case 5: Zelle5;
    break;

    case 6: Zelle6;
    break;

    case 7: Zelle7;
    break;

    case 8: Zelle8;
    break;

    case 9: Zelle9;
    break;

    case 10: Zelle10;
    break;

    case 11: Zelle11;
    break;

    case 12: Zelle12;
    break;

    case 13: Zelle13;
    break;

    case 14: Zelle14;
    break;

    case 15: Zelle15;
    break;

    case 16: Zelle16;
    break;

    case 17: Zelle17;
    break;

    case 18: Zelle18;
    break;

    case 19: Zelle19;
    break;

    case 20: Zelle20;
    break;

    case 21: Zelle21;
    break;

    case 22: Zelle22;
    break;

    case 23: Zelle23;
    break;

    case 24: Zelle24;
    break;

    default: aus;
    break;

  }
  //end switch

}

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.
#define MPLEX_B_OFF()  PORTB=0b00000000;
#define MPLEX_D_OFF() PORTD=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()  do { PORTB = 0b00000000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00000010;//
#define ZELLE10()   do { PORTB = 0b00100000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00100010;//
#define ZELLE11()   do { PORTB = 0b00001000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00001010;// 
#define ZELLE12()   do { PORTB = 0b00101000; PORTD = 0b10000000; } while( 0 )//PORTB=0b00101010;//
#define ZELLE13()   do { PORTB = 0b00000100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00000110;//
#define ZELLE14()   do { PORTB = 0b00100100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00100110;//
#define ZELLE15()   do { PORTB = 0b00001100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00001110;//
#define ZELLE16()   do { PORTB = 0b00101100; PORTD = 0b11000000; } while( 0 )//PORTB=0b00101110;//

#define ZELLE17()  PORTB=0b00000001;            
#define ZELLE18()  PORTB=0b00100001;            
#define ZELLE19()  PORTB=0b00001001;            
#define ZELLE20()  PORTB=0b00101001;            
#define ZELLE21()  do { PORTB=0b00000001; PORTD = 0b01000000;  } while( 0 )  
#define ZELLE22()  do { PORTB=0b00100001; PORTD = 0b01000000;  } while( 0 )
#define ZELLE23()  do { PORTB=0b00001001; PORTD = 0b01000000;  } while( 0 )
#define ZELLE24()  do { PORTB=0b00101001; PORTD = 0b01000000;  } while( 0 )

// Globale Variablen

volatile uint32_t mittelwert; //merker der letzten Zellspannung
volatile int fallunterscheidung;
volatile int16_t i_pidsetpoint=0;  //Sollwert
volatile int i_abbruch;        //Abbruchkriterium für Timer
volatile int16_t i_pidsense=0;          //gucken ob global nötig ist
volatile int16_t i_hold_value;    //Backupvariable für Setpoint, kann ggf gelöscht werden

//------------------------------------------------------------------------
// 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#
  sbi(DDRD,6);  // Multiplexer A2
  sbi(DDRD,7);// (Enable Zelle 9-16)

  // Port Belegung Regelung
  //DDRB|=(1<<DDB1);  // PWM
  DDRC&=~(1<<DDC2);  // Lem Strom Pidsense
  DDRC&=~(1<<DDC0);  // Lem Strom Pidsense
  //----------------------------------------------------------

  // UART initialisieren
  UBRRL  = 7;           //7-->115200 Baud siehe Baudratentabelle//3-->230400
  UCSRB = 8 + 16;           //Sender enable UCSRB / UCR bei z.B.: 2313
}

void initADC()
{
  ADCSRA=0b11000111;      //0b11000011, ADC-Clock, ADC ON
}

unsigned char spannung(void)    //Auswertung ADC...
{
  sbi  (ADCSRA,6);    // restart ADC
  while (ADCSRA & 0x40)
  {
  }      //ende warteschleife für AD-Wandlung

  return (unsigned char) (ADC/4);
}

int set_output(int celnumber)
{
  switch (celnumber)
  {

    case 1: ZELLE1();
    break;

    case 2: ZELLE2();
    break;

    case 3: ZELLE3();
    break;

    case 4: ZELLE4();
    break;

    case 5: ZELLE5();
    break;

    case 6: ZELLE6();
    break;

    case 7: ZELLE7();
    break;

    case 8: ZELLE8();
    break;

    case 9: ZELLE9();
    break;

    case 10: ZELLE10();
    break;

    case 11: ZELLE11();
    break;

    case 12: ZELLE12();
    break;

    case 13: ZELLE13();
    break;

    case 14: ZELLE14();
    break;

    case 15: ZELLE15();
    break;

    case 16: ZELLE16();
    break;

    case 17: ZELLE17();
    break;

    case 18: ZELLE18();
    break;

    case 19: ZELLE19();
    break;

    case 20: ZELLE20();
    break;

    case 21: ZELLE21();
    break;

    case 22: ZELLE22();
    break;

    case 23: ZELLE23();
    break;

    case 24: ZELLE24();
    break;

    default: 
    MPLEX_B_OFF();
    MPLEX_D_OFF();
    break;
}
}


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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark P. (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mark P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mark P. (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.