Voting resources, early voting, and poll worker information - VOTE. ... Adafruit is open and shipping.
0

SPI stops working after first transfer
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

SPI stops working after first transfer

by uhe on Sun May 30, 2010 1:56 pm

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 | TOGGLE FULL SIZE
//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?
"I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm
Location: metric world

Re: SPI stops working after first transfer

by franklin97355 on Sun May 30, 2010 4:33 pm

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

franklin97355
 
Posts: 21567
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: SPI stops working after first transfer

by uhe on Sun May 30, 2010 5:58 pm

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 | TOGGLE FULL SIZE
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.
"I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm
Location: metric world

Re: SPI stops working after first transfer

by oPossum on Sun May 30, 2010 6:10 pm

Try this...

Code: Select all | TOGGLE FULL SIZE
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;
}
I am the Possum, and I approve of this message. Sent from MacBook Wheel Sorry for my bad German.
oPossum
 
Posts: 636
Joined: Fri Oct 26, 2007 12:42 am
Location: Michigan, USA

Re: SPI stops working after first transfer

by mojo on Mon May 31, 2010 6:43 am

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.

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

Re: SPI stops working after first transfer

by uhe on Mon May 31, 2010 4:20 pm

@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 :\
"I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm
Location: metric world

Re: SPI stops working after first transfer

by fat16lib on Mon May 31, 2010 5:26 pm

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.
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: SPI stops working after first transfer

by uhe on Tue Jun 01, 2010 11:28 am

HERO --> fat16lib <-- HERO :D

I added the following two lines and it just worked:
Code: Select all | TOGGLE FULL SIZE
#define SS  _BV(PB2)
DDRB |= SS;

Thx for parsing the datasheet fat16lib!
"I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm
Location: metric world

Re: SPI stops working after first transfer

by mojo on Fri Jun 04, 2010 5:49 pm

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.

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

Re: SPI stops working after first transfer

by uhe on Sat Jun 05, 2010 1:01 pm

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.
"I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm
Location: metric world

Re: SPI stops working after first transfer

by mojo on Sun Jun 06, 2010 12:18 pm

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.

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

Please be positive and constructive with your questions and comments.