Forum: Mikrocontroller und Digitale Elektronik APA102 Protokoll wie ansteuern?


von Maci M. (maci_mio)


Angehängte Dateien:

Lesenswert?

Hallo,

Anbei ist ein Ausschnitt des Datenblattes von dem LED-Strip APA102, das 
versenden der 32 Bits über die Datenleitung habe ich soweit verstanden, 
aber wie genau hängt die Clockleitung damit zusammen, ich verstehe das 
überhaupt nicht.
Und wie soll man die Clockleitung mit einem AVR Mikrocontroller 
ansteuern (Ohne Libraries).

Ich würde mich sehr über hilfreiche Antworten/Codebeispiele freuen.

Bitte nicht auf mir rumhacken, habe bisher nur die Grundlagen wie 
Bitmanipulation, Interrupt, Timer, ADC etc. in der Schule gelernt.

von Karl M. (Gast)


Lesenswert?

Hallo,

das Bild ist nicht als Datenblatt geeignet.

Das fand ich gerade: https://cdn-shop.adafruit.com/datasheets/APA102.pdf

Beim Clock-Signal (CKI) ist noch ein PFEIL zu sehen, der anzeigt, dass 
bei einer steigenden Flanke die Daten (DIN) bitweise übernommen werden.

Ist doch ganz einfach.

Einfach einige Prozeduren die das Timing einhalten und dann jeweils die 
Bytes in den 32 Bit Datenstrom wandeln.

Stichwort Bottom Up Programmierung.

von Karl M. (Gast)


Lesenswert?

Hi,

bei weiteren Suchen findet man hier auch viele Beiträge, die Dir helfen 
könnten:

https://www.sparkfun.com/search/results?term=Re%3A+APA102

von Rudolph R. (rudolph)


Lesenswert?

SPI
Einfach nur MOSI und SCK

von Wolfgang (Gast)


Lesenswert?

Rudolph R. schrieb:
> Einfach nur MOSI und SCK

... zusammen mit dem richtigen SPI-Mode, damit die Daten bei der für den 
APA102 entscheidenden steigenden Clock-Flanke stabil sind.

von Einer K. (Gast)


Lesenswert?

Maci M. schrieb:
> Bitte nicht auf mir rumhacken, habe bisher nur die Grundlagen wie
> Bitmanipulation, Interrupt, Timer, ADC etc. in der Schule gelernt.

Das ist doch mehr als ausreichend um das Problem zu lösen!

Wo klemmts?

von Maci M. (maci_mio)


Lesenswert?

Rudolph R. schrieb:
> SPI
> Einfach nur MOSI und SCK

Gibt es irgendwo ein Codebeispiel/Anweisung wie man den SPI bei einen 
ATMega328P einstellt?

von Karl M. (Gast)


Lesenswert?

Maci M. schrieb:
> Gibt es irgendwo ein Codebeispiel/Anweisung wie man den SPI bei einen
> ATMega328P einstellt?

Wird ja häufig geschrieben, die Register und Bits stehen im Datenblatt.
SPI legt die I/O Pins auf feste PortPins!

ABER für den Lernerfolg rate ich Dir, dies komplett in Software zu 
lösen.

von Volker S. (vloki)


Lesenswert?

Maci M. schrieb:
> Und wie soll man die Clockleitung mit einem AVR Mikrocontroller
> ansteuern (Ohne Libraries).

Maci M. schrieb:
> Gibt es irgendwo ein Codebeispiel/Anweisung wie man den SPI bei einen
> ATMega328P einstellt?

Die Clockleitung steuert man überhaupt nicht an, wenn man ein SPI Modul 
benutzt. Man konfiguriert das Modul entsprechend des Diagramms im APA102 
Datasheet. (Was kommt zuerst MSB oder LSB, Ruhelage und aktive Flanke 
von Clk oder so ähnlich)
Danach schiebt man einfach ein Byte in das SPI Senderegister und das 
Modul kümmert sich hoffentlich um den Rest. Ist wie ein Briefkasten.

Beispiel habe ich leider keines, da ich keine AVRs programmiere.

von Harald (Gast)


Lesenswert?

Bevor hier noch ein dritter Thread gestartet wird, ich halte es nicht 
mehr aus... Hier der fertige Code, ungetestet, sollte aber 
funktionieren.

Portrichtung Ausgang musst Du noch anderswo definieren.

#include <avr/io.h>
#define PORT   PORTB
#define CLOCK  1
#define DATA   2

void send_byte (uint8_t value)
{
  int8_t bit;
  for (bit=7; bit>=0; bit--)      // Schleife fuer 8 bits, beginnend 
beim MSB
  {
    if (value & (1<<bit))         // Aktuelles Bit gesetzt?
    {
      PORT |= (1<<DATA);          // DATA setzen
    }
    else
    {
      PORT &= ~(1<<DATA);         // sonst DATA loeschen
    }
    PORT |= (1<<CLOCK);           // an CLOCK eine 0-1-0 Flanke 
ausloesen
    PORT &= ~(1<<CLOCK);
  }
}


