USI

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

Hi,

I'm trying to implement SPI with USI in attiny26 but no success...

I adapted the code from Atmel's application note 319 and now it's like this:

#ifdef __AVR_ATtiny26__

	#define USI_PORT		PORTB

	#define USI_PIN			PINB

	#define USI_DDR			DDRB

	
	#define USI_SCK			PINB2	//!< USI clock I/O pin.

	#define USI_MISO		PINB1	//!< USI data input pin.

	#define USI_MOSI		PINB0	//!< USI data output pin.
	
	#define TC1_PRESCALER_VALUE 256	//!< Must be 1, 8, 64, 256 or 1024.
	#define TC1_COMPARE_VALUE   5	//!< Must be 0 to 255. Minimum 31 with prescaler CLK/1.


	/*  Prescaler value converted to bit settings.
	 */
	#if TC1_PRESCALER_VALUE == 1
		#define TC1_PS_SETTING (1<<CS00)
	#elif TC1_PRESCALER_VALUE == 8
		#define TC1_PS_SETTING (1<<CS01)
	#elif TC1_PRESCALER_VALUE == 64
		#define TC1_PS_SETTING (1<<CS01)|(1<<CS00)
	#elif TC1_PRESCALER_VALUE == 256
		#define TC1_PS_SETTING (1<<CS02)
	#elif TC1_PRESCALER_VALUE == 1024
		#define TC1_PS_SETTING (1<<CS02)|(1<<CS00)
	#else
		#error Invalid T/C1 prescaler setting.
	#endif

#endif

#define bool char

#define false 	0
#define true  	!false

void SPI_init( char spi_mode);

bool SPI_trade( unsigned char byte);

ISR(TIMER1_CMPB_vect)
{
        TCCR1B = 0;
	USICR |= (1<<USITC);

	DDRA |= 0xff;

	PORTA = USISR;		//check status register

	_delay_ms(500);

        TCCR1B = (1<<CTC1) | (1<<PSR1) | TC1_PS_SETTING;
}
ISR(USI_OVF_vect)
{
	// Master must now disable the compare match interrupt
	// to prevent more USI counter clocks.
	if( spiX_status.masterMode == 1 ) {
		TIMSK &= ~(1<<OCIE1B);
	}
	
	// Update flags and clear USI counter
	USISR = (1<<USIOIF);
	spiX_status.transferComplete = 1;

	// Copy USIDR to buffer to prevent overwrite on next transfer.
	storedUSIDR = USIDR;

	DDRB |= _BV(6);
	PORTB |= _BV(6);
}

void SPI_init( char spi_mode)
{
	USI_DDR |= (1<<USI_MOSI) | (1<<USI_SCK); // Outputs.
	USI_DDR &= ~(1<<USI_MISO);                      // Inputs.
	USI_PORT |= (1<<USI_MISO);                       // Pull-ups.
	
	// Configure USI to 3-wire master mode with overflow interrupt.
	USICR = (1<<USIOIE) | (1<<USIWM0) |
	        (1<<USICS1) | (spi_mode<<USICS0) |
	        (1<<USICLK);

	USISR  =  (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x0<<USICNT0);

	// Enable 'Clear Timer on Compare match' and init prescaler.
	TCCR1B = (1<<CTC1) | (1<<PSR1) | TC1_PS_SETTING;

	// Init Output Compare Register.
	OCR1C = TC1_COMPARE_VALUE;
	OCR1B = TC1_COMPARE_VALUE;
	

	// Init driver status register.
	spiX_status.masterMode       = 1;
	spiX_status.transferComplete = 0;
	spiX_status.writeCollision   = 0;
	
	storedUSIDR = 0;
}

bool SPI_trade( unsigned char byte)
{
	// Check if transmission in progress,
	// i.e. USI counter unequal to zero.

	if( (USISR & 0x0F) != 0 ) {
		// Indicate write collision and return.
		spiX_status.writeCollision = 1;
		return false;
	}
	
	// Reinit flags.
	spiX_status.transferComplete = 0;
	spiX_status.writeCollision = 0;

	// Put data in USI data register.
	USIDR = byte;
	
	// Master should now enable compare match interrupts.
	if( spiX_status.masterMode == 1 ) {
		TIFR |= (1<<OCF1B);   // Clear compare match flag.
		TIMSK |= (1<<OCIE1B);			//interrupção do timer
	}
	return true;
}
/**** main: *****/

int main( void)
{
	SPI_init(0);		//modo 0

	sei();

	SPI_trade(0x55);

	asm("loop: rjmp loop"::);
}

I forwarded USISR to PORTA and strangely the flags keep changing from 1-0 0-1 :S
And the MOSI line is always zero...

Would appreciate any help.

Thanks

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

If anyone can help..I have the same problem...

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

Nobody? :(

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

You have the input and output pins mixed.

Quote:

#define USI_MISO PINB1 //!< USI data input pin.

#define USI_MOSI PINB0 //!< USI data output pin.

PB0 is the input (DI), and PB1 is the output (DO).

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

Thanks for response.

I checked the datasheet and it's ok. PB0 is MOSI and PB1 is MISO. And I'm using attiny26 as master so MISO as input and MOSI as output.

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

The USI module uses pins labeled DI and DO. MOSI and MISO are for ISP programming. Check the chapter on USI, the block diagram on the first page says that PB1 is the output and PB0 the input.

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

... ups... lol

Thank you very much :) It works now :P Attiny26 communicates with atmega8, now I can try to make them communicate with the rf12 transceiver!

Thanks again