Forum: Mikrocontroller und Digitale Elektronik Mega32 mit VS1011 und SD-Karte -> Es will einfach nicht


von André (Gast)


Lesenswert?

Hallo Zusammen

Ich verzweifel hier gleich ...
Also ich will einen Mp3 Player bauen, wie leicht zu erkennen ist an der 
Überschrift.
Ich hab mir so gut wie alle Quelltexte durchgelesen, die hier überall 
veröffentlicht sind. Aber er will nicht!
Zum Stand: Der Mega32 läuft, die SD Karte wird ausgelesen und auch eine 
MP3 Datei kann ich öffnen und über UART die einzelnen Bytes ausgeben. 
Aber der VS1011b will einfach nicht.
Der VS hat 12,288MHz Clock, Schaltung hab ich diese 
(Beitrag "Wecker mit MP3 (vs1011) und SD-Card") aus dem Threat genommen.
Überall stand, ich muss erstmal Register schreiben und lesen, aber auch 
das will nicht.
Dieser Quelltext funktioniert zumindest von Init und vom Reset:
1
void vs1001_init_io(void)
2
{
3
  unsigned char dummy;
4
5
  // setup BSYNC
6
  sbi( DDRA, BSYNC_PIN );   // pin is output for BSYNC
7
  cbi( BSYNC_PORT,   BSYNC_PIN );   // output low
8
9
  // set the MP3/ChipSelect pin hi
10
  sbi( DDRA, MP3_PIN);       // pin output for xCS
11
  sbi( MP3_PORT,   MP3_PIN);       // output hi (select MP3)
12
13
14
  // set the /Reset pin hi
15
  sbi( DDRA, RESET_PIN);     // pin output 
16
  cbi( RESET_PORT,   RESET_PIN);     // output hi
17
18
  cbi(DDRC,DREQ_PIN);//DREQ->INPUT
19
  // setup serial data interface :
20
  // clock = f/4
21
  // select clock phase positive going in middle of data
22
  // master mode
23
  // enable SPI
24
25
  // setup serial data I/O pins
26
27
  sbi(DDRB, PB5);  // set MOSI a output
28
  
29
  // PB4 also used as SCK for SPI data        
30
  sbi(DDRB, PB4);  // SS must be output for Master mode to work
31
    
32
33
  sbi(DDRB, PB7);  // set SCK as output
34
  cbi(PORTB, PB7);// set SCK lo
35
36
  outp((1<<MSTR)|(1<<SPE), SPCR );  // enable SPI interface already done in the mmc routine!!!
37
38
  dummy = inp(SPSR);  // clear status
39
  
40
  
41
  /*RESET*/
42
  
43
  delay(1000);  // 1 mS      
44
  sbi(RESET_PORT, RESET_PIN);  // RESET- hi
45
  delay(5000);  // 5 mS      
46
  
47
  
48
  
49
    
50
}
1
void vs1001_init_chip(void)
2
{
3
  //we use a hardware reset, works much better 
4
  //than software rest, but makes a click noise.
5
6
  delay(3000);
7
  vs1001_nulls(32);
8
  vs1001_reset();
9
10
}
1
void vs1001_reset(void)
2
{
3
  int i;
4
  uint16_t buf[2];
5
  SPCR = 1<<SPE | 1<<MSTR | 0<<SPR1 | 1<<SPR0; //SPI Enable, SPI Master Mode
6
  SPSR = 0 << SPI2X;
7
  
8
    for (i=0;i<20;i++)    // 20*10mS = 200 mS
9
      delay(10000);    // 10 mS
10
11
    // set SW reset bit  
12
    buf[0] = 0x04;
13
    vs1001_write(0,1,buf);  // set bit 2
14
15
    for (i=0;i<2;i++)    // 2*1mS = 2 mS
16
      delay(1000);    // 1 mS
17
18
    //loop_until_bit_is_set(DREQ_PORT , DREQ_PIN); //wait for DREQ
19
    delay(5000);
20
    // set CLOCKF for 24.576 MHz
21
    buf[0] = 0;
22
    vs1001_write(3,1,buf);  
23
24
    vs1001_nulls(16);
25
    delay(5000);
26
  SPCR = 1<<SPE | 1<<MSTR | SPI_MP3_SPEED; //SPI Enable, SPI Master Mode
27
  SPSR = SPI_DOUBLE_SPEED_MP3 << SPI2X;
28
      
29
  
30
}