void send_start_of_frame (void)     // Startframe senden (4 Bytes 0x00)
{
  send_byte(0x0F);
  send_byte(0x00);
  send_byte(0x00);
  send_byte(0x00);
}

void send_end_of_frame (void)       // Endframe senden (4 Bytes 0xFF)
{
  send_byte(0xFF);
  send_byte(0xFF);
  send_byte(0xFF);
  send_byte(0xFF);
}

void send_led (uint8_t r, uint8_t g, uint8_t b)   // LED Frame setzen
{
  send_byte (0xFF);   // Globale Helligkeit erstmal '11111' gesetzt
  send_byte(r);       // Farbwerte fuer R, G, B senden
  send_byte(g);
  send_byte(b);
}


int main(void)
{
  while (1)
  {
    send_start_of_frame();   // Frame starten

    send_led(255, 0, 0);     // 1. LED ROT
    send_led(0, 255, 0);     // 2. LED GRUEN
    send_led(0, 0, 255);     // 3. LED BLAU
    send_led(255, 255, 0);   // 4. LED GELB

    send_end_of_frame();     // Frame beenden
  }
}

von Harald (Gast)


Lesenswert?

Mist, Copy/Paste Fehler

Korrekt:
void send_start_of_frame (void)     // Startframe senden (4 Bytes 0x00)
{
  send_byte(0x00);
  send_byte(0x00);
  send_byte(0x00);
  send_byte(0x00);
}

von Karl M. (Gast)


Lesenswert?

Vielleicht noch dazu: "Und wie soll man die Clockleitung mit einem AVR 
Mikrocontroller ansteuern (Ohne Libraries).)"

Man Abstrahiere und definiert sich über das Macro SBIT(x,y) und seinen 
Abhängigkeiten ein CLK Signal:
1
//++++++++++++++++++++
2
// SBIT - Peter Dannegger
3
//++++++++++++++++++++
4
// Access bits like variables:
5
struct bits {
6
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
7
} __attribute__((__packed__));
8
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
9
#define SBIT(x,y) SBIT_(x,y)
10
11
//++++++++++++++++++++
12
// Beispiel
13
//++++++++++++++++++++
14
#define DOUT     SBIT(PORTB,0)
15
#define DOUT_DDR SBIT(DDRB,0)
16
#define CLK      SBIT(PORTB,1)
17
#define CLK_DDR  SBIT(DDRB,1)
18
19
20
#include <util/delay.h> // delay_us()
21
22
//++++++++++++++++++++
23
// Init
24
//++++++++++++++++++++
25
DOUT_DDR = 1;
26
DOUT = 0; // low signal
27
CLK_DDR  = 1;
28
CLK = 0; // low signal
29
30
// send 8 bit Data in d
31
uint8_t n = 8; // #bit
32
uint8_t d = 0x55;
33
34
// start send data
35
CLK = 0;
36
37
// send loop
38
while (n) {
39
  if (d & 0x80) { // check MSB
40
    DOUT = 1;
41
  } else {
42
    DOUT = 0;
43
  }
44
  d = d << 1; // shift right
45
  delay_us(1); // Clock
46
  CLK = 1;
47
  delay_us(1); // Clock
48
  CLK = 0;
49
50
  n--; // loop counter
51
}
52
// finish
53
DOUT = 0;
54
//++++++++++++++++++++
55
// end
56
//++++++++++++++++++++

Link: https://www.avrfreaks.net/comment/1926446#comment-1926446

von Maci M. (maci_mio)


Lesenswert?

Danke, aber den Code habe ich auch schon im Internet gefunden.
Aber dieser Code hat doch nichts mit SPI zu tun oder?

von Harald (Gast)


Lesenswert?

Maci M. schrieb:
> Danke, aber den Code habe ich auch schon im Internet gefunden.
> Aber dieser Code hat doch nichts mit SPI zu tun oder?

Genau so glaube ich kaum, den habe ich soeben ohne Vorlage 
zusammengezimmert.

Genau in send_byte wird SPI gemacht. Und zwar unidirectional in Richtung 
LED

von Harald (Gast)


Lesenswert?

Ach, noch ein Codevorschlag, nicht gesehen. Meinst du den oder meinen 
Code?

von Maci M. (maci_mio)


Lesenswert?

Harald schrieb:
> Ach, noch ein Codevorschlag, nicht gesehen. Meinst du den oder
> meinen Code?

Ja,
In diesem Video ab Minute 4:30

https://youtu.be/jQivXOvkkC8

von Harald (Gast)


Lesenswert?

Maci M. schrieb:
> Meinst du den oder
>> meinen Code?
>
> Ja,

Sehr präzise Antwort, super!

Natürlich ist der Code im Video ähnlich, das Protokoll ist ja 
festgelegt. Ich habe noch weiter vereinfacht, Global Brightness gibt es 
z.B. nicht.

von Karl M. (Gast)


Lesenswert?

Also ich bin raus,

