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?

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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