einzelne bits ändern in einem Array oder komplett anders ?

Gast #2359811
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
Persönliche Seite #2359850
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.
Gast #2359857
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 ?
Gast #2359983
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
Gast #2359991
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
Persönliche Seite #2360054
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.
#2360102
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.
Persönliche Seite #2360241
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.
#2360395
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.
Gast #2361011
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.
Gast #2361020
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
Persönliche Seite #2361026
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?
Gast #2361033
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
}
#2361158
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren