Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

SPI Interface freezeup on Mega32

2006-03-25 by Robert Ussery

Hi, all...
I'm having some trouble with an SPI interface on the Mega32, which I'm 
using to communicate with a TI TLV2543 ADC. I'm programming the micro in 
C using avr-gcc.

Here's my problem... using the SPI transmit code more or less straight 
from the Mega32 datasheet:
	SPDR = (channel<<4)|(ADCSetup);
	while(!(SPSR & (1<<SPIF)));
my code keeps getting stuck in an infinite loop at that while() 
statement, but only on the 30th iteration or so (the micro loops through 
the ADC code indefinitely). The first 29ish times through the code, 
everything works perfectly. Am I missing something with how to handle 
the SPIF flag? I RTFM'd and all that, and it says that SPIF is set and 
reset automatically based on the SPI state and when SPDR is read.

I've included all of my code at the end of this email, but here are some 
of the more relevant parts:
SPI setup:
	// Set MOSI and SCK output, all others input
	DDRB = (1<<PB5)|(1<<PB7);
	// Enable SPI, Master, set clock rate fck/128
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);

The ADC code is contained in the function ADCRead(), as shown in the 
code below.

Am I making some classic n00b mistake here? Any advice or pointers are 
welcome.

Thanks!

- Robert









/***************************************************************************
  * main.c
  * Fuel Cell Demonstrator Aircraft Data Acquisition System Controller
  * ------------------------------------------------------------------------
  * Main controller code for FCDA DAQ system.
  * Author: Robert Ussery <robert.ussery@gatech.edu>
  * Copyright 2006
  * Revised 03-06-2006
 
***************************************************************************/


  #include <inttypes.h>
  #include <stdlib.h>
  #include <avr/io.h>
  #include <avr/interrupt.h>


/***************************************************************************
  * 
--------------------------------Constants--------------------------------
 
***************************************************************************/
  #define 	clock		8000000	//Clock speed in Hertz
  #define	baud		51		//RS232 Baud definition for 9600bps and 8Mhz

  #define	ADCSetup	0b0100	//Selects 16bit, MSB first, unipolar
								//operation for the ADC



/***************************************************************************
  * --------------------------Pin/Port 
Definitions---------------------------
 
***************************************************************************/
  // When making any changes to these, also make sure to change 
directions in
  // the initialize() function.

  //EEPROM Pins
  #define	EEPWP		PB0		//EEPROM Write Protect

  #define	EEPPort		PORTB	//EEPROM Port Register
  #define	EEPPIN		PINB	//EEPROM Pin Register



  //ADC Pins
  #define	ADCCS		PD3		//ADC Chip Select
  #define	ADCEOC		PD6		//ADC End of Conversion pin

  #define	ADCPORT		PORTD	//ADC Port register
  #define	ADCPIN		PIND	//ADC Pin register


/***************************************************************************
  * 
----------------------------------Macros---------------------------------
 
***************************************************************************/
  //Macro for ASM "sei" global interrupt enable and "cli" global interrupt
  //disable
  #define 	sei()   __asm__ __volatile__ ("sei" ::)
  #define 	cli()   __asm__ __volatile__ ("cli" ::)

  #define 	nop()   __asm__ __volatile__ ("nop" ::)



/***************************************************************************
  * -----------------Function prototypes and global 
variables----------------
 
***************************************************************************/
void initialize(void);
void transmit(unsigned char data);
unsigned char receive(void);
double ADCRead(unsigned int channel);

/***************************************************************************
  * -------------------------------Functions--------------------------------
 
***************************************************************************/


