Connect with us

SPI freezes

Discussion in 'Microcontrollers, Programming and IoT' started by thebignoob, Aug 18, 2014.

Scroll to continue with content
  1. thebignoob

    thebignoob

    1
    0
    Aug 18, 2014
    Hello,
    I have an issue with spi that freezes. I'm using atmega88 with nrf24l01 but when i try to test spi communication i get stuck.
    I initialize spi based on atmel specifications:
    Code:
    DDRB |= (1<<DDB5) | (1<<DDB3) | (1<<DDB2) |(1<<DDB1);
    SPCR |= (1<<SPE)|(1<<MSTR);
    And when I try to test out writing to spi (and print out to terminal ) i get stuck looping... ( i have usart initialized and used without any problems)
    Code:
    char spi_rw(unsigned char x)
    {
        SPDR = x;   
        //get stuck in this while loop
        while(!(SPSR & (1<<SPIF)));
        //printing to terminal after get's out of loop but never go out   
        return SPDR;
    }
    I'm trying to read STATUS register:
    Code:
    uint8_t get_reg(uint8_t reg)
    {   
    
        _delay_us(10);
        CLEARBIT(PORTB, 2);    //CSN low so nrf start listen for command
        _delay_us(10);
        spi_rw(R_REGISTER + reg);   
        _delay_us(10);
        reg = spi_rw(NOP);
        _delay_us(10);
        SETBIT(PORTB, 2);    //CSN IR_High nrf do nothing now
        return reg;   
    }
    I try calling get_reg(STATUS) and passing it to usart to print out resultand I get nowhere since code stuck in while loop.

    P.S. i use this simple functions to set and clear bits
    Code:
    #define BIT(x) (1<<(x))
    #define SETBITS(x,y) ((x)|=(y)))
    #define CLEARBITS(x,y) ((x) &=(~(y)))
    #define SETBIT(x,y) SETBITS((x), (BIT((y))))
    #define CLEARBIT(x,y) CLEARBITS((x), (BIT((Y))))
    Thanks in advance, any help would be greatly appreciated.
     
  2. OLIVE2222

    OLIVE2222

    690
    25
    Oct 2, 2011
    No idea about you code, I don't have C programming skills. However google a bit for "nrf24l01 avr studio" working codes will pop's up.
    Also if it's your first SPI code get a free sample of a SPI DAC or digital potentiometer so you can "debug with a multimeter" !
     
  3. Harald Kapp

    Harald Kapp Moderator Moderator

    9,906
    2,098
    Nov 17, 2011
    You mean this loop?
    while(!(SPSR & (1<<SPIF)));​

    Your error lies with the NOT operation:
    SPSR & (1 <<SPIF) will mask all other bits except SPIF. The result is:
    SPIF=0: SPSR & (1<<SPIF) = 0x00 /* stay in the loop as serial transfer is not complete (SPIF == 0) */
    SPIF=1: SPSR & (1<<SPIF) = 0x80 /* exit the loop here as serial transfer is completed (SPIF == 1) */
    Negating this results in:
    SPIF=0: !(SPSR & (1<<SPIF)) = 0xFF
    SPIF=1: !(SPSR & (1<<SPIF)) = 0x7F
    Both expressions are <> 0 and therefore the loop will not exit.

    Use instead:
    while((SPSR | (1<<SPIF)) == 0x00);​
     
  4. Harald Kapp

    Harald Kapp Moderator Moderator

    9,906
    2,098
    Nov 17, 2011
    Sorry, I mixed up "!" and "~" .
    This part looks actually correct.

    My C is a bit rusty. Are you sure that using "SPSR actually reads the contents of the status register? If SPSR is defined as the address of the status register (i.e. 0x..), then using SPSR this way may operate on the address, not on the register contents. Depending on the version of AVR-GCC/AVR-LIBC or any other compiler you may use it may be required to use an inp() statement like inp/SPSR) to actually access the register's contents.

    It may also help to define SPSR as "volatile". This tells the compiler that the contents of this register may change at runtime and prevents over-optimization (without volatile the compiler does not foresee potential future changes in SPSR and may "optimize" the code to the level of uselessness).
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-