SPI stops working after first transfer

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

SPI stops working after first transfer

Post by uhe »

Hi,

I'm trying to connect a ATmega 168 with an MAX6979 (16x LED driver) via SPI.
So far it works but after the first transfer the ATmega stops and doesn't do anything. Here is the code I'm using:

Code: Select all

//F_CPU 8 Mhz 
#ifndef F_CPU
#define F_CPU 8000000
#endif  
 
#include <avr/io.h>
#include <util/delay.h>	

#define ERR_LED_1   _BV(PC3)
#define MAX_LE      _BV(PD6)    //

#define SCK         _BV(PB5)
#define MISO        _BV(PB4)
#define MOSI        _BV(PB3)

uint8_t spiSend(uint8_t data);

int main(void) {

  // IO Pins
  DDRC |= ERR_LED_1;   
  PORTC &= ~ERR_LED_1;  // error led - off
  
  DDRD |= MAX_LE;  
  PORTD |= MAX_LE;
  
  // SPI init
  DDRB |= MOSI | SCK ;
  PORTB &= ~(SCK | MOSI | MISO);
  
  // SPI Master enable, fosc = fclk/2
  SPCR = (1<<SPE) | (1<<MSTR);
  SPSR = (1<<SPI2X);
  
  while(1) {
    PORTC ^= ERR_LED_1;  // toggle error led - on
    
    _delay_ms(800);
    spiSend(0xaa);
    
    PORTC ^= ERR_LED_1;  // toggle error led - off
    
    _delay_ms(800);
    spiSend(0x55);  
  }
  return 0;
}

uint8_t spiSend(uint8_t data) {
  PORTD |= MAX_LE;    // latch enable
  SPDR = data;      
  while(!(SPSR & (1<<SPIF)));       // wait for end of transfer    
  PORTD &= ~MAX_LE;    // latch disable
  return SPDR;
}
What happens is after releasing the reset button, the ERR_LED_1 just light up once as commented in the code.
I also tried this with an arduino before which shows the same behavior.
What am I missing?

User avatar
Franklin97355
 
Posts: 24171
Joined: Mon Apr 21, 2008 2:33 pm

Re: SPI stops working after first transfer

Post by Franklin97355 »

Are you sure you are getting an 'end of transfer' ? that would lock things up.

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: SPI stops working after first transfer

Post by uhe »

franklin97355 wrote:Are you sure you are getting an 'end of transfer' ?
Hmmm, I'm not sure what you mean with 'End of transfer', but I think the answer is no. AFAIR it gets stuck on this line:

Code: Select all

while(!(SPSR & (1<<SPIF)));       // wait for end of transfer
But I have no clue why.
I tried to explicitly read SPSR followed by a read of SPDR as described on page 170 of the datasheet: Bit 7 – SPIF: SPI Interrupt Flag, but it doesn't change anything.

User avatar
opossum
 
Posts: 636
Joined: Fri Oct 26, 2007 12:42 am

Re: SPI stops working after first transfer

Post by opossum »

Try this...

Code: Select all

uint8_t spiSend(uint16_t data);

int main(void) {

  // IO Pins
  DDRC |= ERR_LED_1;   
  PORTC &= ~ERR_LED_1;  // error led - off
  
  DDRD |= MAX_LE;  
  PORTD |= MAX_LE;
  
  // SPI init
  DDRB |= MOSI | SCK ;
  PORTB &= ~(SCK | MOSI | MISO);
  
  // SPI Master enable, fosc = fclk/16
  SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);

 while(1) {
    PORTC ^= ERR_LED_1;  // toggle error led - on
    
    _delay_ms(800);
    spiSend(0xaa);
    
    PORTC ^= ERR_LED_1;  // toggle error led - off
    
    _delay_ms(800);
    spiSend(0x55);  
  }
  return 0;
}

uint8_t spiSend(uint16_t data) {
  SPDR = (data >> 8);                   // Send bits 15 to 8
  while(!(SPSR & (1<<SPIF)));       // wait for end of transfer    
  SPDR = (data & 0xFF);               // Send bits 7 to 0
  while(!(SPSR & (1<<SPIF)));       // wait for end of transfer    
  PORTD |= MAX_LE;                   // latch high
  PORTD &= ~MAX_LE;                // latch low
  return SPDR;
}

