SPI: wait

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

Hello,

I'm porting one of my app to TFT dispaly, using display3000 boards. I'm using Codevision, for which the code has been ported. I have an issue I'm stuck on, which I tracked down-to the SPI transfer done state:

void LCD_Wait(void){	//waits for SPI transfer is done
    printf("..LCD wait..");
    while (SPCR & _BV(SPE)) {
        while (!(SPSR & (_BV(SPIF))));
        SPCR &= ~(_BV(SPE));
    }
    //while(!((SPSR) & (1<<SPIF)));
    printf("..LCD wait done..");
}

This is called in the LCD_Init, from the LCD_SPI_DBCommand:

printf("..Inside init..set SPI...");
    DDRB = 0x76;        // Set all pins used by this lib to output
    
    SPSR        |= _BV(SPI2X);
	SPCR        = _BV(SPE) | _BV(MSTR);// | _BV(CPOL) | _BV(CPHA); 
    printf("done..");

	delay_ms(300);
        printf("reset LCD...");
 
	RESET(LCD_RESET);	delay_ms(75);
	SET(LCD_SELECT);	delay_ms(75);
	RESET(LCD_CLK);		delay_ms(75); 
	SET(LCD_DC);		delay_ms(75); 
	SET(LCD_RESET);		delay_ms(75); 
	        printf("done..send command1..");

	LCD_SPI_DBCommand(&init_data[0], 2);	
    delay_ms(75);
    	        printf("done...send command2..");
 
	LCD_SPI_DBCommand(&init_data[2], 10);	
    delay_ms(75); 
    	        printf("done...send command3..");

	LCD_SPI_DBCommand(&init_data[12], 23);  
    	        printf("..done...");
// send word (16 bit) (or array with words) by SPI 
void LCD_SPI_DBCommand(unsigned int data[], unsigned int count)
{
    int i;
    unsigned char msbyte;
    unsigned char lsbyte;
    
	for (i=0; i> 8) & 0xff;		// msb!
		lsbyte = data[i] & 0xff;			// lsb!	
		SPCR |= _BV(SPE); 					    //SPI: Ready 
        printf("send 8 first byte..");
		SPDR = msbyte;						//send first 8 bits
		LCD_Wait();							//Wait until all bits has been sent
		SPCR |= _BV(SPE);
		SPDR = lsbyte;						//send last 8 bits
        printf("send 8 last byte..");
		LCD_Wait();
		RESET(LCD_DC);						// Selects Data mode
		SET(LCD_SELECT);					// Disable display
	}
}

With this I get on the serial the following output:

INIT LCD....
..Inside init..set SPI...done..reset LCD...done..send command1..send 8 first byte....LCD wait....LCD wait done..send 8 last byte....LCD wait..

I also tried with some wait code from avrlib, but no chance:

while(!((SPSR) & (1<<SPIF)));

So the first wait is succesfull for ms byte...

The board has a 2561 on it and a 14,745600 crystal.

Anything I have missed ?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 SPCR &= ~(_BV(SPE)); 

?? Why are you turning the SPI on and off all the time?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Well, I don't see any reason. I'll ask the guy who made the code. If I remove this, then the avrlib is equal to the provided code which didn't solve the issue. But I agree it is much cleaner ! I'll take care of that. Thanks for your quick feedback on this.

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

the only thing you have to do is put the byte in SPDR and wait for SPIF to get set in the SPCR register.

when SPIF is set also a byte is received that can be fetched from SPDR when wanted.

setting up the SPI peripheral normally you only do once and then only shift the bytes. except when you want to go to power down mode. but then you power up using the init, send the stuff you want to send and power down when the last byte is send....

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

Why not just use CV's spi() primitive? It waits before it returns.

A reason not to use the provided primitive might be to interleave (e.g., get next byte into a register; check for end) during the wait, but then you can "lift" the spi() code as a base.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.