Also diese Texte scheinen zu funktionieren, also der VS kommt aus dem 
DREQ zurück. Beim Senden und Empfangen der Registereinträge will er 
nicht, ich weiß aber auch nicht so richtig, wie ich es anstellen soll.
1
void vs1001_read(uint8_t address, uint16_t count, uint16_t *pData)
2
{
3
4
  cbi( MP3_PORT, MP3_PIN);  // xCS lo
5
6
  write_byte_spi(VS1001_READ);
7
  write_byte_spi(address);
8
9
  while (count--)
10
  {
11
    *pData = write_byte_spi(0) << 8;
12
    *pData++ |= write_byte_spi(0);
13
  }
14
15
  sbi( MP3_PORT, MP3_PIN);  // xCS hi
16
17
  //this is absolutely neccessary!
18
  delay(5); //wait 5 microseconds after sending data to control port
19
}
1
void vs1001_write(uint8_t address, uint16_t count, uint16_t *pData)
2
{
3
  cbi( MP3_PORT, MP3_PIN);  // xCS lo
4
5
  write_byte_spi(VS1001_WRITE);
6
  write_byte_spi(address);
7
8
  while (count--)
9
  {
10
    write_byte_spi((uint8_t)((*pData) >> 8));
11
    write_byte_spi((uint8_t)*pData);
12
    pData++;
13
  }
14
  
15
  sbi( MP3_PORT, MP3_PIN);  // xCS hi
16
17
  //this is absolutely neccessary!
18
  delay(5); //wait 5 microseconds after sending data to control port
19
}

Ich hab jetzt in der main einfach erst "write" aufrufen und dann bei 
"read" die gleiche Adresse wieder auslesen. Aber er gibt immer wie den 
Anfangswert aus aber keinen Ausgelesenen.
Auch einen Sinustest hab ich schon versucht zu senden, alles mit 
fertigen Codes, angepasst auf meine Pins natürlich, aber will einfach 
nicht klappen.
Hat jemand Tips, woran es liegen kann, worauf man bei dem guten Stück 
besonders achten muss.

Ich bedanke mich schonmal vielmals!

Viele Grüße
André

von Sebastian .. (zahlenfreak)


Lesenswert?

Kennst du diese Appnote schon?

http://www.vlsi.fi/uploads/media/vs10XXan.pdf

Wenn du die Anleitung dadrin wirklich Schritt für Schritt von Oben 
durcharbeitest sollte es eigentlich funktionieren. Oder zumindest hilft 
es den Fehler einzugrenzen.

Gruß, Sebastian

von André (Gast)


Lesenswert?

Also Fehler ist erstmal eingegrenzt, der Chip antwortet nichtmal auf 
Punkt 4.3 (Firmware WakeUp)

Ich hab dazu folgenden einfachen Code verwendet:
1
#include "uart.h"
2
#include <util/delay.h>
3
4
#define VS_PORT PORTA
5
#define VS_DDR DDRA
6
7
#define DREQ_PORT PORTC
8
#define DREQ_DDR DDRC
9
#define DREQ_PIN PINC
10
11
#define VS_DREQ PC0
12
#define VS_RESET PA0
13
#define VS_BSYNC PA1
14
#define VS_CS PA2
15
16
void main ()
17
{
18
 uart_init();
19
 int count = 4096;
20
21
 VS_DDR |= 1 << VS_RESET | 1 << VS_BSYNC | 1 << VS_CS;  //PORTS sind Ausgänge
22
 VS_PORT |= 1 << VS_BSYNC | 1 <<VS_CS;          //BSYNC und CS sind HIGH
23
24
 DREQ_DDR = 0x00;            //DREQ ist Eingang
25
 DREQ_PORT |= 1 << VS_DREQ;        //Pullupwiderstand - Braucht man den hier???
26
 
27
28
 VS_PORT &= ~(1 << VS_RESET);      //RESET geht auf LOW
29
 _delay_us(3000);            //Kurze Verschnaufpause
30
 VS_PORT |= 1 << VS_RESET;        //RESET geht auf HIGH
31
 
32
 while  (count--)                //Um zu sehen, ob DREQ erst LOW dann HIGH wird
33
  {
34
   if ( DREQ_PIN & (1 << VS_DREQ))
35
    {
36
  uart_putc('~');
37
    }
38
   else
39
    {
40
   uart_putc('_');
41
    }
42
  } 
43
}

