Forum: Compiler & IDEs einzelne bits ändern in einem Array oder komplett anders ?


von Frank (Gast)


Lesenswert?

Guten Morgen zusammen.


Ich bin momentan etwas am Ausprobieren aber ich komme gerade nicht ganz 
weiter.
Ich habe eine Tastatur Matrix 5x5 und eine LED Matrix 5x7.
einzeln bekomme ich beide angesteuert.
Die LED Matrix ist an PORTD und PORTC angeschlossen an PORTD die Reihen 
und an PORTC die Spalten, welche gemultiplext sind.

Nun wollte ich aber jetzt die mit es leicht machen um bequem die LEDs 
durch ein Array schalten.

Mein Array sieht zum Beispiel so aus
1
uint8_t LED_Array[5] = {0b00011100,
2
                        0b00110110,
3
                        0b01100011,
4
                        0b00110110,
5
                        0b00011100
6
                        };

Wie könnte ich nun bequem sagen wir mal im LED_Array[1] Bit 0 ändern ?

ich hatte mit das so vergestellt das ich meinem Code
LED_1(an);
bzw LED_1(aus);
Schreiben kann und das in dem Array die jeweilige LED an und 
ausgeschaltet wird.

Nur der Zugriff auf das Array ist mir noch ein rätsel.

könnte mir da vieleicht jemand helfen?


Schönes Gruß
Frank

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> ich hatte mit das so vergestellt das ich meinem Code
> LED_1(an);
> bzw LED_1(aus);
> Schreiben kann

Einfacher wirds, wenn Du statt einer im Funktionsnamen codierten Nummer 
die Koordinaten der LED angibst:

  LedAn(int x, int y);

  LedAus(int x, int y);

(x € [0..7], y € [0 .. 4])

Mit y wählst Du das Arrayelement aus, mit x das Bit im Arrayelement.

Damit kommt sowas dabei raus:

LedAn(int x, int y)
{
  LED_Array[y] |= 1 << x;
}

und

LedAus(int x, int y)
{
  LED_Array[y] &= ~ (1 << x);
}

... jeweils ohne Bereichsüberprüfung für x und y, was Du natürlich 
nachpflegen solltest.

von Frank (Gast)


Lesenswert?

Stimmt soweit hatte ich noch gar nicht gedacht. Ich muss jetzt nur mal 
überlegen ob das Praktisch ist bzw. wie und ob ich das umändern könnte.

Die LEDs werden nämlich später auf eine Frontplatte montiert aber nicht 
alle zusammenhängend. Ich nutze hier nur ein gemultiplextes Array um IO 
Pins zu sparen.

Zum Beispiel wird es eine LED geben die Anzeigen soll ob ein Heizdraht 
bestromt wird. Könnte ich mit Defines Festlegen das die Heizdraht LED im 
Array auf x5 y2 liegt ?

Also das man die Funktion mit:

LedAn(Heizdraht_LED);

LedAus(Heizdraht_LED);

oder wäre so was eine total unüblich Programmierung ?

von Rolf Magnus (Gast)


Lesenswert?

Frank schrieb:
> Zum Beispiel wird es eine LED geben die Anzeigen soll ob ein Heizdraht
> bestromt wird. Könnte ich mit Defines Festlegen das die Heizdraht LED im
> Array auf x5 y2 liegt ?
>
> Also das man die Funktion mit:
>
> LedAn(Heizdraht_LED);
>
> LedAus(Heizdraht_LED);
>
> oder wäre so was eine total unüblich Programmierung ?

Man könnte zwar schon sowas wie
1
#define Heizdraht_LED 5,2
machen, aber elegant finde ich das nicht. Wenn deine Matrix aber 
sowieiso nichts mit der mechaninschen Anordnung der LEDs zu tun hat, 
kannst auch alles mit einem einzigen Index machen:
1
LedAn(int index)
2
{
3
  LED_Array[index / 8] |= 1 << (index % 8);
4
}
5
#define Heizdraht_LED 21

von Frank (Gast)


Lesenswert?

Mechanisch sind sie komplett auf der Frontplatte verstreut. Ich benutze 
die wirklich nur in einer Matrix/Multiplex um IO Pins zu sparen


Das mit dem Index schaue ich mir mal an das sind ganz interessant aus

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> Also das man die Funktion mit:
>
> LedAn(Heizdraht_LED);
>
> LedAus(Heizdraht_LED);


