mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [STM32] CMD0 liefert immer 0xFF zurück


Autor: bbernhard1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche gerade eine SD-Karte mit CMD0 zu initialisieren, aber 
irgendwie klappt das nicht so ganz. So wie ich das verstanden habe, 
sollte die SD-Karte auf CMD0 mit 0x01 antworten, doch ich bekomme immer 
0xFF zurück.

Mein Sourcecode sieht so aus:
void spi_init(){

   //CS = PB12 (General Purpose Output)
   //CLK = PB13 (Alternative Function, Push Pull)
   //SDI(MISO) = PB15 (Input Pull-Up)
   //SDO(MOSI) = PB14 (Alternative Function, Push Pull)

   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //GPIOB clock enable
   GPIOB->CRH &= ~0xFFFF0000;    //clear GPIOB configuration bits
   GPIOB->CRH |= 0x8BB30000; //set GPIOB configuration

   RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;   //SPI2 clock enable
   SPI2->CR1 &= ~SPI_CR1_SPE;  //SPI2 disable
   SPI2->CR1 |= SPI_CR1_CRCEN; //enable hardware CRC calculation
   SPI2->CR1 &= ~SPI_CR1_BIDIMODE; //fullduplex data mode enable
   SPI2->CR1 &= ~SPI_CR1_DFF; //data frame format = 8bit
   SPI2->CR1 &= ~SPI_CR1_SSM; //disable software slave management
   
   SPI2->CR1 |= 0x0038;  //fpclk /256
   SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB transmitted first

   SPI2->CR1 |= SPI_CR1_MSTR; //configure as master
   SPI2->CR1 &= ~SPI_CR1_CPOL; //CPOL = 0
   SPI2->CR1 &= ~SPI_CR1_CPHA; //CPHA = 0

   GPIOB->BSRR |= GPIO_BSRR_BS12; //set pin PB12

   SPI2->CR1 |= SPI_CR1_SPE;  //SPI2 enable

} 
void spi_send(char data){
  SPI2->DR = data;
  while (!(SPI2->SR & SPI_SR_TXE)); //SPI2 Buffer empty?
}
unsigned char spi_receive(){
  char data = 0x00;
  spi_send(0xFF);
  data =  SPI2->DR; //get data 
  while((SPI2->SR & SPI_SR_RXNE) == 0); 
  return data;
}
int main(void){
   int data = 0;
   int i = 0;

   usart2_init(9600);
   USART_TARGET = 2;
   spi_init();
  
   GPIOB->BSRR |= GPIO_BSRR_BS12; //set pin PB12
   for(i=0; i < 10; i++){
    spi_send(0xFF);   //send 8*10 = 80 clock pulses
   }

   //send CMDO
   for(i = 0; i < 500; i++) {
       GPIOB->BSRR &= GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x40);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x95);
       data = spi_receive();
       printf("Data = %d\n", data);
       GPIOB->BSRR |= GPIO_BSRR_BS12; //set pin PB12
       if (data==0x01) break;  
   }

  for(;;){
  }
}

Hat jemand einen Tipp für mich? Langsam gehen mir die Ideen aus...

Autor: Ulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>while (!(SPI2->SR & SPI_SR_TXE)); //SPI2 Buffer empty?

Wartet nicht bis das letzte Byte gesendet wurde, zeigt nur an, das der 
Buffer wieder beschrieben werden kann. Dadurch kommt Deine CS 
Deaktivierung

mit GPIOB->BSRR |= GPIO_BSRR_BS12; //set pin PB12

möglicherweise zu früh.

Benutze mal das BSY Flag,

// Warten bis Byte vollständig gesendet ist
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

Autor: bbernhard1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

hab die Senderoutine folgendermaßen geändert:
void spi_send(char data){
  SPI2->DR = data;
  while ((SPI2->SR & SPI_SR_BSY) == 1);
}

Leider empfange ich immer noch nur 0xFF

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also kompilierbar ist Dein Code so wahrscheinlich nicht; es kann also 
niemand das Ganze mal im Simulator testen. Btw.: Du auch nicht?

Autor: bbernhard1 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Kompilieren kann ich meinen Code. Ich hab hier nur die relevanten 
Codeschnipsel rauskopiert. Im Anhang befinden sich alle 3 Sourcefiles 
die notwendig sind.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bbernhard1 schrieb:
> data =  SPI2->DR; //get data
>   while((SPI2->SR & SPI_SR_RXNE) == 0);

Wenn ich mich im Datenblatt (übrigens: Ich habe in das des 103 
geschaut...) nicht auf die Schnelle verlesen habe, wird RXNE durch das 
Lesen von DR in der Zeile davor auf Null gesetzt. Du VERwhileST danach, 
so lange es Null ist ???
Ehrlich gesagt habe ich aber von den dicken Dingern praktisch noch keine 
Ahnung und dümpel so mit den ARVs rum, also kann es auch Quatsch sein, 
was ich schreibe. Denn sollte der Endlosloop irgendwann mal beendet 
werden, müßte Dein
> printf("Data = %d\n", data);
eigentlich "0" ausgeben ...

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lutz schrieb:
> Denn sollte der Endlosloop irgendwann mal beendet
> werden, müßte Dein
>> printf("Data = %d\n", data);
> eigentlich "0" ausgeben ...

