cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429 Stopping SPI

Eric Lin
Associate II
Posted on April 18, 2018 at 20:03

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

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on April 20, 2018 at 08:40

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

View solution in original post

6 REPLIES 6
Posted on April 19, 2018 at 01:43

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

Eric Lin
Associate II
Posted on April 19, 2018 at 23:02

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.

Posted on April 20, 2018 at 08:40

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

Eric Lin
Associate II
Posted on April 20, 2018 at 20:33

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

T J
Lead
Posted on April 21, 2018 at 03:17

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 ready

    while ((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;

}
Brian D
Associate III
Posted on April 21, 2018 at 08:07

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.