Da Du bei Deiner Hardware die Hardwareadresse der LED kennen musst, also 
wissen musst, in welcher Spalte und Zeile diese angeordnet sind, auch 
genau diese Information in zwei #defines unterbringen:

#define SPALTE_HEIZDRAHT_LED 1
#define ZEILE_HEIZDRAHT_LED 3

LedAn(SPALTE_HEIZDRAHT_LED, ZEILE_HEIZDRAHT_LED);

Wenn Dir das zu viel Tipperei ist, lässt sich das wiederum mit einem 
Macro erledigen:

#define LedAnMacro(a) LedAn(SPALTE_##a##_LED, ZEILE_##a##_LED)

so daß Du

LedAnMacro(HEIZDRAHT);

aufrufen musst.


Natürlich kannst Du auch mit einer indexbasierten Lösung arbeiten, aber 
dann musst Du entweder den Index von Hand berechnen ... oder wieder ein 
Macro verwenden, das den aus den "Koordinaten" der Led bestimmt.

von Karl H. (kbuchegg)


Lesenswert?

>
1
> #define SPALTE_HEIZDRAHT_LED 1
2
> #define ZEILE_HEIZDRAHT_LED 3
3
>

Da kannst du aber dann auch gleich für jede LED einfach seine 
Indexnummer und seine Bitnummer innerhalb des Bytes angeben lassen. Das 
ist dann auch schon egal.
1
#define HEIZDRAHT_INDEX 0    // Index 0 im Array
2
#define HEIZDRAHT_BIT   0    // und dort das 0-te Bit
3
4
#define KUEHLUNG_INDEX  0    // Index 0
5
#define KUEHLUNG_BIT    1    // und dort das 1-te Bit

Noch ein bischen Makro Magie rundherum, wie du das angedeutet hast und 
fertig.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Da kannst du aber dann auch gleich für jede LED einfach seine
> Indexnummer und seine Bitnummer innerhalb des Bytes angeben lassen.

Und worin besteht da jetzt der Unterschied? Das ist, von den Namen 
"Spalte" und "Zeile" abgesehen exakt dasselbe.


Die Index-Variante, die hier 
Beitrag "Re: einzelne bits ändern in einem Array oder komplett anders ?" erwähnt wurde, hat 
nicht Bitnummern in Indexwerten, sondern numeriert alle LEDs durch.

von Karl H. (kbuchegg)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Karl Heinz Buchegger schrieb:
>> Da kannst du aber dann auch gleich für jede LED einfach seine
>> Indexnummer und seine Bitnummer innerhalb des Bytes angeben lassen.
>
> Und worin besteht da jetzt der Unterschied?

Dass sich der TO nicht mit der Umsetzung von Spalten und Zeilen in 
Arrayindizes und Bitnummern gedanklich quälen muss :-)

> Das ist, von den Namen
> "Spalte" und "Zeile" abgesehen exakt dasselbe.

Ja. Sollte auch für den TO nur ein Denkanstoss sein, dass er seine 
Matrix in diesem Sinne nicht wortwörtlich als Matrix ansehen muss, 
sondern einfach für eine LED die Ansteuerinformation so festlegen und 
damit arbeiten kann, wie es ihm am leichtesten fällt.

Ob er eine LED als 'sitzt im Schnittpunkt von Zeile z und Spalte s' 
ansieht, oder ob er sie als 'das zuständige Bit ist das Bit Nr b im 
i-ten Eintrag des Arrays' ansieht ist gehupft wie gesprungen. Mir schien 
nur, dass er die 2-te Sichtweise überhaupt nie in Betracht gezogen hätte 
sondern durch den Begriff der 'Matrix' sich selbst unnötigerweise auf 
Zeilen und Spalten festgenagelt sah.

von Frank (Gast)


Lesenswert?

sooo ich habe mal ein bisschen rumgewerkelt und wollte alles einmal 
ausprobieren aber ich hänge da an einem Haken fest und zwar sieht es 
momentan so aus