Aber der DREQ bleibt auf LOW :( Es kam zwar schon zweimal ein HIGH am 
Ende, aber beim nächsten Controller-Reset ging es wieder nicht mehr. 
Sieht jemand einen Fehler? Hab ich was falsch verstanden? Was heißt das 
Ergebnis jetzt? Ist der Chip kaputt?
Die Spannung an RCAP stimmt aber, wenigstens etwas ;)

von Sebastian .. (zahlenfreak)


Lesenswert?

Ohne deinen Code angeschaut zu haben (ich vertrau da mal auf deine 
Programmierkünste).
Wahrscheinlich läuft der Quarz vom VS nicht. Hatte wie viele andere Auch 
genau dieses Problem. Ich hab's dann quasi mit dem Holzhammer gelöst und 
einen Quarzoszillator rangehängt. Wenn du beim einfachen Quarz bleiben 
willst:
Hast du den 1M-Widerstand zwischen IN und OUT?
Die Leitungen vom VS zum Quarz sollten so kurz wie möglich sein. Wenn 
der VS auf einer Adapterplatine sitzt sollte der Quarz auf jeden Fall 
mit da drauf. Die Kondensatoren auch (Die sollte man natürlich auch 
nicht vergessen haben).

Manchmal hilft es, wenn man den Finger auf das Quarz oder die 
Quarzleitungen hält. Wenn es dann halbwegs läuft kannst du zumindest 
ziemlich sicher sein, dass es der Quarz ist.

Achso: Mess mal mit dem Multimeter DREQ. Wenn ich mich recht erinner 
wird der auch nicht mehr low wenn der Kontroller keine Daten sendet. 
Dann kannst du auch einen Softwarefehler ausschließen.

Gruß, Sebastian

von Stephan Storm (Gast)


Lesenswert?

Hallo,

ich bin auch dabei fast den gleichen Mp3 Player zu bauen wie du, nur mit 
dem VS1001.

Also was mir einmal ein ähnliches Problem verschafft hat war, dass ich 
wie du auch mit den PORT Registern gearbeitet habe. Setzt du hier die 
entsprechenden Bits wird das nicht direkt am Ausgang/Eingang übernommen. 
Versuch mal alle Zustandsänderungen an den PINS mit den PICx Registern 
zu realisieren. Dann ist erstmal sichergestellt, dass da nichts schief 
geht. Und dann auf jeden Fall am DREQ mit Multimeter/Oszi Messen. Auf 
die uart-Ausgabe kannst du später vertrauen.

