www.mikrocontroller.net

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


Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
void vs1001_init_io(void)
{
  unsigned char dummy;

  // setup BSYNC
  sbi( DDRA, BSYNC_PIN );   // pin is output for BSYNC
  cbi( BSYNC_PORT,   BSYNC_PIN );   // output low

  // set the MP3/ChipSelect pin hi
  sbi( DDRA, MP3_PIN);       // pin output for xCS
  sbi( MP3_PORT,   MP3_PIN);       // output hi (select MP3)


  // set the /Reset pin hi
  sbi( DDRA, RESET_PIN);     // pin output 
  cbi( RESET_PORT,   RESET_PIN);     // output hi

  cbi(DDRC,DREQ_PIN);//DREQ->INPUT
  // setup serial data interface :
  // clock = f/4
  // select clock phase positive going in middle of data
  // master mode
  // enable SPI

  // setup serial data I/O pins

  sbi(DDRB, PB5);  // set MOSI a output
  
  // PB4 also used as SCK for SPI data        
  sbi(DDRB, PB4);  // SS must be output for Master mode to work
    

  sbi(DDRB, PB7);  // set SCK as output
  cbi(PORTB, PB7);// set SCK lo

  outp((1<<MSTR)|(1<<SPE), SPCR );  // enable SPI interface already done in the mmc routine!!!

  dummy = inp(SPSR);  // clear status
  
  
  /*RESET*/
  
  delay(1000);  // 1 mS      
  sbi(RESET_PORT, RESET_PIN);  // RESET- hi
  delay(5000);  // 5 mS      
  
  
  
    
}
void vs1001_init_chip(void)
{
  //we use a hardware reset, works much better 
  //than software rest, but makes a click noise.

  delay(3000);
  vs1001_nulls(32);
  vs1001_reset();

}
void vs1001_reset(void)
{
  int i;
  uint16_t buf[2];
  SPCR = 1<<SPE | 1<<MSTR | 0<<SPR1 | 1<<SPR0; //SPI Enable, SPI Master Mode
  SPSR = 0 << SPI2X;
  
    for (i=0;i<20;i++)    // 20*10mS = 200 mS
      delay(10000);    // 10 mS

    // set SW reset bit  
    buf[0] = 0x04;
    vs1001_write(0,1,buf);  // set bit 2

    for (i=0;i<2;i++)    // 2*1mS = 2 mS
      delay(1000);    // 1 mS

    //loop_until_bit_is_set(DREQ_PORT , DREQ_PIN); //wait for DREQ
    delay(5000);
    // set CLOCKF for 24.576 MHz
    buf[0] = 0;
    vs1001_write(3,1,buf);  

    vs1001_nulls(16);
    delay(5000);
  SPCR = 1<<SPE | 1<<MSTR | SPI_MP3_SPEED; //SPI Enable, SPI Master Mode
  SPSR = SPI_DOUBLE_SPEED_MP3 << SPI2X;
      
  
}

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.
void vs1001_read(uint8_t address, uint16_t count, uint16_t *pData)
{

  cbi( MP3_PORT, MP3_PIN);  // xCS lo

  write_byte_spi(VS1001_READ);
  write_byte_spi(address);

  while (count--)
  {
    *pData = write_byte_spi(0) << 8;
    *pData++ |= write_byte_spi(0);
  }

  sbi( MP3_PORT, MP3_PIN);  // xCS hi

  //this is absolutely neccessary!
  delay(5); //wait 5 microseconds after sending data to control port
}
void vs1001_write(uint8_t address, uint16_t count, uint16_t *pData)
{
  cbi( MP3_PORT, MP3_PIN);  // xCS lo

  write_byte_spi(VS1001_WRITE);
  write_byte_spi(address);

  while (count--)
  {
    write_byte_spi((uint8_t)((*pData) >> 8));
    write_byte_spi((uint8_t)*pData);
    pData++;
  }
  
  sbi( MP3_PORT, MP3_PIN);  // xCS hi

  //this is absolutely neccessary!
  delay(5); //wait 5 microseconds after sending data to control port
}

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é

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: André (Gast)
Datum:

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