Du willst nichts lernen - Video schauen - sondern nur Copy&Past machen.

Lerne das Lesen von Datenblättern und die Programmiersprache deiner 
Wahl.

Dann braucht es keine 1:1 Anleitung.
Selbst ist der M/F/D!

von Maci M. (maci_mio)


Lesenswert?

Karl M. schrieb:
> Du willst nichts lernen

(Die Frage ist für eine anstehende Abschlussprojektarbeit)

Doch klar, wenn ich nichts lernen wollte, hätte ich mich einfach für 
einen Arduino entschieden und eine Library mit der ich nach gefühlt 3 
Zeilen Code den ganzen LED-Streifen zum Leuchten gebracht hätte. Oder 
noch besser wie die meisten der Klassenkameraden für eine 
Datenbankerstellung in Access.

Da wir in der Schule bisher nur das nötigste gelernt haben, ist es für 
mich manchmal etwas schwer, Sachen wie SPI etc. zu verstehen.

von Volker S. (vloki)


Lesenswert?

Maci M. schrieb:
> Da wir in der Schule bisher nur das nötigste gelernt haben, ist es für
> mich manchmal etwas schwer, Sachen wie SPI etc. zu verstehen

Irgendwie habe ich das Gefühl, du weichst dem Verstehen aus.
Was viel einfacheres als synchrone Datenübertragung mit Clock gibt es 
leider nicht.
Evtl. solltest du das mit der Arduino Verweigerung noch mal überdenken 
;-)

von Einer K. (Gast)


Lesenswert?

Maci M. schrieb:
> ist es für
> mich manchmal etwas schwer, Sachen wie SPI etc. zu verstehen.

Je öfter du das wiederholst, desto wahrer wird das für dich.
Desto fester glaubst du selber daran.

Das ist kontraproduktiv.

SPI ist wohl das schlichteste, primitivste und am leichtesten zu 
beherrschende Protokoll/Verfahren.

Aus meiner Sicht, siehst du Komplexität, wo keine ist, und darum meinst 
du es nicht verstanden zu haben.
Dem ist aber nicht so.
Es ist wirklich so einfach.


Beweis:
Maci M. schrieb:
> Aber dieser Code hat doch nichts mit SPI zu tun oder?
Doch, ich habs nicht im Detail überprüft, aber DAS ist eine SPI 
Implementierung.
(beide Varianten)

Auch wenn du Arduino nicht magst/willst, es findet sich dort shiftOut() 
im Quellcode.
Ist das gleiche in grün. Damit hast du ein weiteres Beispiel. Und kannst 
jetzt aufhören dahinter her zu nörgeln.

Wenn du ein Beispiel für HardwareSPI möchtest, dann schaue dir die 
Arduino SPI Library an. Auch diese liegt vollständig im Quellcode vor.

Du kannst auch schauen, wie FastLED das abhandelt.

Nochmal zur Klarstellung:
Ich sage nicht, dass du Arduino verwenden sollst. Aber da gibts das und 
da kannst du dir auch was abschauen.

von Harald (Gast)


Lesenswert?

Bin mit Arduino Fanboy (fast) einer Meinung.

Bau jetzt einfach meinen Code ein und lerne durch die Beobachtung mit 
dem Logic Analyzer. Ich glaube, Du hast beim Thema SPI irgendeine 
Vorstellung von einem komplexen Baustein, den man ansteuern muss. Zu Fuß 
ist das ganz banal, siehe z.B. mein Codebeispiel.
Also keine Verhinderungsgründe mehr suchen sondern einfach machen.

von Maci M. (maci_mio)


Lesenswert?

Ja, ihr hattet Recht.

Ich habe mir SPI viel komplizierter vorgestellt (Software SPI) als es 
eigentlich ist.

Aber finde es auch sehr unfair von manchen Vorwürfe zu bekommen, nur 
weil man sich in manchen Themenbereichen nicht so gut bisher auskennt.

Ich habe hier nur gefragt, um meine Verständnisprobleme zu klären und 
wirklich zu 100% zu verstehen, was der Code eigentlich macht den man 
ausführt.

von Maci M. (maci_mio)


Lesenswert?

Harald schrieb:
> Du hast beim Thema SPI irgendeine Vorstellung von einem komplexen
> Baustein, den man ansteuern muss.

Genau das hatte ich!

von Harald (Gast)


Lesenswert?

Maci M. schrieb:
> Aber finde es auch sehr unfair von manchen Vorwürfe zu bekommen

Na ja, lese Dir beide Threads nochmal durch und denke drüber nach. Fast 
immer hatte man den Eindruck, Du wolltest bei den 
Vorschlägen/Kommentaren dagegen halten.

von Einer K. (Gast)


Lesenswert?

Harald schrieb:
> Fast
> immer hatte man den Eindruck, Du wolltest bei den
> Vorschlägen/Kommentaren dagegen halten.

Auch auf mich, es diesen Eindruck hinterlassen hat!
(frei nach Yoda)

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.