Hier mein Vorschlag:
1
#include "uart.h"
2
#include <util/delay.h>
3
4
#define VS_PORT PORTA
5
#define VS_DDR DDRA
6
#define VS_PIN PINA
7
8
#define DREQ_PORT PORTC
9
#define DREQ_DDR DDRC
10
#define DREQ_PIN PINC
11
12
#define VS_DREQ PC0
13
#define VS_RESET PA0
14
#define VS_BSYNC PA1
15
#define VS_CS PA2
16
17
void main ()
18
{
19
 uart_init();
20
 int count = 4096;
21
22
 VS_DDR |= 1 << VS_RESET | 1 << VS_BSYNC | 1 << VS_CS;  //PORTS sind Ausgänge
23
 VS_PIN |= 1 << VS_BSYNC | 1 <<VS_CS;          //BSYNC und CS sind HIGH
24
25
 DREQ_DDR = 0x00;            //DREQ ist Eingang
26
 //DREQ_PORT |= 1 << VS_DREQ;        //Pullupwiderstand - Braucht man den hier??? Glaube ich weniger.
27
 
28
29
 VS_PIN &= ~(1 << VS_RESET);      //RESET geht auf LOW
30
 _delay_us(3000);            //Kurze Verschnaufpause
31
 VS_PIN |= 1 << VS_RESET;        //RESET geht auf HIGH
32
 
33
 while  (count--)                //Um zu sehen, ob DREQ erst LOW dann HIGH wird
34
  {
35
   if ( DREQ_PIN & (1 << VS_DREQ))
36
    {
37
  uart_putc('~');
38
    }
39
   else
40
    {
41
   uart_putc('_');
42
    }
43
  } 
44
}

von André (Gast)


Lesenswert?

Da bin ich wieder ;)

1. Vielen Dank für den Tip mit dem Clock, daran lag es, das gar nichts 
passiert ist.
-> Hab den Quarz, sowie R und C direkt an den Baustein gelötet.

2. Vielen Dank für die Appnotes. Bin diese jetzt durchgegangen, hat 
alles mehr oder weniger schnell geklappt.

Jetzt bin ich bis zum Sinus-Test gekommen, der kommt laut und deutlich 
draußen an.