Vielleicht doch plausibel: Kannst Du mal ausprobieren, wenn Du in 
spi_receive statt spi_send(0xFF) mal spi_send(0xEE) schreibt, Du auch 
immer "EE" zurückbekommst? Dann würdest Du nämlich den vorher selbst ins 
DR geschriebenen Wert zurückbekommen.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach ein bischen planschen im kühlen naß:

bbernhard1 schrieb:
> unsigned char spi_receive(){
>   char data = 0x00;
>   spi_send(0xFF);
>   data =  SPI2->DR; //get data
>   while((SPI2->SR & SPI_SR_RXNE) == 0);
>   return data;
> }
- Wenn die Funktion unsigned char zurückliefern soll, sollte data auf so 
definiert werden.
- Empfohlene Vorgehensweise bei Fullduplex:
1. Enable the SPI by setting the SPE bit to 1.
2.Write the first data item to be transmitted into the SPI_DR register 
(this clears the TXE flag).
3. Wait until TXE=1 and write the second data item to be transmitted. 
Then wait until RXNE=1 and read the SPI_DR to get the first received 
data item (this clears the RXNE bit). Repeat this operation for each 
data item to be transmitted/received until the n–1 received data.
4. Wait until RXNE=1 and read the last received data.
5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.

Wobei ich noch nicht verstanden habe, ob der STM32 den CS jetzt 
automatisch steuert oder nicht. Du willst ihn in der for-Schleife selber 
steuern, aber nur dort.
bbernhard1 schrieb:
> GPIOB->BSRR |= GPIO_BSRR_BS12; //set pin PB12
Wenn ich mich nicht vertue, solle es GPIOB->BSRR = GPIO_BSRR_BS12; 
heißen, wenn ganz sicher nur PB12 beeinflußt werden soll. Gilt überall, 
wo Du BSRR benutzt hast. Auch das "&" ist hier überflüssig. Sonst nimmst 
Du jede vorherige Nutzung (Wert) des BSRR-Registers mit!

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm an besten die LIB von STM. Da sind auch Beispiele drin.
http://www.st.com/mcu/download2.php?file=stm32f10x...

Init Bsp. für SPI1 (nur Output) PORT-Einstellungen
  GPIO_DeInit(GPIOA);                                           // Port-Reset
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);         // GPIO Takt freigeben
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,  ENABLE);         // SPI1 Takt freigeben

  // SPI1 an Port A (SCK, MOSI)
  GPIO_InitStructure.GPIO_Pin   = (GPIO_Pin_5 | GPIO_Pin_7);    // PA5=SCK, PA7=MOSI
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;              // Pin-Mode (Alternativ-Funktion)
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             // Pin-Taktung
  GPIO_Init(GPIOA, &GPIO_InitStructure);                        // Port-Einstellung

  // SPI1 CS-Pin
  GPIO_InitStructure.GPIO_Pin   =  GPIO_Pin_4;                  // PA4=CS
  GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_Out_PP;            // Pin-Mode 
  GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;            // Pin Taktung
  GPIO_Init(GPIOA, &GPIO_InitStructure);                        // Port-Einstellung
....


// ***********************************************************************
// SPI Initialisierung
// ***********************************************************************
void init_spi (void) {
  SPI_InitTypeDef  SPI_InitStructure;                                   // SPI Struktur

  // SPI1 Konfiguration
  SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;             // Nur senden
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // SPI Master-Mode
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 8 Datenbits
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                           // CPOL High=Ruhezustand
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                          // CPHA 2. Flanke (L/H) gibt Daten aus
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // CS Chipselect per Software
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;   // Taktfrequenz 72MHz/32 = 2,2 MHz
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // MSB (höherwertiges Bit) zuerst senden
  SPI_InitStructure.SPI_CRCPolynomial = 7;                              // kein CRC Byte
  SPI_Init(SPI1, &SPI_InitStructure);                                   // SPI initialisieren
  SPI_Cmd(SPI1, ENABLE);                                                // SPI freigeben
}

void sendbyte_spi (unsigned char byte) {
  SPI_I2S_SendData(SPI1, byte);                                     // Byte per SPI senden
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);     // Warten bis Byte vollständig gesendet ist
  // TXE geht auch als Auswertung wenn mehrere Byte hintereinander, aber vor CS Deaktivierung (nach letzen Byte) BSY abfragen und warten
}

CS Steuerung musst Du im Bsp selber machen, geht aber auch von der SPI 
Unit her automatisch (NSS)

Autor: bbernhard1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lutz schrieb:
> Vielleicht doch plausibel: Kannst Du mal ausprobieren, wenn Du in
> spi_receive statt spi_send(0xFF) mal spi_send(0xEE) schreibt, Du auch
> immer "EE" zurückbekommst? Dann würdest Du nämlich den vorher selbst ins
> DR geschriebenen Wert zurückbekommen.

Wenn ich spi_send(0xEE) schreibe, dann bekomme ich immer noch 0xFF 
zurück.

Lutz schrieb:
> - Wenn die Funktion unsigned char zurückliefern soll, sollte data auf so
> definiert werden.