int main(void){	
	double data;
	int datatemp;
	char output;
	
	initialize();

	transmit(0x0C);				//Form Feed

	while(1){
		//Read and transmit channel 1 *************************************
		data = ADCRead(0);
		transmit(0x0A);			//Line Feed
		transmit(0x0D);			//carriage return
		
		//transmit low nibble
		datatemp = (int)(data / 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);
		
		//transmit high nibble
		datatemp = (int)((char)data % 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);

		//Read and transmit channel 2 *************************************
		data = ADCRead(1);
		transmit(0x0A);			//Line Feed
		transmit(0x0D);			//carriage return
		
		//transmit low nibble
		datatemp = (int)(data / 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);
		
		//transmit high nibble
		datatemp = (int)((char)data % 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);
		
		//Read and transmit channel 3 *************************************
		data = ADCRead(2);
		transmit(0x0A);			//Line Feed
		transmit(0x0D);			//carriage return
		
		//transmit low nibble
		datatemp = (int)(data / 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);
		
		//transmit high nibble
		datatemp = (int)((char)data % 0x10);
		if(datatemp<=9) output = datatemp|0x30;
		else output = (datatemp-9)|0x40;
		transmit(output);
		//*****************************************************************
	}

}// End function Main



/**************************************************************************
  * initialize() sets pin directions and enables peripherals on the
  * microcontroller
 
**************************************************************************/
void initialize(void){
	//--------------------PORT Setup--------------------
	DDRD = (1<<ADCCS);
	
	//----------------RS-232 USART Setup----------------
	// Set baud rate
	UBRRH = (unsigned char)(baud>>8);
	UBRRL = (unsigned char)baud;
	// Enable receiver and transmitter
	UCSRB = (1<<RXEN)|(1<<TXEN);
	// Set frame format: 8data, 2stop bit
	UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
	
	
	//------------------ADC/SPI Setup-------------------
	ADCPORT = (1<<ADCCS);			//Disable ADC
	// Set MOSI and SCK output, all others input
	DDRB = (1<<PB5)|(1<<PB7);
	// Enable SPI, Master, set clock rate fck/128
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);

	
	//Globally enable enterrupts
	sei();
	
	//Initialize ADC by performing a conversion and ignoring the result
	//ADCRead(1);
	
}// End function initialize

/**************************************************************************
  * transmit() outputs a character on the RS-232 data bus
 
**************************************************************************/
void transmit(unsigned char data){
	// Wait for empty transmit buffer
	while ( !( UCSRA & (1<<UDRE)) );
	// Put data into buffer, sends the data
	UDR = data;
}//End function transmit

/**************************************************************************
  * receive() receives a byte from the RS-232 data bus.
 
**************************************************************************/
unsigned char receive(void){
	// Wait for data to be received
	while ( !(UCSRA & (1<<RXC)) );
	// Get and return received data from buffer
	return UDR;
}//End function receive

/**************************************************************************
  * ADCRead() reads the value of the selected channel on the external ADC.
  * Accepts a channel number from 0-10.
 
**************************************************************************/
double ADCRead(unsigned int channel){
	double data;
	//Set Chip Select Low
	ADCPORT = ADCPIN^(1<<ADCCS);
	//Send ADC channel select and setup byte
	SPDR = (channel<<4)|(ADCSetup);
	transmit('d');//DEBUG***************************************************************
	while(!(SPSR & (1<<SPIF)));	//Wait for transmission to complete
	//Wait for EOC
	char EOC = 0;
	transmit('e');//DEBUG***************************************************************
	transmit('e');//DEBUG***************************************************************
	while(!EOC){
		EOC = (ADCPIN & (1<<ADCEOC)); //Wait for ADCEOC to go high
	}
	transmit('b');//DEBUG***************************************************************
	//Receive 16 bit value
	while(!(SPSR & (1<<SPIF)));	// Wait for Reception to complete
	data = SPDR;
	transmit('u');//DEBUG***************************************************************
	/*while(!(SPSR & (1<<SPIF)));	// Wait for Reception to complete
	 
transmit('g');//DEBUG***************************************************************
	data += (SPDR<<8);*/
	//Set Chip Select High
	ADCPORT = ADCPIN|(1<<ADCCS);
	transmit('g');//DEBUG***************************************************************
	return data;
}

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.