Hallo, ich kriege meine SPI Schnittstelle einfach nicht zum laufen. im unteren Quelltext ist auch der Senddata-Befehlm der ausgeführt wird. Der GPIOA3 steuert eine LED an. Die leuchtet fleißig, hört dann aber irgendwann einfach auch. Ein clock oder irgendwas ist nicht sichtbar. Wo ist der Fehler? Besten Dank für jede Hilfe -> Ich verwende Keil, Bibliotheken sind ins Projekt eingefügt #include "stm32f10x_conf.h" #include <stm32f10x_lib.h> ErrorStatus HSEStartUpStatus; void RCC_Configuration(void); //Configures Clock for all devices and GPIOs void NVIC_Configuration(void); void GPIO_init(void); void SPI_init (void); //Initializes all required GPIOs void Delay(vu32 nCount); //Creates a delay: nCount / Clock-Speed //Initializes the SPI-interface //Init nested vector interrupt controller #define BufferSize 32 //SPI's Buffersize GPIO_InitTypeDef GPIO_Init_Struct; //Struct für initializing GPIOs SPI_InitTypeDef SPI_InitStructure; //Struct für initializing the SPI-interface //Defining SPI's required Memory for write actions u8 SPI1_Buffer_Tx[BufferSize] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20}; u8 SPI1_Buffer_Rx[BufferSize]; //for read actions u8 TxIdx = 0, RxIdx = 0, k = 0; //setting SPI's control variables and counter k int main(void) { RCC_Configuration (); NVIC_Configuration(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); GPIO_init (); SPI_init(); while (1){ TxIdx = 0; RxIdx = 0; for (k = 0; k < BufferSize; k++) SPI1_Buffer_Rx[k] = 0; while (TxIdx < BufferSize) { GPIO_SetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); GPIO_ResetBits(GPIOA,GPIO_Pin_3); /* Wait for SPI1 Tx buffer empty */ //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) ==RESET); /* Send SPI2 data */ GPIO_SetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); GPIO_ResetBits(GPIOA,GPIO_Pin_3); SPI_I2S_SendData(SPI1, 0x55); /* Wait for SPI2 data reception */ GPIO_SetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); GPIO_ResetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* Read SPI1 received data */ //SPI1_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI1); } } } void SPI_init(void) { //-----Variablendeklaration----- GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; //DMA_InitTypeDef DMA_InitStructure; //-----Pins Configurieren----- /* Config SPI1_NSS - Pin (PA.4) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_SCK - Pin (PA.5) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_MISO - Pin (PA.6) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_MOSI - Pin (PA.7) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //-----SPI-Schnittstelle Initialisierung----- /*Standartinitialisierung*/ SPI_I2S_DeInit(SPI1); /*Spezielle Initialisierung*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master ; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//SPI_BaudRatePrescaler_256; //72MHz / 8 = 9MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //SPI_InitStructure.SPI_CRCPolynomial = 7; //Std-Polynom SPI_Init(SPI1, &SPI_InitStructure); //-----SPI starten----- SPI_Cmd(SPI1, ENABLE); //-----DMA anschalten----- //SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE); /* Standartinitialisierung - DMA1 Channel1 for ADC1 */ //DMA_DeInit(DMA1_Channel1); /* Spezielle Initialisierung */ //DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001244C; //Registeradresse von ADC-Ergebnis //DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ad_buffer[0];//0x40006100; //DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA_InitStructure.DMA_BufferSize = 32; //es sind 32 16bit-Werte =^ 64 8bit-Werte //DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /* DMA1 Channel 2 (SPI1 Rx) initialize */ //DMA_Init(DMA1_Channel2, &DMA_InitStructure); /* DMA Interrupt anschalten bei End of Conversion*/ //DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); /* DMA1 Channel 1 enable bevor ADC sein request sendet */ //DMA_Cmd(DMA1_Channel1, ENABLE); //-----Send Data via SPI----- //SPI_I2S_SendData(SPI1, u16 Data) //-----Send Data via SPI----- //SPI_I2S_ReceiveData(SPI1) } void GPIO_init () { GPIO_DeInit(GPIOA); //Reset GPIOs GPIO_StructInit(&GPIO_Init_Struct); //Connecting GPIO_StructInit with GPIO_Init_Struct GPIO_Init_Struct.GPIO_Pin = GPIO_Pin_3; //Defining which pin is to be initialized GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz; //Defining the previous selected pin's speed GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_Out_PP; //Defining the previous selected pin's mode as push/pull GPIO_Init(GPIOA,&GPIO_Init_Struct); //Initialization of the previous selected pin } /*********************************************************************** ******** * Function Name : RCC_Configuration * Description : Configures the different system clocks. * Input : None * Output : None * Return : None ************************************************************************ *******/ void RCC_Configuration(void) { /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if (HSEStartUpStatus == SUCCESS) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK/2 */ RCC_PCLK2Config(RCC_HCLK_Div2); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE); /* SPI2 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /* PLLCLK = 8MHz * 9 = 72 MHz */ // RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */ // RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ // while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) // {} /* Select PLL as system clock source */ // RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ // while (RCC_GetSYSCLKSource() != 0x08) // {} } } void Delay(vu32 nCount) { for(; nCount != 0; nCount--); } void NVIC_Configuration(void) { #ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #endif }
Edit: Ein clock ist nicht sichtbar soll heißen: Ein sck clock ist nicht messbar , sry
1.) Ein Push so schnell tut absolut nicht not. 2.) Räum deinen Code mal auf, da ist ja ziemlich viel (Mist) auskommentiert. Du wirst da nichts messen können, weil der Clock ja nur während des Sendens anliegt. Darum herum hast du ziemlich viele Delays und Pausen. Gruß Lasse PS: Code-Beispiele bitte erstmal hübscher machen (unnötige eh auskommentierte Zeilen raus) und dann in nen Code-Block.
1 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); |
fehlt schonmal, vielleicht auch noch mehr, aber als text lässt sich Quellcode schlecht lesen.
Ja sry, ich wollte eigentlich auch was rausschmeißen, aber dann fehlt was und die Frage kommt auf: Haste auch wikrlich dieses und jenes gemacht. Beim nächsten mal mach ichs besser, ich poste das evt. gleich nochmal, probier aber erstmal eure tips aus.
die SPI-Clock aktivierst du.
1 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | |
2 | RCC_APB2Periph_SPI1, ENABLE); |
Das passt also. Aber: Du hast da prinzipiell ziemlich viel aus dem Beispiel noch drin, was überhaupt nicht mehr passt (du aktivierst u.a. auch SPI2), dann sind Kommentare falsch... Also: Versteh erstmal, was du mit den einzelnen Schritten im Beispiel überhaupt tust, dann klappt das auch besser.
Also danke schon mal für die Hilfe, ich poste gleich einen ordentlicheren Code. Also hier die SPI_init Routine: void SPI_init(void) { //-----Variablendeklaration----- GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; //DMA_InitTypeDef DMA_InitStructure; //-----Pins Configurieren----- /* Config SPI1_NSS - Pin (PA.4) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_SCK - Pin (PA.5) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_MISO - Pin (PA.6) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Config SPI1_MOSI - Pin (PA.7) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //-----SPI-Schnittstelle Initialisierung----- /*Standartinitialisierung*/ SPI_I2S_DeInit(SPI1); /*Spezielle Initialisierung*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master ; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//SPI_BaudRatePrescaler_256; //72MHz / 8 = 9MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //SPI_InitStructure.SPI_CRCPolynomial = 7; //Std-Polynom SPI_Init(SPI1, &SPI_InitStructure); //-----SPI starten----- SPI_Cmd(SPI1, ENABLE); } Hier der quellcode zum Senden der Daten: int main(void) { RCC_Configuration (); NVIC_Configuration(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); // GPIO_init (); SPI_init(); while (1){ //laufe für immer TxIdx = 0; RxIdx = 0; for (k = 0; k < BufferSize; k++) SPI1_Buffer_Rx[k] = 0; while (TxIdx < BufferSize) { GPIO_SetBits(GPIOA,GPIO_Pin_3); //LED an Delay (0xAFFFF);//Delay,damit man von der LED was sieht GPIO_ResetBits(GPIOA,GPIO_Pin_3); //LED aus //While draußen, weil er hier sonst ewig hängt //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) ==RESET); //Led blinkt einmal GPIO_SetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); GPIO_ResetBits(GPIOA,GPIO_Pin_3); //Hier passiert nix SPI_I2S_SendData(SPI1, 0x55); GPIO_SetBits(GPIOA,GPIO_Pin_3); //LED blinkt Delay (0xAFFFF); GPIO_ResetBits(GPIOA,GPIO_Pin_3); Delay (0xAFFFF); //Anweisung auskommentiert, da er hier sonst hängt, glaube ich //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* Read SPI1 received data, auch mal rausgeschmissen, hat net geholfen */ //SPI1_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI1); } } } Besten Dank für eure Hilfe
Also mein Problem ist, dass ich leider nur noch heute Zeit habe, das
feritg zu kriegen. Wer gut, wenn jemand den Fehler sieht. Grundsätzlich
verstanden was da läuft habe ich schon. das mit den 50 Mhz war ein
Fehler im Eifer des Gefechts. Ich weiß, dass die SPI Schnittstelle max.
18 MHz schafft. Ich finde den Fehler aber trotzdem nicht.
kopiert sind einige Quellcodes aus dem STM Beispiel für Vollduplex
>Datenübertragung mit Soft_NSS. Laufen tut es trotzdem net.
Also, wenn du nochmal Code als Text postest, antworte ich dir nicht mehr. Dafür gibt es Code-Tags, mit denen sich dann der Code gut lesen lässt. Trotzdem zu dem Code: 1.) Wieso hast du das GPIO_init weggeklammert? 2.) Im Firmware-Beispiel wird auch MISO mit AF_PP initialisiert, ob das sinnvoll ist, kann ich aber mangels Erfahrung nicht sagen. 3.) Mach deine Testroutine mal einfacher. Statt dem ganzen Zeugs mit dem Buffer reicht zum testen doch ein
1 | while(1) SPI_I2S_SendData(0xFF); |
Gruß Lasse
Also diese GPIO Sache hab ich brausgenommen, da meine LED an Pin A3 liegt. Meine SPI Schnittstelle liegt aber auch an IO Bank A, nälich A4 bis A7. Ich dachte, das wäre eventuell das Problem. Wars aber net. Und Danke für das Codebeispiel. Habs reinprogrammiert, muss es aber nich zum laufen kriegen. Irgendwo hab ich noch was übersehen...
Ich glaube du musst einmal den Empfangsbuffer(SPI_DR)lesen bevor du wieder senden kannst, siehe ReferenceManual Seite 600(Full-duplex transmit and receive procedure in master or slave mode)
Hallo Steffen, habe deinen Code eingefügt. Es läuft aber trotzdem nicht: Ich konfiguriere zunächst die Clock, mache deine SPI init und dann führe ich deine Funktion spi1_tx aus. Keine Ahnung warum.Im Quellcode rufe ich auch deine Funktionen auf.
Hast du die RCC_Configuration bewusst geändert? Da fehlt nämlich einiges.
Ja, habe ich. Ich verwende keine PLL oder externen Oszillator. Ich verwende nur die internen Oszillatoren.
Ok, mit der Clock Control kenne ich mich nicht so gut aus, fehlt dann nicht trotzdem ein RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); . Achne lese gerade, dass nach einem Reset der HSI oszillator die system clock ist. Ist denn dann
1 | * Enable HSE */ |
2 | RCC_HSEConfig(RCC_HSE_ON); |
richtig?
@Steffen: Hmm, also meine LED kann ich schalten. Und aus dem HSE wird ja alles andere abgeleitet, auch der Clock für IOs .Sollte also nicht daran liegen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.