Stimmt, habs ausgebessert.

Lutz schrieb:
> - Empfohlene Vorgehensweise bei Fullduplex:
> 1. Enable the SPI by setting the SPE bit to 1.
> 2.Write the first data item to be transmitted into the SPI_DR register
> (this clears the TXE flag).
> 3. Wait until TXE=1 and write the second data item to be transmitted.
> Then wait until RXNE=1 and read the SPI_DR to get the first received
> data item (this clears the RXNE bit). Repeat this operation for each
> data item to be transmitted/received until the n–1 received data.
> 4. Wait until RXNE=1 and read the last received data.
> 5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.

Kanns sein, dass diese Vorgehensweise nur dann gilt wenn ich 16bit 
übertragen möchte?

@Max: Die Lib von STM möchte ich wenns geht vermeiden, da ich die 
ehrlich gesagt nicht so gut finde. Es ist zwar ohne Lib zeitintensiver, 
aber so hab ich wenigstens die Chance die ganzen Register und deren 
Funktion kennenzulernen.


Hab gerade etwas zum RXNE Flag im Reference Manual gefunden:
When set, this flag indicates that there are valid received data in the 
Rx Buffer. It is reset when SPI Data register is read.

Das heißt, ich sollte meine Receive Funktion besser so umschreiben:
unsigned char spi_receive(){
  unsigned char data = 0x00;
  spi_send(0xFF);
  data =  SPI2->DR; //get data 
  while((SPI2->SR & SPI_SR_RXNE) != 0); 
  return data;
} 

Ändert aber leider auch nichts dran...ich bekomme wieder nur 0xFF 
zurück.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spi_send(0xFF);

Ok, du musst was senden um ein Byte zurück zu bekommen.

  data =  SPI2->DR; //get data

Du holst dir das Byte, auch ok.

Was soll das hier? Ist doch alles schon vorbei;)

  while((SPI2->SR & SPI_SR_RXNE) != 0);

Oder gehört das ganz woanders hin?

Autor: bbernhard1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hattest Recht, da hab ich etwas verdreht. Hab mir jetzt nochmal das 
Reference Manual und die STM32 Sourcen angesehen und meine 
Sende/Empfangsroutine korrigiert:
unsigned char spi_receive(){
  unsigned char data = 0x00;
  spi_send(0xFF);
  while((SPI2->SR & SPI_SR_RXNE) == 0); 
  data =  SPI2->DR; //get data 
  return data;
}
void spi_send(char data){
  while ((SPI2->SR & SPI_SR_TXE) == 0);
  SPI2->DR = data;
}


Leider noch immer das Problem mit 0xFF

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast du beachtet, dass NSS im Master Mode beim Senden nicht automaisch 
zurückgesetzt wird? Das ist nämlich etwas "buggy" beim STM32.

Autor: Ulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt Deine SPI überhaupt was aus? Hast Du mal den Oszi dran gehalten.

Ansonsten sind in der STM LIB und zu den EVAL Boards einige Beispiele.

Gegen die Nutzung der STM-LIB spricht eigentlich nichts. Läuft seit der 
Version 3 recht stabil.

Errata Sheet mal durchgesehen? Div. Abhängikeiten ua. der SPI bei 
Nutzung anderer Units.

Autor: bbernhard1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Errata Sheet konnte ich keine Abhängigkeiten zwischen dem USART2 und 
dem SPI2 finden.

Hab mir nochmals das Reference Manual hergenommen und meinen Sourcecode 
überarbeitet.
Erstmal @Lutz: Du hattest mit dieser Aussage Recht:
Lutz schrieb:
> Wenn ich mich nicht vertue, solle es GPIOB->BSRR = GPIO_BSRR_BS12;
> heißen, wenn ganz sicher nur PB12 beeinflußt werden soll. Gilt überall,
> wo Du BSRR benutzt hast. Auch das "&" ist hier überflüssig.

Hab jetzt nochmals ein paar Messungen mit dem Oszi durchgeführt:
-) Der Clock wird generiert
-) Es werden Daten gesendet

Nach unzähligen Testversuchen hab ichs zwei Mal geschafft, 0x01 
zurückzubekommen. Ich bin mir aber nicht sicher ob das ein glücklicher 
"Zufall" war, oder ob die SD Karte ein bisschen zickt.

