STM32 und 11x74HC595.

OP #7767921
Lesenswert?

Moin,

Ich bräuchte mal Hilfe mit einem Code für die Ansteuerung.

Ich habe 11 Stück 74HC595, die jeweils 84 LEDs ansteuern, 4 Ausgänge sind leer, die Ansteuerung erfolgt scheinbar mit LSB und nicht mit MSB.

Wenn mein Task startet, gehen die LEDs in umgekehrter Reinfolge an und wieder aus, also Beginnend bei Ausgang 88 bis Ausgang 73...

Wie drehe ich das um, so das Ausgang 1 - 16 angesteuert wird?

currentVal & (1 >> i)) brachte leider kein erfolg.

Mein Code:

1
uint64_t currentVal =  0b00000000000000000000000000000000000000000000000000000000000000000000000000000000;
2
void HC595write()
3
{
4
    for(int i=0; i<88; i++)
5
    {
6
        if(currentVal & (1<< i))
7
        {
8
            HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_SET);
9
        }
10
        else
11
        {
12
            HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_RESET);
13
        }
14
        HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_SET);
15
        HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_RESET);
16
    }
17
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_SET);
18
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET);
19
}
20

21
void HC595writePin(uint8_t pin, uint8_t value)
22
{
23
      if (value == 0)
24
      {
25
          currentVal &= ~(1 << pin);
26
      }
27
      else
28
      {
29
          currentVal |= (1 << pin);
30
      }
31
      HC595write();
32
}
33

34
void StartDefaultTask(void *argument)
35
{
36
  /* init code for USB_DEVICE */
37
  MX_USB_DEVICE_Init();
38
  /* USER CODE BEGIN 5 */
39

40
  /* Infinite loop */
41
  for(;;)
42
  {
43

44
    for(int i=0; i < 16; i++)
45
    {
46
      HC595writePin(i, 0);
47
      osDelay(100);
48
    }
49
    osDelay(1000);
50
    for(int i=0; i < 16; i++)
51
        {
52
          HC595writePin(i, 1);
53
          osDelay(100);
54
        }
55
  }
56
  /* USER CODE END 5 */
57
}

vielen Dank für eure Hilfe :)

#7767972
Lesenswert?

Daniel S. schrieb:

Moin,

Ich bräuchte mal Hilfe mit einem Code für die Ansteuerung.

Ich habe 11 Stück 74HC595, die jeweils 84 LEDs ansteuern, 4 Ausgänge sind leer, die Ansteuerung erfolgt scheinbar mit LSB und nicht mit MSB.

Wenn mein Task startet, gehen die LEDs in umgekehrter Reinfolge an und wieder aus, also Beginnend bei Ausgang 88 bis Ausgang 73...

Wie drehe ich das um, so das Ausgang 1 - 16 angesteuert wird?

currentVal & (1 >> i)) brachte leider kein erfolg.

Logisch, du hast den Code nicht verstanden. Siehe Bitmanipulation.

Naja. Solche Sachen packt man in ein Array mit uint8_t Datentyp, das ist verdaulicher, auch für fette 32 Bit CPUs. Und viel besser erweiterbar auf beliebige Schieberegisterlängen. Im aktuellen Code und auch meiner Version unten, liegt das Ende der LED-Kette am Anfang der Daten, denn die werden zuerst ausgegeben. Kann man ggf. auch umdrehen.

1
uint8_t LEDdata[11];
2
 
3
void HC595write()
4
{
5
    int data;
6

7
    for(int i=0; i<11; i++)
8
    {
9
        data = LEDdata[i];
10
        for (int j=0; j < 8; j++)
11
        {
12
            if(data & (1<<j))
13
            {
14
                HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_SET);
15
            }
16
            else
17
            {
18
                HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_RESET);
19
            }
20
            HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_SET);
21
            HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_RESET);
22
        }
23
    } 
24
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_SET);
25
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET);
26
}
27

28
void HC595writePin(uint8_t pin, uint8_t value)
29
{
30
    int bit, byte;
31

32
    byte = pin / 8;
33
    bit = pin % 8;
34

35
    if (value == 0)
36
    {
37
        LEDdata[byte] &= ~(1 << bit);
38
    }
39
    else
40
    {
41
        LEDdata[byte] |= (1 << bit);
42
    }
43
    HC595write();
44
}
45

46
void StartDefaultTask(void *argument)
47
{
48
    /* init code for USB_DEVICE */
49
    MX_USB_DEVICE_Init();
50
    /* USER CODE BEGIN 5 */
51
    /* Infinite loop */
52
    for(;;)
53
    {
54
        for(int i=87; i>=70; i--)
55
        {
56
            HC595writePin(i, 0);
57
            osDelay(100);
58
        }
59
        osDelay(1000);
60
        for(int i=70; i < 88; i++)
61
        {
62
            HC595writePin(i, 1);
63
            osDelay(100);
64
        }
65
    }
66
    /* USER CODE END 5 */
67
}
OP #7767990
Lesenswert?

Hallo Falk,

vielen Dank, habe den Code mal getestet, funktioniert.

habe mal den Code abgeändert, nun funktionierts wie gewollt! :)

1
void HC595write()
2
{
3
  int data;
4
  for(int i=11; i >=  0; i--)
5
  {
6
    data = channelData[i];
7

8
    for(int j=7; j >= 0; j--)
9
    {
10
      if(data & (1<< j))
11
      {
12
        HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_SET);
13
      }
14
      else
15
      {
16
        HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_RESET);
17
      }
18
      HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_SET);
19
      HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_RESET);
20
    }
21
  }
22
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_SET);
23
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET);
24
}
#7767995
Lesenswert?

Daniel S. schrieb:

Hallo Falk,

