AnsweredAssumed Answered

SPI data register alwas return 0xFF when execute couninously

Question asked by plante.raphael on Nov 26, 2016
Latest reply on Nov 28, 2016 by plante.raphael
Hi, I am trying to read the accelerometer with SPI. I need to do it without the libraries for school. I am able to read the info register from LIS3DSH when I run the code line by line. However when, I run it in contiuous and the break it, the value of the DR register is always 0xFF.



int main(void){
    
    System_Clock_Init();
    GPIO_INIT();
    SPI_INIT();    
    SysTick_Initialize(4000);
    // Enable Clock of GPIO Port D
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;                 
                                
    // Set Pin 13 I/O direction as Digital Output
    GPIOD->MODER &= ~(GPIO_MODER_MODER13);   // Clear mode
    GPIOD->MODER |= (GPIO_MODER_MODER13_0);  // Input(00, reset), Output(01), Alternate Func(10), Analog(11)

    // Set Pin 13 the push-pull mode for the output type
    GPIOD->OTYPER &= ~(GPIO_OTYPER_OT_13);   // Output Push-Pull(0, reset), Output Open-Drain(1)
                
    // Set I/O output speed value as high speed
    GPIOD->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR13); // Low speed (00), Medium speed (01), Fast speed(01), High speed (11)
        
    // Set I/O as no pull-up pull-down  
    GPIOD->PUPDR &= ~(GPIO_PUPDR_PUPDR13); // No PUPD(00, reset), Pull up(01), Pull down (10), Reserved (11)


    // SET CS TO HIGH
        GPIOE->ODR |= GPIO_ODR_ODR_3;
    
    
    // CONFIG OF CSLASDF    
    GPIOE->ODR ^= GPIO_ODR_ODR_3;
    while (!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = 0X20;
    
    while (!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = 0XC0;

    GPIOE->ODR ^= GPIO_ODR_ODR_3;
    // END CONFIG
    

    address=0x0F;
    buffer= address | READ;
    

    while(1)
    {
        SPI_Read();
    }
}


void SPI_Read ()
{
    while (!(SPI1->SR & SPI_SR_TXE)); // wait for transmitter empty

    GPIOE->ODR ^= GPIO_ODR_ODR_3;
    while (!(SPI1->SR & SPI_SR_TXE));
    
    SPI1->DR = buffer;
    while (!(SPI1->SR & SPI_SR_RXNE));    
    SPI1->DR;
    
    while (!(SPI1->SR & SPI_SR_TXE));    
    SPI1->DR = 0X00;
    while (!(SPI1->SR & SPI_SR_RXNE));    
    
    GPIOE->ODR ^= GPIO_ODR_ODR_3; // back to high during iddle
    xVal= SPI1->DR;
}


void GPIO_INIT()
{
    // acitvate clock for port A and E
        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOEEN;     
    
    // configure PA5 for SCL AF5
    GPIOA->MODER |= (GPIO_MODER_MODER5_1); // Alternate function
    GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_5);  // output pushpull
    GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR5_1);
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5); // no pull up no pull down
    GPIOA->AFR[0]|=5<<(4*5);

    
    // PA7 for MOSI AF5
    GPIOA->MODER |= (GPIO_MODER_MODER7_1); // Alternate function
    GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_7);  // output pushpull
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR7); // no pull up no pull down
    GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR7_1);
    GPIOA->AFR[0]|=5<<(4*7);
    // PA6 for MISO (CS)    
    GPIOA->MODER |= (GPIO_MODER_MODER6_1); // Alternate function
    GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_6);  // output pushpull
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR6); // no pull up no pull down
    GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6_1);
    GPIOA->AFR[0]|=5<<(4*6);
    // PE3 for CS
    GPIOE->MODER |= (GPIO_MODER_MODER3_0); // general output
    GPIOE->OTYPER &= ~(GPIO_OTYPER_OT_3);  // output pushpull
    GPIOE->PUPDR &= ~(GPIO_PUPDR_PUPDR3_0); // pull up
    GPIOE->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR3);
}


void SPI_INIT()
{
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // Enable the clock

    // CPOL=1 clk high during iddle
    // CPHA=1 capture value on second edge
    // DFF =1 Frame size = 16 bit
    // MSTR SPI as master
    // baud rate is 8 MHz
    SPI1->CR1 &= ~SPI_CR1_LSBFIRST; // MSB first
    SPI1->CR1 |= SPI_CR1_CPOL | SPI_CR1_CPHA  ; // fRAME SIZE = 16, clk high during iddle
    
    SPI1->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; //if software managed
    SPI1->CR1 |= SPI_CR1_SPE  | SPI_CR1_MSTR;
    
}

    

void SysTick_Handler(void){
    if (counter%500==0)
    {
    
        GPIOD->ODR ^= GPIO_ODR_ODR_13;
    }
    counter++;
}

void System_Clock_Init(void){
    // On active le High Speed Internal Clock ( HSI = 16 MHz )
RCC ->CR |= (( uint32_t ) RCC_CR_HSION );
// On attends que le HSI soit pr^et
while ( (RCC ->CR & ( uint32_t ) RCC_CR_HSIRDY ) == 0 ) {;}

    
    // f=fclk*N/m/p = 16*192/16/4=40 MHz
    //RCC->PLLCFGR &= 0XF0FF8000;
    //RCC->PLLCFGR |= RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLN_4 | RCC_PLLCFGR_PLLN_3; // N = 10
//    RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_1; // M= 2
    RCC->PLLCFGR |= RCC_PLLCFGR_PLLP_1; // P =2 (voir datasheet)
    
    RCC->CR |= RCC_CR_PLLON; // activate PLL
    while ( (RCC ->CR & ( uint32_t ) RCC_CR_PLLRDY ) == 0 ) {;}
    // On selectionne le PLL comme source de l ' horloge
RCC -> CFGR &= ( uint32_t )(( uint32_t )~( RCC_CFGR_SW )); // On met les bits du " System Clock Switch " a 0
RCC -> CFGR |= ( uint32_t ) RCC_CFGR_SW_1; // PLL comme signal d'horloge
// On attends que le PLL soit bien selectionne
while (( RCC -> CFGR & ( uint32_t ) RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL ) {;}

}



void SysTick_Initialize(int ticks){

    //Set status and control register
    SysTick->CTRL = 0;
    //Set reload value register
    SysTick->LOAD |= ticks-1;
    //Set interrupt priority
    NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS)-1);
    //Reset counter value
    SysTick->VAL=0;
    //Select processor clock
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Pos;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Pos;
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Pos;
}


Attachments

Outcomes