Mein derzeitiger Code:
void spi_init(){

   //CS = PB12 (General Purpose Output)
   //CLK = PB13 (Alternative Function, Push Pull)
   //SDI(MISO) = PB14 (Input Pull-Up)
   //SDO(MOSI) = PB15 (Alternative Function, Push Pull)

   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //GPIOB clock enable
   GPIOB->CRH &= ~0xFFFF0000;    //clear GPIOB configuration bits
   GPIOB->CRH |= 0xB8B30000; //set GPIOB configuration

   RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;   //SPI2 clock enable
   SPI2->CR1 &= ~SPI_CR1_SPE;  //SPI2 disable
   SPI2->CR1 |= SPI_CR1_CRCEN; //enable hardware CRC calculation
   SPI2->CR1 &= ~SPI_CR1_BIDIMODE; //fullduplex data mode enable
   SPI2->CR1 &= ~SPI_CR1_DFF; //data frame format = 8bit
   SPI2->CR1 &= ~SPI_CR1_SSM; //disable software slave management
   SPI2->CR2 |= SPI_CR2_SSOE; //slave select output is enabled in master mode

   SPI2->CR1 |= 0x0038;  //fpclk /256
   SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB transmitted first

   SPI2->CR1 |= SPI_CR1_MSTR; //configure as master
   SPI2->CR1 &= ~SPI_CR1_CPOL; //CPOL = 0
   SPI2->CR1 &= ~SPI_CR1_CPHA; //CPHA = 0

   GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

   SPI2->CR1 |= SPI_CR1_SPE;  //SPI2 enable
}
void spi_send(char data){
  GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
  while ((SPI2->SR & SPI_SR_TXE) == 0);
  SPI2->DR = data;
  GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
}
unsigned char spi_receive(){
  unsigned char data = 0x00;
  spi_send(0xFF);
  while((SPI2->SR & SPI_SR_RXNE) == 0); 
  data =  SPI2->DR; //get data 
  return data;
}
int main(void){
   int data = 0;
   int i = 0;
   usart2_init(9600);
   USART_TARGET = 2;
   spi_init();

   GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
   for(i=0; i < 10; i++){
    spi_send(0xFF);   //send 8*10 = 80 clock pulses
   }
   
   GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
   //send CMDO
   for(i = 0; i < 500; i++) {
       GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x40);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x00);
       spi_send(0x95);
       data = spi_receive();
       printf("Data = %d\n", data);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
       if (data==0x01) break;  
   }

  for(;;){
  }  
}

Autor: 78787 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast du während dieser init den takt mal runtergesetzt ?
in 90% der beispiele ist der takt hier bei < 1Mhz

erst nach der init wird dann auf  max möglicher takt geschwenkt

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab bereits den größten Taktteiler (fpclk/256) eingestellt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach hinter dem

       spi_send(0x95);

mal mehrere

       data = spi_receive();
       data = spi_receive();

und schau dir jeweils an wie data aussieht.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch hier bekomm ich immer nur 0xFF zurück.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bbernhard1 schrieb:
> Hab jetzt nochmals ein paar Messungen mit dem Oszi durchgeführt:
> -) Der Clock wird generiert
> -) Es werden Daten gesendet
>
> Nach unzähligen Testversuchen hab ichs zwei Mal geschafft, 0x01
> zurückzubekommen. Ich bin mir aber nicht sicher ob das ein glücklicher
> "Zufall" war, oder ob die SD Karte ein bisschen zickt.

Mit diesen beiden Aussagen tippe ich mal auf die Karte. Zumindest hat 
sie dann einen großen Anteil am Problem. Denn wenn die selbe Software 
mal ein Ergebnis liefert und mal nicht, muß etwas anderes das Problem 
verursachen oder zumindest stark mitwirken. Bleibt also nur die 
Hardware. Wenn möglich, einfach mal zum Testen eine andere Karte nehmen. 
Die Kosten ja zum Glück nichts mehr.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab vorhin mal eine andere SD Karte getestet, die hat auch nicht 
funktioniert. Aber der Test ist vermutlich nicht sehr aussagekräftig 
gewesen, da die neue Karte vom gleichen Hersteller wie die alte Karte 
(nämlich Traveler SD-Karte) ist. Lediglich die Speichergröße variiert.

Mal schauen ob ich noch eine Karte von einem anderen Hersteller finde

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, jetzt wirds wirklich strange. Ich hab keine SD-Karte im Slot stecken 
und bekomme trotzdem 0xFF zurück! Was empfängt der da bitte? Die Daten 
die ich wegschicke könnens auch nicht sein, denn wenn ich in meiner 
Empfangsroutine
folgendes ändere:
unsigned char spi_receive(){
  unsigned char data = 0x00;
  //spi_send(0xFF); wird geaendert zu
  spi_send(0x40);
  while((SPI2->SR & SPI_SR_RXNE) == 0); 
  data =  SPI2->DR; //get data 
  return data;
}

dann empfange ich immer noch 0xFF

Der Schaltplan von meinem Entwicklungsboard: 
http://www.olimex.com/dev/images/ARM/ST/STM32-P103-sch.gif

Ich checks nicht...

Autor: hdd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind die Pullups in der MISO-Leitung aktiviert?
Wenn ja, dann mal deaktivieren und nen Pulldown nach Masse bei fehlender 
Karte an die Leitung hängen, dann solltest du auf jeden Fall 0x00 zurück 
bekommen wenn der Fehler nicht in der Software liegt.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab den MISO Pin jetzt mal auf Floating Input geschalten, das heißt 
dann sollte ja nur der Pullup am Entwicklungsboard wirken?
Ändert leider auch nichts dran.

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>SPI2->CR1 &= ~SPI_CR1_CPOL; //CPOL = 0
>SPI2->CR1 &= ~SPI_CR1_CPHA; //CPHA = 0

Ist das überhaupt so Ok? Sieht das Timing auf dem Oszi geanus so aus wie 
im Datenblatt der SD?