vielen Dank, habe den Code mal getestet, funktioniert. Jetzt müsste ich nur noch das ganze gedreht bekommen, denn wenn ich Pin 1 auf 1 stelle, geht die LED 88 an u.s.w.

Tja, sagte ich ja bereits.

Über die Bitmanipulation müsste ich doch eigentlich das gedreht bekommen?

Jain, man muss die Adressierung der Bytes auch spiegeln.

Wenn ich meine for-schleife nun aufif(data & (1>> j))

funktionierts leider nicht,

Logisch.

eigentlich muss ich doch die 1 in die andere Richtung schieben mit 1>>j... ?

Das allein reicht nicht.

1
#define LCD_CNT 88
2
#define BYTE_CNT ((LED_CNT+7)/8)
3

4
uint8_t LEDdata[BYTE_CNT];
5
 
6
void HC595write()
7
{
8
    int data;
9

10
    for(int i=BYTE_CNT; i>=0; i--)
11
    {
12
        data = LEDdata[i];
13
        for (int j=7; j >= 0; j--)
14
        {
15
            if(data & (1<<j))
16
            {
17
                HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_SET);
18
            }
19
            else
20
            {
21
                HAL_GPIO_WritePin(SER_GPIO_Port, SER_Pin, GPIO_PIN_RESET);
22
            }
23
            HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_SET);
24
            HAL_GPIO_WritePin(SRCLK_GPIO_Port, SRCLK_Pin, GPIO_PIN_RESET);
25
        }
26
    } 
27
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_SET);
28
    HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET);
29
}
30

31
void HC595writePin(uint8_t pin, uint8_t value)
32
{
33
    int bit, byte;
34

35
    byte = pin / 8;
36
    bit = pin % 8;
37

38
    if (value == 0)
39
    {
40
        LEDdata[byte] &= ~(1 << bit);
41
    }
42
    else
43
    {
44
        LEDdata[byte] |= (1 << bit);
45
    }
46
    HC595write();
47
}
48

49
void StartDefaultTask(void *argument)
50
{
51
    /* init code for USB_DEVICE */
52
    MX_USB_DEVICE_Init();
53
    /* USER CODE BEGIN 5 */
54
    /* Infinite loop */
55
    for(;;)
56
    {
57
        for(int i=0; i<16; i++)
58
        {
59
            HC595writePin(i, 0);
60
            osDelay(100);
61
        }
62
        osDelay(1000);
63
        for(int i=16; i >= 0; i--)
64
        {
65
            HC595writePin(i, 1);
66
            osDelay(100);
67
        }
68
    }
69
    /* USER CODE END 5 */
70
}
Gast #7767997
Lesenswert?

Daniel S. schrieb:

Wenn ich meine for-schleife nun auf if(data & (1>> j)) funktionierts leider nicht

Versuche morgen nochmal, die Frage neu zu formulieren, so dass sie verständlich ist. Bei der Gelegenheit kannst du dann auch eine Skizze von der Verschaltung der Schieberegister und deinen LEDs mit Nummern nachreichen.

Aber erst morgen!

(Firma: Jasinski) #7768110
Lesenswert?

Daniel S. schrieb:

vielen Dank für eure Hilfe :)

Für die 74HC595 kann man eine SPI-Schnittstelle nehmen, um bequem die Daten in die kaskadierten Chips hineinpumpen zu lassen, aber wenn man das Bitkippen schon selbst per Software macht oder üben will oder von mir aus auch machen muss und sowieso viele Kilobytes an SRAM noch übrig hat, kann man z.B. 100 Bytes für ein Bytearray opfern und jeweils nur ein Bit in einem Byte speichern, gerne auch an der LSB-Stelle, also im Bit 0. Dieser verschwenderische Umgang mit dem SRAM, der am Ende des Projekts sowieso ungenutzt im µController liegen würde, erleichtert unheimlich die Bitadressierung, also eigentlich dann schon die LED-Adressierung, da die LED-Adresse dann dem Index vom Array entspricht – demnach wird also auch das Codeschreiben sehr vereinfacht, obendrein wird im Hintergrund von der CPU vermutlich alles deutlich schneller ausgeführt, da grundsätzlich nur noch mit Bytes hantiert wird.

Man muss halt wissen, wann Sparen angesagt ist und wann aus Komfort- oder Geschwindigkeitsgründen das genaue Gegenteil angewandt werden darf – bei einem AT89C2051 oder AT89C51 kommt es auf jedes Byte an und dort muss man teilweise extrem sparen und oft auch zu Assembler greifen, weil auch der Flash relativ kurz ist, beim STM32 ist es Unsinn, krampfhaft irgendwelche Bitakrobatik mit Schiebe-, Modulooperationen oder gar Divisionen, die quasi mit jedem Schleifendurchlauf ausgeführt werden müssen, zu vollführen, wenn man sowieso sehr viel Speicher zur Verfügung hat und alles viel einfacher und vermutlich auch übersichtlicher oder leserlicher in C gestaltet werden kann. Wie ich bereits woanders mal sagte – eine kostbare Ressource, mit der schonend umgegangen werden muss, kann immer etwas anderes bedeuten, mal ist es der Speicher, mal die Zeit, ein anderes mal etwas ganz anderes oder eine Kombination aus allem, aber die wichtigste Ressource eines Homo sapiens ist die entsprechend gefaltete und vernetzte Hirnmasse, die es einem ermöglichen kann, über den Tellerrand hinauszuschauen und generell einen besseren Überblick zu bekommen; ja, zu bekommen, denn dieser wird nicht jedem von der geistigen, unsichtbaren Welt gewährt, geschenkt oder erlaubt, sich diesen selbst hart erarbeiten zu dürfen.

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