2009-04-13 07:34 PM
SPI Communication Issue
2011-05-17 04:09 AM
Hey guys,
I'm working on a project for school, and I'm trying to getting communication over the SPI to work right. I am trying to communicate with the LIS302 accelerometer in 4 pin SPI mode. I can read any register just fine. The problem is that I can't read more than one. It always does whatever read command I gave it first. For example in the first example, I read from Cntrl_Reg1, then try reading from Cntrl_Reg2, and it returns the data in Cntrl_Reg1. I can tell it to do a sequential read as well, and then everytime I send a byte on the SPI, I get each sequential register. So the problem is that the accelerometer ignores new commands. Anytime I reset, I can pick any register and read it, no problem, but once I read one, I can't read a different one. I appreciate any tips or ideas. Here is my initialization:Code:
<BR> <BR>/************************************** <BR> * Start Accel. Config <BR> **************************************/ <BR> <BR> /* Accel. CS */ <BR> <BR> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; <BR> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; <BR> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; <BR> GPIO_Init(GPIOB, &GPIO_InitStructure); <BR> <BR> <BR> /* Accel. MOSI */ <BR> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; <BR> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; <BR> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; <BR> GPIO_Init(GPIOB, &GPIO_InitStructure); <BR> <BR> /* Accel. MISO */ <BR> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; <BR> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; <BR> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; <BR> GPIO_Init(GPIOB, &GPIO_InitStructure); <BR> <BR> /* Accel. SCLK */ <BR> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; <BR> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; <BR> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; <BR> GPIO_Init(GPIOB, &GPIO_InitStructure); <BR> <BR> /* SPI initialization stuff <BR> * Note: Accelerometer is attached to SPI2. <BR> * SPI is using slow clock (36MHz [APB1]) <BR> */ <BR> /* SPI: Master <BR> * 8 bit data mode <BR> * Serial clock steady state high <BR> * data capture on second edge <BR> * NSS controlled in software <BR> * baud prescaler = 64 (SPI clock should be ~ 5.6MHz) <BR> * MSB = first bit <BR> */ <BR> <BR> <BR> SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; <BR> SPI_InitStructure.SPI_Mode = SPI_Mode_Master; <BR> SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; <BR> SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; <BR> SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; <BR> SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; <BR> SPI_InitStructure.SPI_BaudRatePrescaler = <BR> SPI_BaudRatePrescaler_128; <BR> SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; <BR> SPI_InitStructure.SPI_CRCPolynomial = 7; <BR> SPI_Init(SPI2, &SPI_InitStructure); <BR> <BR> // enable SPI2 <BR> SPI_Cmd(SPI2, ENABLE); <BR> <BR> <BR> /************************************** <BR> * End Accel. Config <BR> **************************************/ <BR>
Here is my code to test it. It is just a simple while loop to make sure I'm reading the right register.Code:
<BR> <BR> Address = 0xA0; <BR> SendByte(Address); <BR> while(1){ <BR> <BR> Address = 0xA0; <BR> ReceivedData = SendByte(Address); <BR> printf(''Cntrl_Reg1: %x nr'', ReceivedData); <BR> <BR> Address = 0xA1; <BR> ReceivedData = SendByte(Address); <BR> printf(''Cntrl_Reg2: %x nr'', ReceivedData); <BR> <BR> Address = 0xA2; <BR> ReceivedData = SendByte(Address); <BR> printf(''Cntrl_Reg3: %x nr'', ReceivedData); <BR> } <BR>
Then, here is my SendByte function.Code:
<BR>/******************************************************************************* <BR>* Function Name : SendByte <BR>* Description : Sends the input byte on the SPI, then returns a the byte <BR>* recieved from the SPI device. <BR>* Input : byte: The byte to be sent to the SPI device. <BR>* Output : None <BR>* Return : The byte returned by the SPI device. <BR>*******************************************************************************/ <BR>u8 SendByte( u8 byte ) <BR>{ <BR> u8 ReturnData; <BR> <BR> <BR> SPI_Cmd(SPI2, ENABLE); <BR> // set chip select low <BR> GPIO_WriteBit( GPIOB, GPIO_Pin_10, Bit_RESET ); <BR> <BR> <BR> /* Loop while DR register in not empty */ <BR> while( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_TXE ) == RESET ); <BR> <BR> /* Send byte through the SPI2 peripheral */ <BR> SPI_I2S_SendData( SPI2, byte ); <BR> <BR> /* Wait to receive a byte */ <BR> while( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_RXNE ) == RESET ); <BR> <BR> ReturnData = SPI_I2S_ReceiveData( SPI2 ); <BR> <BR> // set chip select high <BR> GPIO_WriteBit( GPIOB, GPIO_Pin_10, Bit_SET ); <BR> <BR> SPI_Cmd(SPI2, DISABLE); <BR> /* Return the byte read from the SPI bus */ <BR> return ReturnData; <BR> <BR> <BR>} <BR>
[ This message was edited by: atkranz on 10-04-2009 04:05 ]2011-05-17 04:09 AM
Hello atkranz,
I am not sure, but probably CS signal is not working properly.. Are you able to check it with oscilloscope ? In my project that worked with LIS302DL, I used following code to initialize ChipSelect pin:Code:
.... GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure);2011-05-17 04:09 AM
Thanks for the idea. I tried that once before, and it didn't work. I just tried it again, and I get ff out on the line no matter what I read.
I think you are probably right on the CS though, but the oscilloscopes we have suck, and I can't see anything. The accelerometer I am using is in fact the LIS302DL. Edit: Do I need to use the SPI_NSSInternalSoftwareConfig function to toggle the CS? What I'm asking is: is me manually trying to do it by setting or resetting the bit wrong? As you can see, the CS is hooked up to PB10, so I don't see how I could use SPI_NSS to do anything. So I think I need to manually do this. [ This message was edited by: atkranz on 10-04-2009 20:54 ]2011-05-17 04:09 AM
Doing it manually and having pin initialized as Out_PP GPIO should work. Works here ;)