Oft Fehler, da bei falscher Einstellung, die Daten zur falschen Zeit 
(H/L, L/H Flanke) übernommen werden.

Autor: STM32 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
btw, der spi hat so eine art fifo wenn ich mich nicht täusche, der füllt 
sich auch mit den sendedaten, also nach jedem senden nochmal das 
datenregister auslesen..
Dann sollte das funktionieren.


char spi_send(char data){

  GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12

  while ((SPI2->SR & SPI_SR_TXE) == 0);
  SPI2->DR = data;

  while((SPI2->SR & SPI_SR_RXNE) == 0);
  data =  SPI2->DR; //get data

  GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

  return data;
}

irgendwie so, hoffe das ist richtig, hab nicht ins datenblatt wegen den 
statusregistern geschaut.

spi_send(xy);                // schreiben
data = spi_send(0xFF);       // lesen

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kuck mal in die aktuelle LIB. Dort ist ein Bsp. für die SD-Karten drin.

STM32F10x_StdPeriph_Lib_V3.3.0\Utilities\STM32_EVAL\Common\stm32_eval_sp 
i_sd.c

Zumindest kannst Dir dort abkucken, wie es geht, auch wenn Du die LIB 
nicht einsetzen willst (Warum eigentlich nicht?). Die Quellen der 
SPI-LIB im SRC-Ordner verraten sicher auch einiges.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@STM32: Ich hab das mal in meine Senderoutine übernommen. Hab das auch 
in der von Matthias K. angesprochenen Library so gefunden. Leider bekomm 
ich noch immer nur 0xFF zurück.

@Matthias K.
Ich hab mir das von dir angesprochene Sourcecodefile aus der ST Library 
angesehen und darin auch die CMD0 Initialisierung gefunden. Soweit ich 
das beurteilen kann, unterscheidet sich der CMD0 Initialisierungsprozess 
nicht wirklich von meinem. Ein paar kleine Unterschiede konnte ich 
feststellen (höherer Takt, Verwendung der internen CRC Calculation 
Unit...), aber wie gesagt kein wesentlicher Unterschied.

Eine andere SD Karte (Kingston 1GB) hab ich auch schon versucht, liefert 
auch nur 0xFF zurück.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat noch jemand nen Tipp?

btw: vielen Dank an alle die sich bis jetzt beteiligt haben!

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh weh, ich habe gerade mal versucht, den Kram der ST-LIB 
nachzuvollziehen und zu überfliegen. Nach mehreren includes und defines 
und hin- und hergespringe bin ich dann abgestürzt. Entweder haben die es 
echt drauf, etwas zu verkomplizieren oder es ist doch viel komplexer 
als ich dachte. Wenn auch nur 10 % des Codes in der LIB wirklich 
erforderlich sind, dann dürften Deine paar Zeilen sicherlich einiges 
ausgelassen haben ...

Du schriebst, daß Du mit einem Oszi Takt und Daten messen konntest. Hat 
das auch alles gestimmt, also Bits, Sequenz, Frequenz etc., und vor 
allem in beide Richtungen? Witzig ist ja auch, daß ohne SPI-Karte 0xFF 
zurückkommt.

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die LIB ist einfacher zu beherschen, als es im ersten Moment aussieht. 
Es ist ein Template für die verschiedenen IDE/Compiler enthalten. Die 
ganze Ordnerstruktur für den Anfang erstmal beibehalten.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist genau der Grund warum ich die Library nicht wirklich mag. Da 
sind so viele defines drinnen um ja alle STM32 Devices abzudecken. Was 
auch ziemlich lustig ist: Oftmals werden dort Namen definiert, die so 
nicht mal im Reference Manual zu finden sind. Da muss man dann erst 
wieder auf Registerebene runter und schauen welche Register tatsächlich 
verwendet werden.

Wenn ich mich nicht verschaut habe, dann sollte meine CMD0 
Initialisierung mit der aus der Standard-Lib übereinstimmen. Wie du 
bereits gesagt hast, ist das ein ziemliches Rumgehopse in den 
Sourcefiles. Ich hoff ich hab nichts übersehen.

Ich werd mir das morgen nochmals mit dem Oszi anschauen. Damals hab ich 
nur geschaut ob ein Takt generiert wird und auf der MOSI Leitung etwas 
gesendet wird. Das sollte ich mir mit dem Oszi echt noch genauer 
untersuchen.

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>SPI2->CR1 &= ~SPI_CR1_CPOL; //CPOL = 0
>SPI2->CR1 &= ~SPI_CR1_CPHA; //CPHA = 0

Hatten wir weiter oben schon, dachte Du hast das gecheckt?

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß, dass sich meine CPOL/CPHA Konfiguration von der Konfiguration 
der STM32 Lib unterscheidet. Wenn ich das richtig verstanden habe, dann 
sollte das auch mit CPOL = 0 und CPHA = 0 funktionieren.
Siehe elm-chan:
"For SDC, the 'SPI mode 0' is defined for its SPI mode. For MMC, it is 
not the SPI timing, both latch and shift actions are defined with rising 
edge of the SCLK, but it seems work in SPI mode 0 in SPI mode. Thus the 
SPI Mode 0 (CPHA=0, CPOL=0) is the proper setting for MMC/SDC interface, 
but SPI mode 3 also works as well in most case."
http://elm-chan.org/docs/mmc/mmc_e.html