User avatar
mojo
 
Posts: 136
Joined: Mon Jan 21, 2008 5:04 pm

Re: SPI stops working after first transfer

Post by mojo »

Take a look at my code in the downloads here:

http://denki.world3.net/pad_converters.html

The SPI code is in psx.asm. If you are having trouble it is often down to not resetting the bit counter. Also make sure you are not accidentally resetting things like the port control bits. The datasheet and tutorials I have seen are not that clear and I had some trouble getting it to work at first.

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: SPI stops working after first transfer

Post by uhe »

@oPossum
I tried but it doesn't work either. Btw. thx for pointing out (indirectly) that i don't need to open the latch for the whole transfer :)

@mojo
I don't know anything about AVR asm. I had learned some ARM asm but that was years ago. I avoid asm because of it's maintainability (in comparison to C).
Can you tell me where the bitcounter resides? Can i check/reset it?
Btw. i get a 404 for the downloads on your Retro Adapter site.

I also tried using an IRQ ISR(SPI_STC_vect) to solve this... same behavior, it stops after the first byte :\

User avatar
fat16lib
 
Posts: 595
Joined: Wed Dec 24, 2008 1:54 pm

Re: SPI stops working after first transfer

Post by fat16lib »

The problem may be due to SS, PB2 on the ATmega 168, not being in output mode or held high in input mode.

See section 18.3 of the datasheet:
When the SPI is configured as a Master (MSTR in SPCR is set), the user can determine the direction of the SS pin.

If SS is configured as an output, the pin is a general output pin which does not affect the SPI system. Typically, the pin will be driving the SS pin of the SPI Slave.

If SS is configured as an input, it must be held high to ensure Master SPI operation.

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: SPI stops working after first transfer

Post by uhe »

HERO --> fat16lib <-- HERO :D

I added the following two lines and it just worked:

Code: Select all

#define SS  _BV(PB2)
DDRB |= SS;
Thx for parsing the datasheet fat16lib!

User avatar
mojo
 
Posts: 136
Joined: Mon Jan 21, 2008 5:04 pm

Re: SPI stops working after first transfer

Post by mojo »

uhe wrote:@mojo
I don't know anything about AVR asm. I had learned some ARM asm but that was years ago. I avoid asm because of it's maintainability (in comparison to C).
Can you tell me where the bitcounter resides? Can i check/reset it?
Btw. i get a 404 for the downloads on your Retro Adapter site.
Thanks for the heads up, I will sort that out.

It is worth learning to at least understand some assembler because eventually you will come across it if you do embedded development. Some of us actually prefer it :-) Anyway, I find that often the best thing to do in these situations is to go to the register description page in the datasheet and just work through all the registers checking every bit. My guess would be that maybe you have the number of bits per word set incorrectly or something like that. Unfortunately the USART interface is different for the various families of AVRs so a lot of the tutorial and example material on the web probably does not apply to your one.

If you have a Tiny2313 then it might be worth trying to get the SPI interface working with that first. The 2313 has a much simpler interface and needs only three registers setting to work.

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: SPI stops working after first transfer

Post by uhe »

mojo wrote:Unfortunately the USART interface is different for the various families of AVRs so a lot of the tutorial and example material on the web probably does not apply to your one.
IMO it's a little bit annoying that Atmel doesn't mention the SS pin functionality in master or slave example they give. A single commet like:
// don't forget to handle the SS functionality!
would have been enough.
mojo wrote:If you have a Tiny2313 then it might be worth trying to get the SPI interface working with that first. The 2313 has a much simpler interface and needs only three registers setting to work.
I started with the 2313 and I compared working code but since it has no SS pin I didn't see what was wrong / that something was missing.

User avatar
mojo
 
Posts: 136
Joined: Mon Jan 21, 2008 5:04 pm

Re: SPI stops working after first transfer

Post by mojo »

Ah yes, Atmel do seem to have a habit of using copy-pasta when doing their datasheets. Of course there would be nothing wrong with that if they bothered to check the text afterwards.

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”