1
LedAn(int x, int y)
2
{
3
  LED_Array[y] |= (1 << x);
4
}
5
6
7
LedAus(int x, int y)
8
{
9
  LED_Array[y] &= ~ (1 << x);
10
}
11
12
13
14
15
int main(void){
16
  int index;
17
18
  int a,b;
19
20
  DDRD   = 0xFF;
21
  DDRC   = 0xFF;
22
  DDRB   = 0xFF;
23
   PORTB  = 0xFF;
24
  
25
  TCCR1A    =  0x00;          // Timer 1 Initialisieren
26
  TCCR1B    |=  ((1<<CS11) | (1<<CS10));// Prescaler auf "64"
27
  TIMSK    |=  (1<<OCIE1A);      // Output Compare A Interrupt  
28
  OCR1AH    =  0x00;          // einschalten. Interrupt bei:
29
  OCR1AL    =  0x7D;          // 100ms = 10Mhz / 64 / 15624 (0x3D08)
30
                      // OCR1 Inhalt = 4Mhz / 64 * 0,1s
31
                      // =186A
32
33
  TCCR0     = 1<<CS02^1<<CS00;      // divide by 1024
34
  TIMSK    |= 1<<TOIE0;          // Time 0 Initialisieren
35
36
  sei();
37
38
  a=1;
39
  b=1;
40
41
//  LedAn(a,b);
42
//  PORTD = 0x01;
43
  
44
  
45
46
  while(1){
47
48
  LedAn(a,b);
49
50
  
51
  }

Wenn ich das LedAn vor der Whileschleife aufrufe dann geht die richtige 
LED an und wenn ich das in der Whileschleife aufrufe dann geht sie nicht 
an ?!

Woran liegt das denn ?

Danach werde ich das mit dem einzelindex und den makros mal 
ausprobieren.

von benwilliam (Gast)


Lesenswert?

also falls du keine lust hast das rad neu zu erfinden ...
ich habe eine einfachte LED Matrix lib gebastelt

https://github.com/benwilliam/AVR/tree/master/LED

in der LEDMatrix.c findest du funktionen um genau ein bit in einem array 
zu setzen
1
unsigned char setWorkingBufferBit(unsigned char x, unsigned char y, unsigned char value)


in der canvas.c findest du etwas höhere graphik funktionen unter anderem 
einfache 5x7 ASCII zeichen ausgeben

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> Wenn ich das LedAn vor der Whileschleife aufrufe dann geht die richtige
> LED an und wenn ich das in der Whileschleife aufrufe dann geht sie nicht
> an ?!

Die Funktionen LedAn und LedAus schalten nicht die LEDs selbst, sondern 
setzen nur im Array die korrespondierenden Bits.

Wo ist Dein Code, der den Array-Inhalt per Multiplex an die LEDs 
ausgibt?

von Frank (Gast)


Lesenswert?

Ich habe einen Timer Interruppt der alle 1ms ausgelöst wird und dann 
nach unt nach die spalten ausgibt: Momentan ist es auf sehr langsam 
eingestellt so das ich quasi sehe welche spalten immer an sind.
1
ISR (TIMER1_COMPA_vect)
2
{    
3
4
  uint8_t i;
5
    PORTB ^= (1<<PB0) ;
6
  TCNT1L    =  0x00;  //Timer1-Compare-Wert wieder 
7
  TCNT1H    =  0x00;  //auf 0 setzen
8
  
9
10
  ms_100++;
11
  if(ms_100 == 250){
12
  PORTB ^= (1<<PB1) ;
13
  PORTC = LED_Array[Mask];
14
  
15
  PORTD = CulCodes[Mask];
16
  Mask++;
17
  if(Mask==5)
18
    Mask=0;
19
  ms_100 = 0;
20
  }
21
22
}

von Karl H. (kbuchegg)


Lesenswert?

>   TIMSK    |= 1<<TOIE0;          // Time 0 Initialisieren

Und für den Timer 0 hast du auch eine ISR?


Zeig bitte den ganzen Code. Wenn du denkst, dass das zuviel Code ist, 
dann specke ihn auf das Notwendige ab, probier nochmal ob sich auch 
wirklich derselbe Fehler zeigt, und poste das dann.

Für uns Helfer gibt es nichts lästigeres, als wie wenn wir uns aus 
Codeschnipseln die möglichen Fehlerursachen zusammensuchen müssen und 
dann ständig irgendwelche Nachfragen stellen müssen, die sich ganz 
leicht dadurch verhindern lassen, indem du einfach alles zeigst.

Die meisten 'Dauerhelfer' hier sind ziemlich gut darin, auch etwas 
umfangreicheren Code in kurzer Zeit zu verstehen und auf versteckte 
Fehler abzuklopfen. Dazu gehören zb vergessene volatile oder auch 
freigegebene Interrupts, für die es keine ISR gibt. Beides ist mit 
deinen Codeschnipseln nicht beantwortbar.

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.