Ich habs aber auch schon so probiert, wie ST das in der Library macht - 
es bleibt aber dabei, ich empfange nur 0xFF

Autor: STM32 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest dir mal ein Array erstellen und solange lesen bis der 
empfangsbuffer bzw das datenregister leer ist, das array schaust du dir 
danach mal an, evtl ist doch noch etwas versetzt und somit solltest du 
die zu erwartenden Daten auch irgendwo im array sehen sofern der rest 
richtig ist.

Autor: Bernhard B. (schluchti)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab heute die Messungen mit dem Oszi durchgeführt.

Der Sendevorgang auf der MOSI Leitung sieht ganz gut aus (siehe 
Screenshot).
Um meine Senderoutine zu testen, hab ich in einer Endlosschleife 0x40 
gesendet. Die CPOL/CPHA Konfiguration passt auch, die Daten werden mit 
der steigenden Flanke angelegt.

Der Takt beträgt, wie in der Initialisierungsroutine konfiguriert, 
125kHz.

Die Empfangsroutine macht mir Sorgen, die MISO Leitung ist durchgehend 
auf High...

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Empfangsroutine macht mir Sorgen, die MISO Leitung ist durchgehend
>auf High...

Was ist mit der CS Leitung? Wenn die dauernd high ist kommt
auch nichts raus aus der SD.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
   GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12

Sieht für mich irgendwie gleich aus;)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
>GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12

>Sieht für mich irgendwie gleich aus;)

Nee, doch nicht:( Hab doch glatt das BR12/BS12 übersehen.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber nur irgendwie: Unterschied R und S :-)

Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist schon lang her aber ich kann mich noch blaß daran erinnern...
Hatte damals nen Mp3-Player gebastelt, der lief super mit MMC Karten, SD 
funkionierten nur manchmal.
Ich weiß die Lösung nicht mehr ganz genau, nur daß ich im init der Karte 
irgendwo ne Wartezeit bißchen verlängert hab. Und siehe da, 
funktionierte Tadellos

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
trotzdem irgendwie komisch... ich mach das mit:
GPIOB->BRR = GPIO_Pin_12;      
bzw.
GPIOB->BSRR = GPIO_Pin_12;     

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> trotzdem irgendwie komisch... ich mach das mit:
> GPIOB->BRR = GPIO_Pin_12;      bzw.GPIOB->BSRR = GPIO_Pin_12;

Komisch nicht, aber das Ergebnis eines der viiiiiielen #defines in der 
LIB bzw. der stm32f10x.h, quasi eine Geschmacksfrage: Im jeweiligen BSRR 
sind die unteren 16 bit für das Setzen und die oberen 16 bit für das 
Rücksetzen des jeweiligen bits zuständig. Also kann man alles mit dem 
BSRR machen und braucht das BRR gar nicht. Die Unterscheidung erfolgt 
über die defines
#define GPIO_BSRR_BS12  ((uint32_t)0x00001000)   /*!< Port x Set bit 12 */ 
#define GPIO_BSRR_BR12  ((uint32_t)0x10000000)   /*!< Port x Reset bit 12 */

Autor: Bernhard B. (schluchti)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
holger schrieb:
>>Die Empfangsroutine macht mir Sorgen, die MISO Leitung ist durchgehend
>>auf High...
>
> Was ist mit der CS Leitung? Wenn die dauernd high ist kommt
> auch nichts raus aus der SD.

Ich ziehe die CS Leitung auf Low, schicke ein Datenbyte, lese das 
Empfangsregister um die Antwort der SD Karte zu bekommen und setze CS 
wieder auf High (siehe Screenshot)

gelb = CS
blau = MOSI

Um das mit dem Oszi gut aufnehmen zu können, schicke ich wieder 0x40 in 
der Endlosschleife. MISO bleibt, wie schon vorhin erwähnt, immer auf 
High.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was macht deine Clock Leitung während dessen? Clockt die vllt nicht? :)

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SCK clockt (siehe auch den 1.Oszi-Screenshot weiter oben), hab aber 
leider nur ein Oszi mit 2 Kanälen.

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard B. schrieb:
> Ich ziehe die CS Leitung auf Low, schicke ein Datenbyte, lese das
> Empfangsregister um die Antwort der SD Karte zu bekommen und setze CS
> wieder auf High (siehe Screenshot)

Hm. Ich habe mir jetzt das Timing nicht durchgerechnet, aber die 
High-Phase Deines CS-Signals sieht sehr kurz aus. Vielleicht zu kurz, um 
von der Karte erkannt zu werden. Außerdem macht es den Eindruck, als 
wenn nur 1 Bit und nicht ein ganzes Byte übertragen wird. Wenn das 
Timing aber stimmt und hier 2 Bits aus dem Byte dargestellt sind, dürfte 
CS dazwischen nicht High werden.
Schau Dir z.B. mal Figure 239 auf Seite 660 des Manuals an. Da sieht 
eine SPI-Sequenz doch anders aus.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf welches Manual beziehst du dich? Ich hab hier das Reference Manual 
RM0008 vom STM32F103RBT6 vor mir liegen und da ist auf Seite 660 der 
Watchdog.

