2018-04-18 11:03 AM
Hi, there
This might be a basic question, but I've been trying to solve it for a few days now. I hope there will be an SPI expert who is willing to help. My codes are as follows:
======================================================================= RESET_PIN(GPIOF, GPIO_PIN_6); // CS pulled low -- PF6 is my Chip Select PIN
item_count = 82; jmax = 400; // I need to read out 82*2 = 164 bytes per loop. Then I'll have to
// do some data processing on the data read, before reading
// the next 164 bytes, etc. The data width is 16-bit. jmax is
// simply a variable used for testing at this stage.
for(volatile int j=0; j<jmax; j++){ ii = 0; SPI1->CR1 |= SPI_CR1_SPE; // Enable SPI1 clock while(ii < item_count){if(SPI1->SR & SPI_SR_RXNE){
//if(ii == 81)SPI1->CR1 &= (~SPI_CR1_SPE); SPI_rx_tmp[ii] = SPI1->DR; ii++;if(ii==80){ // This is the second to last RXNE for(volatile int jj=0; jj<2;jj++); // Software delay of roughly 1.5 SPI clock cycle. SPI1->CR1 &= (~SPI_CR1_SPE); } // Disable SPI1 clock. The above 2 lines of codes take about 0.1 us to complete. // 0.1 us is about one clock cycle for a clock of 10MHz, which is what the SPI-1 // has been configured. According to the manual, DM00031020.pdf: Page 897/1745, // the SPI clock should be halted after one SPI clock cycle, following the second to // last occurrence of RXNE. } } First2Bytes_Arry[j] = SPI_rx_tmp[0];
if((First2Bytes&0x0FFF) == 0x0000){ // 0th frame
//Readout the entire frame.. //for(volatile int jj=0; jj<80;jj++)fb[jj]=SPI_rx[2+jj+j*82]; // Read the first line. //ReadOneFrame(&fb[80]); // The first line has just been read.//for(volatile int jj=0; jj<30;jj++);
} } SET_PIN(GPIOF, GPIO_PIN_6); // CS pulled high to disable the SPI reading.=================================================================
Unless I misunderstand what the reference manual says on section 28.3.8, what happened
was that if I disabled the SPI clock following the steps outlined on that page, then the
last RXNE=1 never came. On the other hand, if I disabled the SPI clock following the very
last RXNE=1, the SPI clock was not stopped correctly, meaning that more data was clocked
out after the SPI was stopped. I would miss these data.
I've also tried to use the HAL_SPI_Receive() and the SPI clock was not stopped correctly either.
I hope it makes sense. Thank you for your time.
Regards,
Eric
Solved! Go to Solution.
2018-04-20 01:40 AM
Sorry, but I in fact haven't gotten to it. I was trying to work with the accelerometer on the L4Disco board, just as a hobby, and gave up due to no time.
As in the receive-only mode (contrary to the bidirectional one) you don't need to turn direction of the single data line, you might perhaps use a normal two-line mode (RXONLY = 0), and simply not set any pin to MOSI. Then you could easily control the number of clocks by writing to the data register. Am I overlooking something?
JW
2018-04-18 04:43 PM
It's not quite clear from your post, but you are probably using the bidirectional mode, do you?
It's tricky to get the timing right. There is
https://community.st.com/0D50X00009XkaBgSAJ
in Cube. I personally would try to come up with some timer-and-DMA based solution, rather than relying on software.JW
2018-04-19 02:02 PM
Hi,
Waclawek.Jan
Thank you very much for pointing me to the earlier posts. I figured that I wouldn't be the only person who struggles with this.
I am using the 'Master Receiving Only' mode. (MSTR=1, BIDIMODE=0, RXONLY=1). I understand that I need to control the timing of setting SPE=0 very carefully, and currently it is not working perfectly. From time to time, SPI clock will misfire one or two cycles.
I agree that it is very tricky to get it done exactly right at every single read. So far, I am not there yet.
I'll be appreciated If you have a few lines of codes showing the timing control for SPI in the master receive mode.
2018-04-20 01:40 AM
Sorry, but I in fact haven't gotten to it. I was trying to work with the accelerometer on the L4Disco board, just as a hobby, and gave up due to no time.
As in the receive-only mode (contrary to the bidirectional one) you don't need to turn direction of the single data line, you might perhaps use a normal two-line mode (RXONLY = 0), and simply not set any pin to MOSI. Then you could easily control the number of clocks by writing to the data register. Am I overlooking something?
JW
2018-04-20 11:33 AM
Hi, JW
Someone else has actually made the same recommendation as you did. I'll give it a try.
I started to think that it is not the SPI clock issue. Even if I didn't stop the SPI clock, but continuously reading out the data, I still have issues on the data clocked out. It might be that the Camera is clocking out data imperfectly. I am not sure at the moment.
Thank you for your inputs. I will come back to post an update soon.
Regards,
Eric
2018-04-20 06:17 PM
if you could carefully read this code below, it works well.
unsigned char SPI_t::transfer_receive(unsigned short data) {
char RxSPI;
// Clear_SPI1_nSS_Out();
while (!(hspi1.Instance->SR & SPI_FLAG_TXE)) ; // make sure we are readywhile ((hspi1.Instance->SR & SPI_FLAG_RXNE))
RxSPI = hspi1.Instance->DR; // read / clear out / dump all the bytes left in the Rx register*((__IO uint8_t *)&hspi1.Instance->DR) = data; // force the SPI to transceive 8 bit
while (!(hspi1.Instance->SR & SPI_FLAG_TXE)) ; //wait for buffer to start shifting while ((hspi1.Instance->SR & SPI_FLAG_BSY)) ; // wait for all bits to completely leave the chip while ((hspi1.Instance->SR & SPI_FLAG_RXNE)) RxSPI = hspi1.Instance->DR; //read all the bytes left in the Rx register, the last one is for your reading.// Set_SPI1_nSS_Out();
return RxSPI;}2018-04-20 11:07 PM
Why not configure the spi as tx and rx, then repeat the dummy write (load DR register) 82 times as wished. After each data in DR shifted out, then just read the DR for the desired read data. This will generate the correct clk cycles.