ATTINY4313 SPI

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used to do this, but I think I've been infected by xMega and can't make it go in 4313 any more. Perhaps I should have been vaccinated. I even looked at old code.

 

I made the program to twiddle each of the pins independently and probed with the handy Diligent Analog Discovery II some freak sent me so I know the connections are there, but when I try to just shove out some SPI data, I get a square wave on SCK, but none on MOSI.

 

The horrible code:

#include <avr/io.h>

#define F_CPU 8000000UL  // 1 MHz
#include <util/delay.h>

#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define MISOddr     DDRB
#define MISOport    PORTB
#define MISOpin     6

#define MOSIddr     DDRB
#define MOSIport    PORTB
#define MOSIpin     5

#define SCKddr      DDRB
#define SCKport     PORTB
#define SCKpin      7

#define NRFCSddr    DDRB
#define NRFCSport   PORTB
#define NRFCSpin    0
#define NRFCSlow	NRFCSport &= ~(1<<NRFCSpin)
#define NRFCShigh	NRFCSport |= (1<<NRFCSpin)

#define NRFCEddr    DDRB
#define NRFCEport   PORTB
#define NRFCEpin    1
#define NRFCElow	NRFCEport &= ~(1<<NRFCEpin)
#define NRFCEhigh	NRFCEport |= (1<<NRFCEpin)

#define LEDddr      DDRD
#define LEDport     PORTD
#define LEDpin      0

#define LEDon LEDport &= ~(1<<LEDpin)
#define LEDoff LEDport |= (1<<LEDpin)

#define DECTddr     DDRD
#define DECTport    PORTD
#define DECTpin		PIND
#define DECTApin    3
#define DECTBpin    4

#define BUTTONddr   DDRD
#define BUTTONport  PORTD
#define BUTTONpin   1

// use OC0B to operate the 38KHz ir led
#define IRLEDport   PORTD
#define IRLEDpin    5

#define IRon TCCR0A = (1<<WGM00) | (1<<WGM01) | (1<<COM0B1)
#define IRoff TCCR0A = (1<<WGM00) | (1<<WGM01)

void Init(void)
{
	// set up ports
	DDRB = (1<<MOSIpin) | (1<<SCKpin) | (1<<NRFCSpin) | (1<<NRFCEpin) ;
	DDRD = (1<<LEDpin) | (1<<IRLEDpin) ;
	PORTD = 255 ; //(1<<BUTTONpin) | (1<<DECTApin) | (1<<DECTBpin) | (1<<LEDpin) | (1<<IRLEDpin) ; // turn on pullups, off LEDs
	PORTB = 255 ;
	// start 38KHz ir signal
	TCCR0A = (1<<WGM00) | (1<<WGM01) | (1<<COM0B1);
	TCCR0B = (1<<WGM02) | (1<<CS00) ;
	OCR0A = 200 ;
	OCR0B = 190 ;

	// start a millisecond interrupt

	TIMSK = (1<<TOIE0) ; // Interrupt on overflow of timer 0 (38khz)
	sei() ;

	USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USITC); // set up spi
}

uint8_t spi(uint8_t val)
{
	USIDR = val;
	USISR = (1<<USIOIF);
	do
	{
		USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);
		//USICR = (1<<USIWM0)|(1<<USICLK)|(1<<USITC);
	} while ((USISR & (1<<USIOIF)) == 0);
	return USIDR;
}

volatile uint8_t ic ;
volatile uint32_t ms ;

ISR(TIMER0_OVF_vect)
{
	ic += 1 ;
	if (ic==38)
	{
		ms += 1 ;
		ic = 0 ;
	}
}

int main(void)
{
	Init() ;
	while(1)
	{
		uint8_t s = spi(0x55) ;
	}

}

I know, by turning an led on when (ms%100) < 500 and off when it's not that the isr is working.

 

A loop like

MOSIddr = (1<<MOSIpin);
while(1)
{
    MOSIport = (1<<MOSIpin);
    MOSIport = 0 ;
}

fiddles the MOSI pin, so I know the pin is working.

 

I figure I'm misreading something in the datasheet for spi. Anybody see it?

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

Last Edited: Sun. May 26, 2019 - 09:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tom,

 

The tiny4313 and the tiny2313A have both got USART_MSPI which gives 100% perfect MSPI up to F_CPU/2

And they both have USI which gives pretty reasonable SPI Slave up to F_CPU/4

 

Note that USART_MSPI gives far better performance than Xmega SPI

Of course Xmega USART_MSPI is best of all.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The stupid thing works if I bitbang the spi.

 

I wonder if it's because I used debugwire to program this one 'stead of isp.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

Last Edited: Tue. May 28, 2019 - 12:25 PM