Zentraler Baustein des Dfplayer-Moduls ist der IC YX5200-24SS. Ein Datenblatt (YX5200-24SS.pdf) zu diesem Baustein findet man im Anhang; höchstwahrscheinlich handelt es sich hierbei um eine automatische Übersetzung aus dem Chinesischen. Dieses Datenblatt ist leider teilweise etwas unübersichtlich, an einigen Stellen auch widersprüchlich bzw. fehlerhaft. Fast alle Beiträge zum DFPlayer greifen letztlich auf dieses Datenblatt zurück, z. B. dfplayer_datashhet_spe033.pdf (s. Anhang). Eine gute Darstellung in deutscher Sprache findet man unter https://bascomforum.de/lexicon/index.ph ... ayer-mini/. Hierauf fußt auch unser Beitrag.
Um den Dfplayer kennen zu lernen, wollen wir:
- eine Test-SD-Karte erstellen
- eine Tasten-Steuerung vorstellen
- eine Programm-Steuerung mit BASCOM vorstellen
Erstellen einer SD-Karte für den Dfplayer
Wir benötigen eine Mikro-SD-Karte mit FAT16 oder FAT32, max. 32 GB. Der Dfplayer besitzt nur ein Mini-FAT-System, welches letztlich nur mit den Nummern der Dateien bzw. Ordnern (Folder) auf der Mikro-SD-Karte arbeitet. Die Struktur auf der SD-Karte sieht dann so aus:
Big Folder (mit jeweils bis zu 3000 Dateien; Dateinummern 4-stellig):
\01
...
\15
Standard Folder (mit jeweils bis zu 255 Dateien; Dateinummern 3-stellig)
\16
..
\99
Ein Ordner für Werbe-Material:
\ADVERT
MP3 Folder (mit bis zu 3000 Dateien; Dateinummern 4-stellig)
\MP3
(Stammverzeichnis mit max. 3000 Dateien)
0001.mp3 bzw. 0001.wav
0002.mp3 bzw. 0002.wav
...
oder auch 0001xxxxx.mp3 bzw. 0001.xxxxx.wav (Zeichenkette xxxxx frei wählbar)
Für die Namen der Dateien in den einzelnen Foldern gilt Ähnliches wie für die Dateien im Stammverzeichnis.
Die gesamte Struktur sollte zunächst auf einem anderen Datenträger vorbereitet werden und dann in einem Zug auf die (noch leere) SD-Karte kopiert werden. Im Hauptverzeichnis richtet sich der Dfplayer nämlich nicht nach dem Dateinamen selbst, sondern nach der Reihenfolge in der FAT. Weitere Informationen dazu findet man unter https://wolles-elektronikkiste.de/dfpla ... em-arduino.
Im Folgenden arbeiten wir mit einer Test-SD-Karte, deren Inhalt sich in der Datei SD.zip im Anhang befindet (Diese Datei stammt von der bereits erwähnten Forum-Seite von BASCOM.). Entpacken Sie diese Datei und kopieren sie den Inhalt dieses Ordners, (nicht den Ordner selbst) auf eine leere SD-Karte.
Tastensteuerung
Wir stecken den Dfplayer auf ein Breadboard und schließen ihn an eine elektrische Quelle mit max. 5 V an. Es bietet sich an, dazu das Nano-Board einzusetzen:
Code: Alles auswählen
Nano DFPlayer
5V Vcc
G GND
Nun verbinden wir das eine Ende eines Jumper-Kabels mit GND und berühren mit dem anderen Ende des Kabels kurz den Anschluss IO2. Die Busy-LED (roter Pfeil in Abb. 1) leuchtet auf und es wird die Datei 0001.mp3 ('Freude auf...') aus dem Stamm-Verzeichnis abgespielt. Diese Busy-LED erlischt erst, wenn die Datei vollständig abgespielt ist. Schon während des Abspielens von 0001.mp3 können wir aber auf die gleiche Weise GND noch einmal (kurz) mit IO2 verbinden. Nun wird die nächste Datei 0002.mp3 ('Song 2') abgespielt. Auf diese Weise können alle Dateien abgespielt werden: Nach den Dateien aus dem Stammverzeichnis kommen die Dateien aus dem Ordner 01 an die Reihe, danach die von Ordner 02... (s. o.). Benutzen wir statt IO2 den Anschluss IO1, dann gelangen wir zur jeweils voran gehenden Datei. Berührt man den Anschluss IO2 etwas länger, dann wird die Lautstärke erhöht, bei IO1 entsprechend verringert. (Bei den gerade dargestellten Sachverhalten widersprechen die Abb. 4.1 bis 4.4 aus dem Datenblatt YX5200-24SS.pdf der Tabelle 2.2 aus demselben Dokument; meine Versuche zeigen, dass die Tabelle korrekt ist. Interessanterweise findet man die falschen Abbildungen in fast jedem Dokument zum Dfplayer.)
Programmierung
Wir wollen hier zeigen, wie man den Dfplayer mit Hilfe des Nano-Boards steuern kann. Dabei kommt es uns darauf an, an Hand einiger wichtiger, typischer Funktionen zu zeigen, wie diese Steuerung funktioniert. Auf dieser Grundlage sollte man dann in der Lage sein, auch weitere Steuerbefehle zu implementieren. Wir greifen dabei zurück auf ein Demo-Programm, welches unter dem oben angegebenen Link auf dem BASCOM-Forum zu finden ist. Unser "Lern-Programm" funktioniert (im Gegensatz zum Programm vom BASCOM-Forum) auch mit der Demo-Version von BASCOM.
Die Steuerung des Dfplayers erfolgt, indem das Nano-Board einen Befehls-Code und ggf. auch weitere Parameter an den Dfplayer sendet. Zusätzlich werden weitere Kontroll-Bytes gesendet. Für jeden Steuerungs-Befehl wird eine Folge von 10 Bytes gesendet. Die Byte-Folge hat folgende Struktur:
Die Bedeutung der einzelnen Bytes ist:
Code: Alles auswählen
Start (Startbyte): &H7E
Ver (Version): &HFF
Len (Length): Anzahl der Bytes von Ver bis ParL inklusive: &H06
Cmd (Command): Befehls-Code (s. u.)
FB (Feedback): 0 (kein Feedback), 1 (Feedback) s. u.
ParH (Parameter High): 1. Parameter, häufig High-Byte, s. u.
ParL (Parameter Low): 2. Parameter, häufig Low-Byte, s. u.
CheckH (Checksum High-Byte): s. u.
CheckL (Checksum Low-Byte): s. u.
End (Endbyte): &HEF
Man kann übrigens auch auf die Check-Summe verzichten; in diesem Fall wird das End-Byte direkt nach dem 2. Parameter-Byte gesendet.
Die Übertragung der einzelnen Bytes erfolgt seriell mit der Konfiguration 9600 Baud, 8 Bit, kein Paritätsbit, 1 Stop-Bit. Wir benutzen in unserem Programm hierzu nicht die Hardware-USART des Atmega328, weil wir diese sowohl für die Programmierung als auch für den Austausch von Daten mit einem Terminal-Programm einsetzen wollen. Mit den BASCOM-Befehlen
Code: Alles auswählen
Open "COMD.2:9600,8,n,1" For Output As #1 'TxD-Nano >>> RX-DFPlayer
Open "COMD.3:9600,8,n,1" For Input As #2 'RxD-Nano >>> TX-DFPlayer
Das Anschluss-Schema ist demnach:
Code: Alles auswählen
Nano DFPlayer
5V Vcc
G GND
D2 - 1K - RX
D3 TX
Kommen wir nun zum Programm. Um dieses einfach zu halten, stellen wir die Byte-Folge durch ein (globales) Array mit der Bezeichnung Cmd dar. Einige Elemente dieses Arrays bleiben gleich; wir legen sie in einer Initialisierungsprozedur fest:
Code: Alles auswählen
Sub Cmd_reset
Cmd(1) = &H7E
Cmd(2) = &HFF
Cmd(3) = &H06
Cmd(4) = 0
Cmd(5) = 0
Cmd(6) = 0
Cmd(7) = 0
Cmd(8) = 0
Cmd(9) = 0
Cmd(10) = &HEF
End Sub
Code: Alles auswählen
Sub Set_checksum
Local Checksum1 As Integer
Checksum1 = 0
For I = 2 To 7
Cmd_wert = Cmd(i)
Checksum1 = Checksum1 - Cmd_wert
Next I
Cmd(8) = High(checksum1) 'High-Byte
Cmd(9) = Low(checksum1) 'Low-Byte
End Sub
Code: Alles auswählen
Sub Cmd_send
Portb.5 = 1 'Nano_LED an (zur Kontrolle)
Call Set_checksum
Printbin #1 , Cmd(1) ; 10
'Printbin Cmd(1) ; 10 'zur Kontrolle am Terminal
Portb.5 = 0 'LED aus
End Sub
Manche Befehle liefern eine Antwort: Hier sendet der Dfplayer eine Byte-Folge mit der gleichen Struktur zurück. Mit der Prozedur Cmd_get werden diese Bytes empfangen und im Cmd_Array gespeichert (vgl. Gesamtprogramm). Hinweis: Mit printbin A(1) ; 10 werden 10 Elemente des Arrays A beginnend mit A(1) ausgegeben.
Hier nun das Gesamtprogramm:
Code: Alles auswählen
' DFPlayer
' Dieses Programm basiert auf dem BASCOM-Programm DEMO_DFplayerMini von
' https://bascomforum.de/lexicon/index.php?entry/93-dfplayer-mini/
' Datei für Nano3-Platine
' Über die zu zugehörige Konfigurationsdatei werden automatisch Voreinstellungen
' für die Kompilierung übernommen; diese betreffen z. B. die Taktfrequenz, die
' Baudrate, die Anschlüsse von LCD, I2C- und SPI-Modulen.
' Eingebaute LED pin13 = PortB.5; blinkt, wenn ein Befehl an das Modul gesendet wird.
' Lautsprecher mit 25 Ohm an SPK1 und SPK2
' Nano DFPlayer
' 5V Vcc
' G GND
' D2 - 1K - RX
' D3 TX
' Kommunikation mit DFPlayer über Software-USART
' Kommunikation mit PC/Terminal über Hardware-USART (zum Testen oder zur Ausgabe von Meldungen)
' Bei Cmd_send und Cmd_get kann optional das vollständige cmd-Array zur Kontrolle
' über die Hardware-Schnittstelle (TxD) des Nano an ein Terminal gesendet werden.
' Achtung: Bei Befehlen mit Rückgabewerten darf zwischen Senden und Empfangen keine Pause liegen,
' da die Software-USART (offensichtlich) keinen Puffer hat!
'----------------------------------------------------------------------------
$regfile = "m328pdef.dat" 'Dadurch wird auch das Pin Layout bestimmt
$crystal = 16000000
$framesize = 32
$swstack = 32
$hwstack = 64
$baud = 9600 'für Hardware-USART, s. o.
'**********************************************************
'******************* Deklarationen ************************
Dim Cmd(10) As Byte 'Array für Befehls-Sequenz
Dim Cmd_wert As Byte
Dim I As Byte 'Globale Schleifen-Variable spart hier Ressourcen
Dim Status As Byte
Declare Sub Cmd_reset
Declare Sub Set_checksum
Declare Sub Cmd_send
Declare Sub Cmd_get
Declare Sub Next_file
Declare Sub Prev_file
Declare Sub Play_file(byval Pfile As Word)
Declare Sub Set_volume(byval Pvalue As Byte)
Declare Sub Resume_file
Declare Sub Pause_file
Declare Sub Set_ampgain(byval Pamp As Byte , Byval Pgain As Byte)
Declare Sub Stop_file
Declare Function Init_player() As Byte
Declare Sub Play_fromfolder(byval Pfolder As Byte , Byval Pfile As Byte)
Declare Sub Play_frombigfolder(byval Pfolder As Byte , Byval Pfile As Word)
Declare Sub Play_frommp3(byval Pfile As Word)
Declare Sub Play_random
Declare Sub Play_allloop(byval Pvalue As Byte)
Declare Function Get_status() As Byte
Declare Function Get_folders() As Byte
Const Pause = 15 'Wartezeit in ms
'**********************************************************
'****************** Initialisierung ***********************
Ddrb.5 = 1 'Nano-LED
'Software-USART:
Open "COMD.2:9600,8,n,1" For Output As #1 'TxD-Nano >>> RX-DFPlayer
Open "COMD.3:9600,8,n,1" For Input As #2 'RxD-Nano >>> TX-DFPlayer
'*******************************************************************************
'******************************* Hauptprogramm *********************************
'Einige Steuerbefehle testen...
Wait 2 'Power-Up
Status = Init_player() 'Initialisierung und Rückmeldung des Status
Printbin Status 'Ausgabe über Terminal
Call Set_volume(25) 'Lautstärke
Call Set_ampgain(1 , 20) 'Verstärker einschalten; 20/31
Call Play_file(5) 'Datei 5 aus Stammverzeichnis abspielen ("Song 5")
Wait 3
Call Play_fromfolder(20 , 6) 'Datei 6 (006.mp3) aus 3. Ordner (20) (Standard-Folder) abspielen: "Song 6"
Wait 3
Call Play_frombigfolder(2 , 4) 'Datei 4 (0004.mp3) aus 2. Ordner (02) (Big-Folder) abspielen: "Song 14"
Wait 3
Call Play_frommp3(5) 'Datei 5 (0005.mp3) aus MP3-Ordner abspielen: "File 5 ... File 5 ... File 5"
Wait 5
Status = Get_status()
Printbin Status 'Ausgabe über Terminal (Status)
Status = Get_folders()
Printbin Status 'Ausgabe über Terminal (Anzahl der Verzeichnisse)
Call Play_file(1) 'Datei 1 (0001.mp3) aus Stammverzeichnis abspielen ("Freude auf...")
Wait 10
Call Stop_file 'Abspielen beenden
Close #2
Close #1
End
'*******************************************************************************
'******************************* Unterprogramme ********************************
' Hilfs-Routinen:
' ##############################################################################
' #
' # Cmd_reset
' # Initialisiert die Befehls-Sequenz
' #
' # Der Aufbau der Befehls-Sequenz setzt sich wie folgt zusammen:
' # Byte 01: Startbyte, ist immer 0x7E
' # Byte 02: Versionsbyte , ist immer 0xFF
' # Byte 03: Byteanzahl beginnend mit dem Versionsbyte bis
' # einschliesslich dem LSB des Parameters; ist immer 0x06
' # Byte 04: Commandbyte
' # Byte 05: Feedback 0x01: Gibt Feedback zurueck, 0x00: kein Feedback
' # Byte 06: Parameter_MSB Hoeherwertiges Byte des Parameters
' # Byte 07: Parameter_LSB Niederwertiges Byte des Parameters
' # Byte 08: Checksum_MSB Hoeherwertiges Byte der Pruefsumme (optional)
' # Byte 09: Checksum_LSB Niederwertiges Byte der Pruefsumme (optional)
' # Byte 10 (bzw. 08, wenn keine Checksum): Endbyte, ist immer 0xEF
' #
' ##############################################################################
Sub Cmd_reset
Cmd(1) = &H7E
Cmd(2) = &HFF
Cmd(3) = &H06
Cmd(4) = 0
Cmd(5) = 0
Cmd(6) = 0
Cmd(7) = 0
Cmd(8) = 0
Cmd(9) = 0
Cmd(10) = &HEF
End Sub
' ##############################################################################
' #
' # Set_CheckSum
' # Berechnet die Pruefsumme und setzt die entsprechenden Bytes
' #
' # Die Pruefsumme berechnet sich aus folgender Formel:
' # 0-Versionsbyte-Byteanzahl-Commandbyte-Feedback-Parameter_MSB-Parameter_LSB
' #
' ##############################################################################
Sub Set_checksum
Local Checksum1 As Integer
Checksum1 = 0
For I = 2 To 7
Cmd_wert = Cmd(i)
Checksum1 = Checksum1 - Cmd_wert
Next I
Cmd(8) = High(checksum1) 'High-Byte
Cmd(9) = Low(checksum1) 'Low-Byte
End Sub
' ##############################################################################
' #
' # Cmd_send
' # Sendet die Befehls-Sequenz über die Software-USART an den Dfplayer
' #
' ##############################################################################
Sub Cmd_send
Portb.5 = 1 'Nano_LED an (zur Kontrolle)
Call Set_checksum
Printbin #1 , Cmd(1) ; 10
'Printbin Cmd(1) ; 10 'zur Kontrolle am Terminal
Portb.5 = 0 'LED aus
End Sub
' ##############################################################################
' #
' # Cmd_get
' # Empfängt 10 Antwort-Bytes vom Dfplayer und speichert sie im Cmd-Array
' #
' ##############################################################################
Sub Cmd_get
Do 'warten auf Start-Byte (eigentlich nur für init_player nötig)
Inputbin #2 , Cmd_wert
Loop Until Cmd_wert = &H7E
Cmd(1) = Cmd_wert
Inputbin #2 , Cmd(2) ; 9
'Printbin Cmd(1) ; 10 'zur Kontrolle
End Sub
' Einige Befehle:
' ##############################################################################
' #
' # Next_file [&H01]
' # Spielt die naechste MP3-Datei entsprechend der FAT-Reihenfolge ab.
' #
' ##############################################################################
Sub Next_file
Call Cmd_reset
Cmd(4) = &H01
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Prev_file [&H02]
' # Spielt die vorhergehende MP3-Datei entsprechend der FAT-Reihenfolge ab.
' #
' ##############################################################################
Sub Prev_file
Call Cmd_reset
Cmd(4) = &H02
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_file [&H03]
' # Spielt eine MP3-Datei aus dem Hauptverzeichnis entsprechend der
' # FAT-Reihenfolge ab.
' #
' # Dateiformat im Folder : 1234.MP3
' #
' # PARAMETER:
' # pFile : 1 bis 3000
' #
' ##############################################################################
Sub Play_file(byval Pfile As Word)
Call Cmd_reset
Cmd(4) = &H03
Cmd(6) = High(pfile)
Cmd(7) = Low(pfile)
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Set_volume [&H06]
' # Setzt die Lautstaerke auf den uebergebenen Wert
' #
' # PARAMETER:
' # pValue : 0 bis 30
' #
' ##############################################################################
Sub Set_volume(byval Pvalue As Byte)
Call Cmd_reset
Cmd(4) = &H06
Cmd(7) = Pvalue 'High Byte = 0
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Init_player [&H0C]
' # Setzt das Modul zurueck und gibt den Status zurueck.
' #
' # Es werden dabei folgende Standardwerte angewendet:
' # Lautstaerke : 30
' # Equalizer : 0
' # Amplifier : 1
' # Gain : 31
' #
' # RUECKGABE: 0 = Nicht bereit, kein Speichermedium vorhanden
' # 1 = USB-Speicherstick
' # 2 = SD-Karte <<<<<<<<<<<<<<<<<<<<<
' # 3 = USB-Speicherstick und SD-Karte
' # 4 = PC
' #
' ##############################################################################
Function Init_player() As Byte
Call Cmd_reset
Cmd(4) = &H0C
Call Cmd_send
Call Cmd_get
Init_player = Cmd(7)
End Function
' ##############################################################################
' #
' # MP3_Resume [&H0D]
' # Spielt einen pausierten Track weiter oder startet den aktuellen Track
' # welcher mittels MP3_Play(Track) vorher aktiviert wurde.
' #
' ##############################################################################
Sub Resume_file
Call Cmd_reset
Cmd(4) = &H0D
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Pause_file [&H0E]
' # Pausiert die gerade abgespielte MP3-Datei. Fortsetzung mit resume_file
' #
' ##############################################################################
Sub Pause_file
Call Cmd_reset
Cmd(4) = &H0E
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_FromFolder [&H0F]
' # Spielt eine MP3-Datei aus dem Ordner 01 - 99 ab
' #
' # Dateiformat im Folder : 123.MP3
' #
' # PARAMETER:
' # pFolder : 1 bis 99 fuer den ausgewaelten Ordner
' # pFile : 1 bis 255 fuer die ausgewaelte Datei
' #
' ##############################################################################
Sub Play_fromfolder(byval Pfolder As Byte , Byval Pfile As Byte)
Call Cmd_reset
Cmd(4) = &H0F
Cmd(6) = Pfolder
Cmd(7) = Pfile
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Set_AmpGain [&H10]
' # Schaltet den Verstaerker ein oder aus und setzt den Verstaerkungsfaktor
' #
' # PARAMETER:
' # pAmp : 0, schaltet den Verstaerker aus
' # : 1, schaltet den Verstaerker ein
' # pGain : 0 bis 31 fuer den Verstaerkungsfaktor
' #
' ##############################################################################
Sub Set_ampgain(byval Pamp As Byte , Byval Pgain As Byte)
Call Cmd_reset
Cmd(4) = &H10
Cmd(6) = Pamp
Cmd(7) = Pgain
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_AllLoop [&H11]
' # Schaltet das wiederholende Abspielen aller Datein ein oder aus.
' #
' # PARAMETER:
' # pValue : 0, Stoppt das abspielen
' # : 1, startet das abspielen
' #
' ##############################################################################
Sub Play_allloop(byval Pvalue As Byte)
Call Cmd_reset
Cmd(4) = &H11
Cmd(7) = Pvalue
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_FromMP3 [&H12]
' # Spielt eine MP3-Datei aus dem Ordner MP3 ab.
' #
' # Dateiformat im Folder : 1234.MP3
' #
' # PARAMETER:
' # pFile : 1 bis 9999 entsprechend der FAT-Reihenfolge
' #
' ##############################################################################
Sub Play_frommp3(byval Pfile As Word)
Call Cmd_reset
Cmd(4) = &H12
Cmd(6) = High(pfile)
Cmd(7) = Low(pfile)
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_FromBigFolder [&H14]
' # Spielt eine MP3-Datei aus einem "grossen" Ordner 01 - 15 ab
' #
' # Dateiformat im Ordner: 1234.MP3
' #
' # PARAMETER:
' # pFolder : 1 bis 15 fuer den ausgewaelten Ordner
' # pFile : 1 bis 3000 fuer die ausgewaelte Datei
' #
' ##############################################################################
Sub Play_frombigfolder(byval Pfolder As Byte , Byval Pfile As Word)
Call Cmd_reset
Cmd(4) = &H14
Shift Pfolder , Left , 4
Pfolder = Pfolder + High(pfile)
Cmd(6) = Pfolder
Cmd(7) = Low(pfile)
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Stop_file [&H16]
' # Beendet das Abspielen der laufenden MP3-Datei.
' #
' ##############################################################################
Sub Stop_file
Call Cmd_reset
Cmd(4) = &H16
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Play_Random [&H18]
' # Spielt alle Dateien des Mediums zufaellig ab
' #
' # HINWEIS: Es wird immer mit Track 1 begonnen, die Titel danach sind dann
' # tatsaechlich zufaellig!
' #
' ##############################################################################
Sub Play_random
Call Cmd_reset
Cmd(4) = &H18
Call Cmd_send
Waitms Pause
End Sub
' ##############################################################################
' #
' # Get_Status [&H42]
' # Gibt den aktuellen Status zurueck
' #
' # RUECKGABE: 0 = SD-Karte, ist gestoppt oder im Sleep-Modus
' # 1 = SD-Karte spielt einen Track
' # 2 = SD-Karte ist im Pausenmodus
' #
' ##############################################################################
Function Get_status() As Byte
Call Cmd_reset
Cmd(4) = &H42
Call Cmd_send
Call Cmd_get
Get_status = Cmd(7)
End Function
' ##############################################################################
' #
' # Get_Folders [&H4F]
' # Gibt die Anzahl der Ordner auf dem Medium zurueck
' #
' # RUECKGABE: Anzahl der Ordner
' #
' # HINWEIS: Auch das Hauptverzeichnis ist ein Ordner und wird daher
' # hinzugezaehlt!
' # Das Resultat hat daher den Mindestwert von 1.
' #
' ##############################################################################
Function Get_folders() As Byte
Call Cmd_reset
Cmd(4) = &H4F
Call Cmd_send
Call Cmd_get
Get_folders = Cmd(7)
End Function