2011-04-18 06:29 AM
2011-05-17 05:31 AM
SPI requires that the master generate the clock signal when transmitting OR receiving. You need to transmit a dummy byte to generate the clocks for each incoming byte.
Jack Peacock2011-05-17 05:31 AM
SPI_I2S_ReceiveData merely reads the internal register of the STM32 of the data received during the last SPI_I2S_SendData. ie as you send data across the SPI bus to the slave, the master clocks back in the data the slave is sending.
Try looking at the ST library (2.0.1) example code bundled with the IAR/KEIL evals. \ST\STM32F10xFWLib\Examples\SPI\M25P64_FLASH /******************************************************************************* * Function Name : SPI_FLASH_ReadByte * Description : Reads a byte from the SPI Flash. * This function must be used only if the Start_Read_Sequence * function has been previously called. * Input : None * Output : None * Return : Byte Read from the SPI Flash. *******************************************************************************/ u8 SPI_FLASH_ReadByte(void) { return (SPI_FLASH_SendByte(Dummy_Byte)); } /******************************************************************************* * Function Name : SPI_FLASH_SendByte * Description : Sends a byte through the SPI interface and return the byte * received from the SPI bus. * Input : byte : byte to send. * Output : None * Return : The value of the received byte. *******************************************************************************/ u8 SPI_FLASH_SendByte(u8 byte) { /* Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_I2S_SendData(SPI1, byte); /* Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(SPI1); }2011-05-17 05:31 AM
''SPI_I2S_ReceiveData'' just returns the current value of the data register of the SPI peripheral (''return SPIx->DR'') and does not encapsulate the complete data transaction as anyone would expect from the library function :).
As peacock.jack wrote, the SPI nature is mostly full duplex bidirectional: the receiption takes place while sending the data or in other words, to receive the data ''write'' transaction should be initiated like below (pseudocode): WAIT_FOR_TXE; SPI_I2S_SendData(SPI1, value); if (read_transaction) { WAIT_FOR_RXNE; value = SPI_I2S_ReceiveData(SPI1) }2011-05-17 05:31 AM
Ok, so i get that i need to send to be able to receive. What im trying to do as a first thing (im pretty new at this which you maybe have noticed by now so please have patience) is to read the manufacturer id and device id from the flash memory. I read in the flash memory data sheet that i could send 0x90 followed by 0x000000 to the memory, and get back 0xEF followed by 0x14 which would be the id's. If i can't receive it with the SPI_I2S_ReceiveData function, how do i set it up? I just want to get this into a variable. Im doing this as a first step just to see that im really communicating with my external flash memory.
This is the code i have so far: ========================== ////////// INCLUDES /////////// #include ''stddef.h'' #include ''stm32f10x.h'' #include ''stm32f10x_gpio.h'' #include <stm32f10x_spi.h> #include ''string.h'' ////////////// DEFINE //////////////// #define SPI_COMMS SPI1 #define PORT_SPI_COMMS GPIOA #define PIN_SPI_COMMS_NCS GPIO_Pin_4 #define PIN_SPI_COMMS_SCK GPIO_Pin_5 #define PIN_SPI_COMMS_MISO GPIO_Pin_6 #define PIN_SPI_COMMS_MOSI GPIO_Pin_7 //////////// FUNCTIONS //////////// void RCC_Configuration(void); void GPIO_Configuration(void); void SPI_Configuration(void); void NVIC_Configuration(void); ///////////// MAIN //////////////////// int main(void) { uint16_t data1=0, data2=0; //NVIC_Configuration(); RCC_Configuration(); GPIO_Configuration(); SPI_Configuration(); //memory ChipSelect must set high and thn low after powerup GPIO_SetBits(GPIOA, GPIO_Pin_4);//Chip select set high GPIO_ResetBits(GPIOA, GPIO_Pin_4);//Chip select set low for(;;){ //Chip select set low GPIO_ResetBits(GPIOA, GPIO_Pin_4); //find out manufacturer id and device id SPI_I2S_SendData(SPI1,0x09); //10010000 = hex 90 while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){} SPI_I2S_SendData(SPI1,0x00); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){} SPI_I2S_SendData(SPI1,0x00); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){} SPI_I2S_SendData(SPI1,0x00); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){} SPI_I2S_SendData(SPI1,0x00); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){} data1 = SPI_I2S_ReceiveData(SPI1); SPI_I2S_SendData(SPI1,0x00); //Chip select set high GPIO_SetBits(GPIOA, GPIO_Pin_4); } } /* SPI1-CONFIGURATION*/ void SPI_Configuration(void) { SPI_InitTypeDef SPI_InitStructure; /* SPI_MASTER configuration -------------------------------------------------*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //low SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 4 = 5Mhz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; //MSB SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI_COMMS, &SPI_InitStructure); /* Enable SPI_MASTER TXE interrupt */ SPI_I2S_ITConfig(SPI_COMMS, SPI_I2S_IT_TXE, ENABLE); /* Enable SPI_MASTER */ SPI_Cmd(SPI_COMMS, ENABLE); } /*NVIC-CONFIGURATION*/ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 0 bits for pre-emption priority, 4 bits for subpriority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Configure and enable SPI_MASTER interrupt --------------------------------*/ NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /*GPIO-CONFIGURATION*/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure SPI_MASTER pins: SCK, MISO and MOSI */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_COMMS_SCK | PIN_SPI_COMMS_MISO | PIN_SPI_COMMS_MOSI; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //alternate function pushpull GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2, 10, 50 GPIO_Init(PORT_SPI_COMMS, &GPIO_InitStructure); //port A /* Configure SPI_MASTER pin: NCS */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_COMMS_NCS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //out pushpull GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2, 10, 50 GPIO_Init(GPIOA, &GPIO_InitStructure); //port A } /*RCC-CONFIGURATION*/ void RCC_Configuration(void) { /* Enable GPIO clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_SPI1, ENABLE); } ========================================== I have also set the chip select as a normal gpio because i couldn't make it work in any other way. The chip select pin must be brought low during sending and reading from the memory. I guess the code i have right now is pretty messed up but but ive tried to send some bytes while reading but failed. At least i dont see anything being clocked out from the memory... Thanks again for your help! Appreciate it a lot!2011-05-17 05:31 AM
//find out manufacturer id and device id
SPI_I2S_SendData(SPI1,0x09); //10010000 = hex 90 Watch! - your comment is hex 90, but you send 0x09 !2011-05-17 05:31 AM
Hey,
Thanks for observing that, but its actually something i chose because it got sent in the wrong way otherwise? 0x90 got sent like 00001001 instead of 10010000. Maybe its not the correct way to handle this problem but for me it was a simple solution =). But something else is clearly wrong since i dont get any signals on the MISO.2011-05-17 05:31 AM
The function expects a uint16_t argument.
void SPI_I2S_SendData (SPI_TypeDef *SPIx, uint16_t Data)2011-05-17 05:31 AM
Ah! Didn't seem to help though but thanks! One step closer to solving the problem!
2011-05-17 05:31 AM
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; //MSB Are you sure 8 bit MSB wouldn't be more appropriate? What part are you using, I don't see it specified in the thread.