Ich hab dazu folgenden einfachen Code verwendet:
#include "uart.h"
#include <util/delay.h>

#define VS_PORT PORTA
#define VS_DDR DDRA

#define DREQ_PORT PORTC
#define DREQ_DDR DDRC
#define DREQ_PIN PINC

#define VS_DREQ PC0
#define VS_RESET PA0
#define VS_BSYNC PA1
#define VS_CS PA2

void main ()
{
 uart_init();
 int count = 4096;

 VS_DDR |= 1 << VS_RESET | 1 << VS_BSYNC | 1 << VS_CS;  //PORTS sind Ausgänge
 VS_PORT |= 1 << VS_BSYNC | 1 <<VS_CS;          //BSYNC und CS sind HIGH

 DREQ_DDR = 0x00;            //DREQ ist Eingang
 DREQ_PORT |= 1 << VS_DREQ;        //Pullupwiderstand - Braucht man den hier???
 

 VS_PORT &= ~(1 << VS_RESET);      //RESET geht auf LOW
 _delay_us(3000);            //Kurze Verschnaufpause
 VS_PORT |= 1 << VS_RESET;        //RESET geht auf HIGH
 
 while  (count--)                //Um zu sehen, ob DREQ erst LOW dann HIGH wird
  {
   if ( DREQ_PIN & (1 << VS_DREQ))
    {
  uart_putc('~');
    }
   else
    {
   uart_putc('_');
    }
  } 
}

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 ;)

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Storm (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include "uart.h"
#include <util/delay.h>

#define VS_PORT PORTA
#define VS_DDR DDRA
#define VS_PIN PINA

#define DREQ_PORT PORTC
#define DREQ_DDR DDRC
#define DREQ_PIN PINC

#define VS_DREQ PC0
#define VS_RESET PA0
#define VS_BSYNC PA1
#define VS_CS PA2

void main ()
{
 uart_init();
 int count = 4096;

 VS_DDR |= 1 << VS_RESET | 1 << VS_BSYNC | 1 << VS_CS;  //PORTS sind Ausgänge
 VS_PIN |= 1 << VS_BSYNC | 1 <<VS_CS;          //BSYNC und CS sind HIGH

 DREQ_DDR = 0x00;            //DREQ ist Eingang
 //DREQ_PORT |= 1 << VS_DREQ;        //Pullupwiderstand - Braucht man den hier??? Glaube ich weniger.
 

 VS_PIN &= ~(1 << VS_RESET);      //RESET geht auf LOW
 _delay_us(3000);            //Kurze Verschnaufpause
 VS_PIN |= 1 << VS_RESET;        //RESET geht auf HIGH
 
 while  (count--)                //Um zu sehen, ob DREQ erst LOW dann HIGH wird
  {
   if ( DREQ_PIN & (1 << VS_DREQ))
    {
  uart_putc('~');
    }
   else
    {
   uart_putc('_');
    }
  } 
}

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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é

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läuft irgendwie gar nicht :(

Ich hab also die beiden Register gesetzt:
VS_PORT &= ~(1 << VS_CS);
 SPI_MasterTransmit(0x02);   //write
 SPI_MasterTransmit(0x03);   //CLOCKF-Register    
 SPI_MasterTransmit(0x98);   //Wert nach Datenblatt
 SPI_MasterTransmit(0x00);   //für 12,288MHz
 VS_PORT |= 1<< VS_CS;

 _delay_ms(500);

 VS_PORT &= ~(1 << VS_CS);
 SPI_MasterTransmit(0x02);   //write
 SPI_MasterTransmit(0x05);   //AUDATA-Register  
 SPI_MasterTransmit(0xAC);   //Wert für 44100kHz
 SPI_MasterTransmit(0x45);   //steht als Bsp im Datenblatt
 VS_PORT |= 1<< VS_CS;

Hab ich das so richtig verstanden, mit dem Registersetzen?

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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? ;)

Autor: Sebastian ... (zahlenfreak)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.