SPI read problem
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-22 9:47 PM
Hello
I want to set some parameters on W5100 chip and then read them. the parameters sets right, but when I want to read a register what I receive from SPI is value of past register address I've sent. My micro is STM32F103 and I use KEIL here is my codes, I use these functions too write and read SPI:void W5100_write(u16 addr, u8 data)
{
//SPI_NSSInternalSoftwareConfig(SPI1, RESET); // enable the W5100 chip
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, W5100_WRITE_OPCODE); // need to write a byte
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, (addr & 0xff00) >> 8); // send MSB of addr
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, (addr & 0xff)); // send LSB
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, data); // send the data
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
//SPI_NSSInternalSoftwareConfig(SPI1, SET); // disable the W5100 chip // done with the chip
while( SPI1->SR & SPI_I2S_FLAG_BSY );
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
u8 W5100_read(u16 addr)
{
u8 data;
//SPI_NSSInternalSoftwareConfig(SPI1, RESET); // enable the W5100 chip
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, W5100_READ_OPCODE); // need to write a byte
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, (addr & 0xff00) >> 8); // send MSB of addr
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, (addr & 0xff)); // send LSB
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, (0x00)); // send Dummy byte
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
data = SPI_I2S_ReceiveData(SPI1); // done with the chip
while( SPI1->SR & SPI_I2S_FLAG_BSY );
GPIO_SetBits(GPIOA, GPIO_Pin_4);
return data;
}
here I write then read and send to pc by usart:
W5100_write(W5100_GAR + 0, pcfg->gtw_addr[0]); // set up the gateway address
W5100_write(W5100_GAR + 1, pcfg->gtw_addr[1]);
W5100_write(W5100_GAR + 2, pcfg->gtw_addr[2]);
W5100_write(W5100_GAR + 3, pcfg->gtw_addr[3]);
delay_ms(1);
while( !(USART1->SR & 0x00000040));
USART_SendData(USART1, W5100_read(W5100_SIPR + 0));
while( !(USART1->SR & 0x00000040));
USART_SendData(USART1, W5100_read(W5100_SIPR + 1));
while( !(USART1->SR & 0x00000040));
USART_SendData(USART1, W5100_read(W5100_SIPR + 2));
while( !(USART1->SR & 0x00000040));
USART_SendData(USART1, W5100_read(W5100_SIPR + 3));
I can't understand whats the problem,
thank you.
#spi #w5100 #stm32f103 #spi
- Labels:
-
SPI
-
STM32F1 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-23 2:33 PM
SPI is inherently bi-directional. After every transmit the SPI also clocks in a data byte, which you have to clear with a dummy read. Chances are you are overrunning the SPI RX buffer.
Jack Peacock- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-23 3:55 PM
Jack makes a very valid point - but I disagree w/his conclusion. You state that you ''read'' the address of the most recently sent data. Suspect that what you'd prefer is the ''data'' contained in that target location - not the address.
Edit - upon a 2nd read of your post - I find the description of your read to be imprecise. (i.e. could mean that you recover the address of past write - or the ''data'' of past write. And - if it is the ''data'' - then Jack's comment is spot on. And - if that's the case - my sense is that you'd have to, ''readdress'' the slave to recover the data @ that specific address. (also - many such devices enable a sequential ''dump'' of such data - after you specify some starting register and/or address) Might the command for, ''data read'' differ from that for, ''address read?'' If so - isn't it likely that you are not sending the proper command to recover data? As you must first, ''clock in'' the data - simultaneous reads seem not to the the issue. You may have to first specify the target data's address - and then issue a HW or SW (or both) toggle to recover the desired data. Suggest a deeper read of the slave SPI device data manual is in order - and then you must align your MCU code to comply with the slave's specification.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-24 1:04 AM
Hi,
Can you provide us the how SPI is configured?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 5:56 AM
thank you for your response, I have done it by a DUMMY read.
in datasheet said that after sending address, the value of that comes on SPI, and I send a 0x00 byte too read the Value, but its value of previous address I sent in previous session!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 6:51 AM
thank you a lot for you'r attention
that's what exacly happening: I write on 4 addresses, and then I want too read them to make sure that I'm doing right. I read 4 addresses with read function, but at every SPI session, my received data is value of previous session address!In data sheet said do what I'm doing with my read and write functions! here is the SPI signallimg diagram in datasheet:- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 6:55 AM
here it is, Thank you:
void config_SPI1()
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PA5, PA7 in AF pushpool mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
/* Initialize GPIOA */
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
/* Initialize GPIOA */
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/* Initialize GPIOA */
GPIO_Init(GPIOA, &GPIO_InitStructure);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
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_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
/* Initialize SPI1 */
SPI_Init(SPI1, &SPI_InitStructure);
/* enable SPI1 */
SPI_Cmd(SPI1, ENABLE);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 10:30 AM
Hi Beh,
Can you give us the value of status register ''SPI_SR'' when you exitW5100_read()
?I am suspecting an overrun condition...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 11:02 AM
it is 0x43!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-12-25 11:17 AM
Hi Beh,
As you are using SPI in Full Duplex you must read data every times you write in data register (even if you do not need it). The writing sequence should be something like the code below: /*!< Wait until the transmit buffer is empty */ while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); /*!< Send the byte */ SPI_I2S_SendData(SPIx, Data); /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); readata = (uint8_t)SPI_I2S_ReceiveData(SD_SPI);Consequently, you code will be:void W5100_write(u16 addr, u8 data){ u8 dummy; //SPI_NSSInternalSoftwareConfig(SPI1, RESET); // enable the W5100 chip GPIO_ResetBits(GPIOA, GPIO_Pin_4); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, W5100_WRITE_OPCODE); // need to write a byte /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, (addr & 0xff00) >> 8); // send MSB of addr /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, (addr & 0xff)); // send LSB while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); SPI_I2S_SendData(SPI1, data); // send the data while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); //SPI_NSSInternalSoftwareConfig(SPI1, SET); // disable the W5100 chip // done with the chip while( SPI1->SR & SPI_I2S_FLAG_BSY ); GPIO_SetBits(GPIOA, GPIO_Pin_4);} u8 W5100_read(u16 addr){ u8 data; //SPI_NSSInternalSoftwareConfig(SPI1, RESET); // enable the W5100 chip GPIO_ResetBits(GPIOA, GPIO_Pin_4); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, W5100_READ_OPCODE); // need to write a byte while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); SPI_I2S_SendData(SPI1, (addr & 0xff00) >> 8); // send MSB of addr while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, (addr & 0xff)); // send LSB /*!< Wait to receive a byte*/ while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ dummy = (uint8_t)SPI_I2S_ReceiveData(SD_SPI); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, (0x00)); // send Dummy byte while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); data = SPI_I2S_ReceiveData(SPI1); // done with the chip while( SPI1->SR & SPI_I2S_FLAG_BSY ); GPIO_SetBits(GPIOA, GPIO_Pin_4); return data;}