Wenn ich keinen groben Denkfehler hab, dann sollte das Timing meiner 
Meinung nach schon stimmen. Ich schicke, wie gesagt, in einer 
Endlosschleife 0x40.

0x40 = 01000000b

Die CS Leitung zieht auf Low, dann wird ausgehend vom MSB das Byte 
übertragen. Nach der Übertragung wird CS wieder auf High gezogen.

Ich werd mal die High-Phase der CS Leitung mit einem delay etwas 
vergrößern.
Vielleicht bringts ja etwas...

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich warte jetzt zwischen jedem Befehl 2ms - bringt aber leider auch 
nichts. Ich hab echt keinen blassen Dunst was da falsch sein könnte...

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard B. schrieb:
> Auf welches Manual beziehst du dich? Ich hab hier das Reference Manual
> RM0008 vom STM32F103RBT6 vor mir liegen und da ist auf Seite 660 der
> Watchdog.

Ich meine auch das RM0008, Doc ID 13902 Rev 11 vom April 2010. Sollte 
eigentlich das Aktuellste sein. Sicher, daß Du nicht bei 460 
nachgeschaut hast?

Bernhard B. schrieb:
> Die CS Leitung zieht auf Low, dann wird ausgehend vom MSB das Byte
> übertragen. Nach der Übertragung wird CS wieder auf High gezogen.

Ich interpretiere den Screenshot so:
CS kommt low ins Bild und wird 20 µs später für ca. 100 ns high, um 
danach wieder low weiterzulaufen. Ca. 15 µs später wird MOSI, der von 
Anfang an low war, für ca. 10 µs high, um dann low weiterzulaufen. Das 
ganze wiederholt sich ca. 70 µs später noch einmal, außer das CS jetzt 
für ca. 200 ns high wird.
=> Ich kann da kein ganzes Byte durchlaufen sehen, sondern nur max. 2 
Bit. Und bei denen wird zwischenzeitlich CS kurz high. Aber ich habe 
auch jetzt nicht das Timing durchgerechnet. Oder sind die beiden 
MOSI-Peaks in Wirklichkeit 2 ganze Bytes (0x04), man erkennt nur wegen 
des gestauchten Zeitstrahls nicht die einzelnen 8 bits da drin?

Oh, Oh, jetzt habe ich aber einen Termin ....

Autor: gggg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast du es mal mit einer fertigen Lib versucht ?

ich hab zB die Elm Chan lib benutzt .
diese lief auch nach einigen anläufen erst richtig ..

gerade das CS timing sollte man bei STM oder höhrern µC nicht dem HW SPI 
überlassen
zumindest haben hier die meisten fertigen Libs ihre schwierigkeiten

wenn da mal ein CS high zu früh kommt wars das mit den 0xFF oder 0xFE ( 
token)

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte post mal Deinen aktuellen Code; mit den ganzen Änderungen wirds 
langsam unübersichtlich.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lutz schrieb:
> Ich meine auch das RM0008, Doc ID 13902 Rev 11 vom April 2010. Sollte
> eigentlich das Aktuellste sein. Sicher, daß Du nicht bei 460
> nachgeschaut hast?

Ich hatte noch ein ältere Version vom RM0008 Manual. Hab gar nicht 
gewusst, dass es schon ein neueres gibt. Danke für den Hinweis!

Lutz schrieb:
> CS kommt low ins Bild und wird 20 µs später für ca. 100 ns high, um
> danach wieder low weiterzulaufen. Ca. 15 µs später wird MOSI, der von
> Anfang an low war, für ca. 10 µs high, um dann low weiterzulaufen. Das
> ganze wiederholt sich ca. 70 µs später noch einmal, außer das CS jetzt
> für ca. 200 ns high wird.
> => Ich kann da kein ganzes Byte durchlaufen sehen, sondern nur max. 2
> Bit. Und bei denen wird zwischenzeitlich CS kurz high. Aber ich habe
> auch jetzt nicht das Timing durchgerechnet. Oder sind die beiden
> MOSI-Peaks in Wirklichkeit 2 ganze Bytes (0x04), man erkennt nur wegen
> des gestauchten Zeitstrahls nicht die einzelnen 8 bits da drin?

Ich werd da morgen nochmals messen, vielleicht bekomme ich den 
Oszi-Screenshot etwas besser hin.

gggg schrieb:
> gerade das CS timing sollte man bei STM oder höhrern µC nicht dem HW SPI
> überlassen
Stimmt, das hab ich mittlerweile auch schon mitbekommen. Die 
Hardware-NSS-Steuerung beim STM32 funktioniert ja mal gar nicht so wie 
gewünscht.
Mittlerweile kontrolliere ich CS komplett per Software, da gibts 
wenigstens keine bösartigen Überraschungen :)

