I've been tearing out my hair for a while on this. I'm just trying to do a basic SPI transaction — sending one byte — on the ATtiny441 but I'm getting nothing on the SCK and MOSI lines. First, here are my fuse settings and pinout (in red):
Probably the most useful information here is that I'm using the 8MHz internal oscillator, and not dividing by 8. Note that I'm remapping the SPI pins so that I can leave my logic analyzer on while programming with the default pins.
Here's my main.c
file:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#define SCK 3
#define MOSI 1
#define CSN 2
uint8_t data = 0;
uint8_t reg = 0;
int main(void)
{
PRR = 0; // turn off power reduction
REMAP |= (1<<SPIMAP); // remap SPI pins
// set SCK, MOSI, CSN as outputs:
DDRA = (1<<SCK) | (1<<MOSI) | (1<<CSN);
// enable SPI, set as master, use f_clkIO/16 (500kHz):
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
reg = SPSR;
reg = SPDR;
while(1)
{
PORTA &= ~(1 << CSN); // clear CSN
SPDR = data++; // send byte
while( !(SPSR & (1<<SPIF)) ); // wait for flag to set
PORTA |= (1 << CSN); // set CSN
_delay_ms(10);
}
return 0;
}
I'm reading the SPSR
and SPDR
registers before the while
loop at the recommendation of Atmel's AVR151 app note (page 11).
When I run the code the CSN
line stays low, along with SCK
and MOSI
, suggesting that it's getting stuck in the while( !(SPSR & (1<<SPIF)) );
section waiting for the SPIF
to set. When I comment out this line, the CSN
line goes low for ~25us then back high, which is expected. I tried manually setting the outputs high on SCK
and MOSI
, too, to make sure it's not a pin connection problem and they worked fine.
Question: Does anyone see the error in my ways? I feel like there's one small, stupid error somewhere.
Edit: I also want to mention that I tried it with and without the clock divider (by 8) fuse bit set, and with and without remapping the SPI pins from the default location (i.e. programming, removing programming leads, attaching logic probe leads).
Best Answer
Eureka! Turns out the
SPIMAP
bit is incorrectly mapped!(It should be bit 1.) Therefore, the line remapping the SPI pins was failing! This is corrected by placing a
#define SPIMAP 1
in the#define
section.EDIT: As Martin pointed out, I am indeed using an old version of avr-libc. I was using the latest version of CrossPack, which is dated back almost 4 years from today. The newest version has this bug fixed.