Nun also Mp3 Daten:
Ich habe von Roland Riegel die SD Bibliothek genommen, die läuft auch, 
liest die Karte, gibt mir Infos.
Man kann damit auch eine Datei öffnen und sich diese Byte für Byte 
ausgeben lassen. Also immer 32 Byte genommen und an den VS geschickt. 
Aber er will keinen Ton drauß machen :(
- BSYNC ist auf Low beim Senden
- nach 32 Byte wird DREQ abgefragt
- Volume ist hoch

Frage: Muss ich dem VS noch sagen, dass jetzt MP3-Daten kommen 
(VS_STREAM?)
Braucht er nach dem Senden eine gewisse Wartezeit? Darf ich ihm die 
ganze MP3-Datei schicken, am Anfang stehen ja die ID3-Tags (die zeigt 
UART auch richtig an)?

Vielen Dank
André

von Sebastian .. (zahlenfreak)


Lesenswert?

Schaut doch schonmal gut aus.
Das Volume-Register brauchst du erstmal garnicht anfassen. Das ist 
standartmäßig voll aufgedreht.
Dein VS läuft ja auf 12,xxx MHz. Dann musst du den Clock doubler im 
Clock frequency-Register aktivieren.
Nachdem du das register geschrieben hast muss man das Audata-Register 
beschreiben, damit der doubler aktiv wird. Inhalt ist so weit ich weiß 
egal, da dieses Register eigentlich nur zum Lesen von Songdaten ist.

Sonst muss man nichts machen. Bei meiner Init wird auch nur Mode-, 
Frequency- und Audataregister beschrieben. Der Controller erkennt den 
mp3-Header und weiß damit was zu tun ist. ID3-Tag kann auch dabei 
bleiben

Nimm zum Testen erstmal eine mp3 mit geringer Bitrate (z.B. 32kbit/s). 
Wenn du Timingprobleme hast (zu langsamer SPI, Quarz falsch eingestellt, 
zu große Latenzzeit auf DREQ,...) funktioniert es am ehesten noch so.

Und meld dich wieder wie's läuft.

Gruß, Sebastian

von André (Gast)


Lesenswert?

Läuft irgendwie gar nicht :(

Ich hab also die beiden Register gesetzt:
1
VS_PORT &= ~(1 << VS_CS);
2
 SPI_MasterTransmit(0x02);   //write
3
 SPI_MasterTransmit(0x03);   //CLOCKF-Register    
4
 SPI_MasterTransmit(0x98);   //Wert nach Datenblatt
5
 SPI_MasterTransmit(0x00);   //für 12,288MHz
6
 VS_PORT |= 1<< VS_CS;
7
8
 _delay_ms(500);
9
10
 VS_PORT &= ~(1 << VS_CS);
11
 SPI_MasterTransmit(0x02);   //write
12
 SPI_MasterTransmit(0x05);   //AUDATA-Register  
13
 SPI_MasterTransmit(0xAC);   //Wert für 44100kHz
14
 SPI_MasterTransmit(0x45);   //steht als Bsp im Datenblatt
15
 VS_PORT |= 1<< VS_CS;

Hab ich das so richtig verstanden, mit dem Registersetzen?

von Sebastian .. (zahlenfreak)


Lesenswert?

Du musst als erstes das Mode-Register beschreiben. Und VOR jedem Befehl 
musst du mit DREQ prüfen, ob der VS wieder bereit ist.
Das gleiche gilt vor jedem 32-Byte-Block an Daten.

Wenn garnichts gehen will kannst du mal versuchen ein kurzes mp3 (2-5 
sekunden) mit niedriger Bitrate (8-32 kbit/s) direkt mit in den Flash zu 
schreiben und von da aus auszulesen. Für diesen test wird dann nichts 
anderes mehr mitbedient, insbesondere die SD-Karte nicht. Also einfach 
stur aus dem Flash ins SPI. Wenn das mit DREQ nicht hilft könnte es 
nämlich gut sein, dass du Timingprobleme hast.

Grüße, Sebastian

von André (Gast)


Lesenswert?

Achso ok, da versteh ich aber was nicht:
Hat das komplette Mode-Register 16Bit? Wenn ich also beispielsweise 
folgendes sende:
SPI_MasterTransmit(0x02); //für write
SPI_MasterTransmit(0x00); //für Mode-Register
SPI_MasterTransmit(0x01); <- Nur SM_DACT ist auf 1 gesetzt, 9:13 ist 0
SPI_MasterTransmit(0x01); <- Nur SM_DIFF ist auf 1 gesetzt, 1:7 ist 0

Hab ich das richtig verstanden?
Oder ist die Zahl im Datenblatt einfach als Dezimale Zahl zu sehen und 
muss dort ins Register geschrieben werden?

Und was muss ich da genau reinschreiben für die ganzen Werte? Einige 
sind ja logisch, den SM_SHARE muss ich ja auf 0 setzen ...

von Sebastian .. (zahlenfreak)


Lesenswert?

Mode hat 16 bit, es werden aber nur 14 genutzt. Die anderen muss man auf 
null setzen.

Ich hab im Mode-Register nur SM SDINEW gesetzt, der rest ist alles null. 
Wenn du zwei CS-Leitungen (XCS und XDCS) hast muss SM_SDISHARE null 
sein, sonst eins. Wenn du nicht die "stadart-SPI-konfig" verwenden 
willst musst du da auch noch was einstellen (So wie ich das sehe musst 
du das aber nullsetzen).

Sebastian

von André (Gast)


Lesenswert?

Gut, also auch mit Mode-Register mag er mich nicht.

Die SD-Karte wird richtig gelesen, auch Dateien richtig geöffnet und 
richtige Daten angezeigt (würd ich am ID3-Tag jedenfalls vermuten). Auch 
der Sinustest wird eingebettet in die SD-Routinen richtig abgespielt.

Zum Ablauf:
- Öffnen der Datei auf der SD-Karte (ist es möglich)
- Hard-Reset (Reset-Pin auf 0 - dann wieder 1 - DREQ abfragen)
- Soft-Reset (CS-Pin auf 0, SPI senden 0x02 - 0x00 - 0x00 - 0x04 -> DREQ 
)
- Mode-Reg (CS-Pin auf 0, SPI senden 0x02 - 0x00 - 0x00 - 0x00 -> DREQ)
- ClockF-Reg (CS-Pin auf 0, SPI senden 0x02 - 0x03 - 0x98 - 0x00 -> 
DREQ)
- AuData-Reg (CS-Pin auf 0, SPI senden 0x02 - 0x05 - 0xAC - 0x45 -> 
DREQ)
- Immer 32 Byte von der Datei lesen, Bsync-Pin auf 0, SPI senden, Bsync 
auf 1, DREQ abfragen, neue Daten lesen ...

Hab ich da irgendwo was falsch verstanden? Es kommt nämlich gar nichts, 
kein Knacken, nichts.

Dann hab ich heute mal die FuseBits nochmal ausgelesen. Dachte 
eigentlich, die wären richtig gesetzt, jetzt stand aber Interner Clock 
mit 8 MHz da. Wollte ich auf Extern Crystal High ändern, jetzt ging der 
Chip nicht mehr. Also neuer Chip, die Fusebits sind: LOW: 0xE3 ; HIGH: 
0x99 ; LOCK 0xFF
Irgendwie raff ich das noch nicht, will aber auch nicht wieder was 
kaputt machen. Was wäre denn Richtig für Externen Quarz mit 4MHz bzw 
auch 8MHz (wenn das besser wäre für die Übertragung)

VIELEN DANK!!!

von Sebastian .. (zahlenfreak)


Lesenswert?

Nimm einfach den internen Oszillator. Der SD-karte gibts du ja so weit 
ich weiß den Takt vor, beim VS bist du sowieso der Boss. Macht also 
nichts, wenn der Oszillator nicht sooo exakt schwingt. Und 8 MHz reichen 
dicke.

Durchsuch mal bei vlsi.fi die Appnotes. Irgendwo hatte ich dort noch 
gefunden, dass man beim Einschalten RESET und DCS low halten soll. Dann 
erst Reset auf high, mindestens 10ms warten und dann DCS auf high.

Die Registerwerte sollten soweit erstmal passen.

Passen polarität und Flanke beim SPI von VS und AVR überein?

Und versuch es wirklich mal ne mp3 in Flash zu schreiben und von dort 
aus abzuspielen.
Hab bei mir sehr viel Ram angeschlossen und für den ersten Versuch 
einfach ein paar Sekunden mp3 erst in den RAM geladen und von dort 
gespielt. Der erste Versuch von Festplatte zu streamen ist total daneben 
gelaufen.

Sebastian

von André (Gast)


Lesenswert?

Kleine Ergänzung:

Eben war ein Ton zu hören, aber stockend, viel zu langsam bei einer 
32kbit/s Datei. Nach etwas basteln kommt jetzt aber nichts mehr :S

Was für eine SPI-Geschwindigkeit ist denn gut? Ich habe grad SPR0, SPR1 
und SPI2X auf 0, also Clock/4 -> Clock ist auf Intern 8MHz

Was mir aufgefallen ist: Der Sinustest ist ruckelfrei bei 1MHz und 4MHz, 
aber 8MHz stockt er unregelmäßig.

Welche Geschwindigkeit hat denn der VS - ist mit 0x9800 im 
ClockF-Register das richtig mit Clockdoubler bei 12,288MHz Quarz dran?

Sind 32Byte als Buffer ok oder lieber mehr/weniger?


Soweit weg vom Ziel kann ich doch fast gar nicht mehr sein oder? ;)

von Sebastian .. (zahlenfreak)


Lesenswert?

Klingt genau nach dem was ich schon länger befürchte: Du bist nicht 
schnell genug. 32 Byte ist schon sehr knapp als Puffer, mach den mal 
größer. Deine SD-Karte wird ja auch eine gewisse Zugriffszeit haben.

Ob der Wert im ClockF-Register genau passt weiß ich jetzt nicht. Der 
Clock-doubler sollte aber aktiv sein. Könnte nur noch sein, dass die mp3 
zu schnell/langsam gepielt wird. Aber bei einer 32kbit mp3 muss 
eigentlich immer was rauskommen.

1 oder 2 MHz als SPI sollten gehen. Mehr macht beim initialisieren des 
VS probleme.

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.