gggg schrieb:
> ich hab zB die Elm Chan lib benutzt .
> diese lief auch nach einigen anläufen erst richtig ..
Mit einer fertigen Lib hab ichs noch nicht versucht.
Im Moment bin ich mir überhaupt nicht sicher wo ich den Fehler vermuten 
soll. Bei der Konfiguration der SPI Schnittstelle, beim Senden der 
Daten, beim Empfangen der Daten oder irgendwo dazwischen? Das ist leider 
der erste Versuch mit der SPI Schnittstelle auf dem STM32, deshalb kann 
ich nicht wirklich etwas ausschließen...

Der aktuelle Code:
void spi_init(){

   //CS = PB12 (General Purpose Output)
   //CLK = PB13 (Alternative Function, Push Pull)
   //SDI(MISO) = PB14 (Input Pull-Up)
   //SDO(MOSI) = PB15 (Alternative Function, Push Pull)

   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //GPIOB clock enable
   GPIOB->CRH &= ~0xFFFF0000;    //clear GPIOB configuration bits
   GPIOB->CRH |= 0xB4B30000; //set GPIOB configuration

   RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;   //SPI2 clock enable
   SPI2->CR1 &= ~SPI_CR1_SPE;  //SPI2 disable
   SPI2->CR1 &= ~SPI_CR1_BIDIMODE; //fullduplex data mode enable
   SPI2->CR1 &= ~SPI_CR1_DFF; //data frame format = 8bit
   SPI2->CR2 |= SPI_CR2_SSOE; //slave select output is enabled in master mode
   
   SPI2->CR1 |= SPI_CR1_SSM; //enable software slave management
  
   SPI2->CR1 |= 0x0028;  //fpclk /64

   SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB transmitted first

   SPI2->CR1 |= SPI_CR1_MSTR; //configure as master
   
   SPI2->CR1 |= SPI_CR1_CPOL; //CPOL = 1
   SPI2->CR1 |= SPI_CR1_CPHA; //CPHA = 1

   SPI2->CR1 |= SPI_CR1_SPE;  //SPI2 enable
}
unsigned char spi_send(unsigned char data){
  unsigned char dat = 0x00;

  while ((SPI2->SR & SPI_SR_TXE) == 0);
  SPI2->DR = data;
  while((SPI2->SR & SPI_SR_RXNE) == 0);
  dat =  SPI2->DR; //get data

  return dat;
} 
int main(void){
   char data = 0;
   int i = 0;
   usart2_init(9600);
   USART_TARGET = 2;
   spi_init();

   
     delay_ms(50);
       GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12
       for(i=0; i < 10; i++){
        delay_ms(2);
        spi_send(0xFF);   //send 8*10 = 80 clock pulses
       }
   
   
   
   GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
   //send CMDO
   for(i = 0; i < 500; i++) {
        delay_ms(2);
       GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x40);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x00);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x00);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x00);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x00);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

      delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
       spi_send(0x95);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    delay_ms(2);
    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
    data = spi_send(0xFF);
    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12

    printf("Data = %d\n", data);
       if (data==1) break;  
   }

  for(;;){
  }     
}

Danke nochmals für die vielen Gedankenanstöße bzw 
Verbesserungsvorschläge!

Autor: gggg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soweit ich das sehe musst du für die init

0x40 0x00 0x00 0x00 0x00 senden mit 0x95 als CRC
das ganze aber als block ohne CS zu ändern
also im prinzip ist das bei jedem commando so ..

CS wird hierbei erst wieder gesetzt wenn man fertig is ..

    GPIOB->BSRR = GPIO_BSRR_BR12; //reset pin PB12
    //send CMDO
    spi_send(0x40);
    spi_send(0x00);
    spi_send(0x00);
    spi_send(0x00);
    spi_send(0x00);
    spi_send(0x95);
    
    n = 10;
    do
    {
       data = spi_send(0xFF);
    }
    while ((data & 0x80)&& --n)

    // hier CS nur wieder setzen wenn man nix weiter tun will 
    // ansonst .. LOW lassen

    GPIOB->BSRR = GPIO_BSRR_BS12; //set pin PB12


bei http://elm-chan.org/fsw/ff/00index_e.html
brauch man "nur" die SPI schreib/lese routinen anzupassen
in den samples gibts genug beispiele

also insgesammt 5 funktionen anpassen
init
spi_send
spi_receive
spi_send_block
spi_receive_block

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut zu wissen. Ich dachte, dass man CS nach jedem Byte wieder auf High 
ziehen muss. Ich hab den Sourcecode jetzt mal dahingehend umgebaut, aber 
leider bekomm ich noch immer 0xFF zurück.

Ich werd jetzt nochmal das Oszi anwerfen, vielleicht entdeck ich da 
etwas.

Autor: Bernhard B. (schluchti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Juhu, es funktioniert!

Ich hab die CS Leitung irrtümlicherweise schon nach dem Befehl 0x95 auf 
High gezogen.

Danke an alle die hier gepostet haben. Ohne euch würd ich wahrscheinlich 
jetzt noch an dem Problem sitzen!

Autor: STM32 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
btw. ich würde sowas einfach über ein define machen..

#define SD_CS0 (GPIOB->BSRR = GPIO_BSRR_BR12)  //reset pin PB12
#define SD_CS1 (GPIOB->BSRR = GPIO_BSRR_BR12)  //  set pin PB12

SD_CS0;

...


SD_CS1;

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.