SparkFun Forums 

Where electronics enthusiasts find answers.

Discussions on the software and hardware for Atmel's STK standard.
By konfafal
#130471
i have problem with i2c.
after this line: " i2cTransmit(ADXL345, POWER_CTL, 0)"
the communication stop and program don't perform in while(1) loop. usart works great.

what am I doing wrong?
Code: Select all
#define F_CPU 20000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>   
#include <util/twi.h>
 
#define BAUD 19200
#define MYUBRR F_CPU/16/BAUD-1
 
#define VREF 5
 
#define ADXL345 		0x53
#define POWER_CTL		0x2D
#define DATAX0			0x32	
#define DATAX1			0x33	
#define DATAY0			0x34	
#define DATAY1			0x35	
#define DATAZ0			0x36	
#define DATAZ1			0x37	
 
void USART_Init(unsigned int ubrr);
void USART_Tx(unsigned char data);
void USART_TS(const char *s);
void USART_RS(void);
unsigned char USART_Rx(void);
void USART_Flush(void);
 
void PWM_Init(void);
void set_motors(int L_motor, int P_motor); 
 
void ADC_Init(void);
 
void i2cInit(unsigned long scl_freq);
char i2cTransmit(char sla, char reg_addr, char value);
char i2cReceive(char sla, char reg_addr, char * value);
void i2cReset(void);
 
 
unsigned char buff[32];
int x;
int y;
int z;
char temp;
char value;
char c;
float vbat;
static volatile uint8_t adc_flag;
static volatile uint8_t rx_flag;
static volatile uint8_t tx_flag;
 
int main(void)
{
    DDRC |= _BV(1)|_BV(2)|_BV(3);				//diody led
	DDRD |= _BV(4)|_BV(5)|_BV(6)|_BV(7);      //L298
	DDRB |= _BV(1)|_BV(2);						//pwmy
	DDRC |= _BV(4)|_BV(5);						//SDA i SCL
 
	PWM_Init();
	ADC_Init();
	//sei();                            
	cli();
 
	i2cInit(50000); 
	USART_Init(MYUBRR);
 
	i2cReset(); 
	i2cTransmit(ADXL345, POWER_CTL, 0);  	//reset
	//i2cReset(); 
	//i2cTransmit(ADXL345, POWER_CTL, 16);	//standby
	//i2cReset(); 
	//i2cTransmit(ADXL345, POWER_CTL, 8);	//measure
 
 
	i2cReset();
	_delay_ms(100);
 
    while(1) 
    {
		/*
		i2cReceive(ADXL345, DATAX0, &value);
		temp = value;
		i2cReceive(ADXL345, DATAX1, &value);
		x = (value<<8)|temp;			
 
		i2cReceive(ADXL345, DATAY0, &value);
		temp = value;
		i2cReceive(ADXL345, DATAY1, &value);
		y = (value<<8)|temp;		
 
		i2cReceive(ADXL345, DATAZ0, &value);
		temp = value;
		i2cReceive(ADXL345, DATAZ1, &value);
		z = (value<<8)|temp;
		*/
 
 
		sprintf(buff, "%d %d %d\r\n", x,y,z);
		USART_TS(buff);
		USART_TS("wynik: \r\n");
		_delay_ms(1000);
 
    }
}
 
void USART_Init(unsigned int ubrr)
{	
	UBRR0H = (unsigned char)(ubrr>>8);		// Set baud rate 
	UBRR0L = (unsigned char)ubrr;
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);		// Enable receiver and transmitter 
 
	//UCSR0B |= (1<<RXCIE0)|(1<<TXCIE0);		// przerwania 
 
	UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);		// 8 bitów danych, 1 bit stopu, brak parzystości 
}
 
void USART_Tx(unsigned char data)
{
	while (!( UCSR0A & (1<<UDRE0)));		// Wait for empty transmit buffer 
	UDR0 = data;							// Put data into buffer, sends the data 
}
 
void USART_TS(const char *s)
{
	while (*s) 
		USART_Tx(*s++);
}
 
void USART_RS(void)
{
	unsigned char i=0;
	do
	{
		if((buff[i] = USART_Rx()) == '\n') break;
		i++;
	}while(i < 32);							//zeby nie przepelnic bufora
}
 
unsigned char USART_Rx(void)
{
	while (!(UCSR0A & (1<<RXC0)));			/* Wait for data to be received */
	return UDR0;							/* Get and return received data from buffer */
}
 
void USART_Flush(void)						/* opróżnianie bufora odbioru */
{
	unsigned char dummy;
	while (UCSR0A & (1<<RXC0)) dummy = UDR0;
}
 
void PWM_Init(void)
{
	//8bit PWM, phase correct
	//MCU clock / 8
 
	OCR1A = 0;
	OCR1B = 0;
 
	TCCR1A = (1<<COM1A1)|
			 (1<<COM1B1)|
			 (1<<WGM10);
 
	TCCR1B = (1<<CS11)|
			 (1<<WGM12)|
			 (1<<CS10);
}
 
void set_motors(int L_motor, int P_motor) 
{
	if(L_motor<0){
			ENABLE_B = (-1)*L_motor;
			INPUT3_PORT &= ~INPUT3;
			INPUT4_PORT |=  INPUT4;}
 
	else if(L_motor>0){
			ENABLE_B = L_motor;
			INPUT3_PORT |=  INPUT3;
			INPUT4_PORT &= ~INPUT4;}
 
	else if(L_motor==0){		
			ENABLE_B = 0;}
 
	else if(L_motor==-1){
			INPUT3_PORT |=  INPUT3;
			INPUT4_PORT |=  INPUT4;}
 
 
	if(P_motor<0){
			ENABLE_A = (-1)*P_motor;
			INPUT1_PORT &= ~INPUT1;
			INPUT2_PORT |=  INPUT2;}
 
	else if(P_motor>0){
			ENABLE_A = P_motor;
			INPUT1_PORT |=  INPUT1;			
			INPUT2_PORT &= ~INPUT2;}	
 
	else if(P_motor==0){		
			ENABLE_A = 0;}
 
	else if(P_motor==-1){
			INPUT1_PORT |=  INPUT1;
			INPUT2_PORT |=  INPUT2;}	
}
 
void ADC_Init(void)
{
	ADMUX |= (1 << REFS0);              					// Set ADC reference to AVCC 
	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 128
	ADCSRA |= (1 << ADIE);									// przerwania
	ADCSRA |= (1 << ADEN)|(1<<ADATE);  					// Enable ADC + auto triger
	ADCSRA |= (1 << ADSC);              					// Start A2D Conversions (ADEN musi byc wlaczony)
}
 
void i2cInit(unsigned long scl_freq)
{
	//Set the TWI Prescaler to 1
	//(Actually this is default setting...)
 
	//Set up the TWI Bit Rate
	TWBR = F_CPU/(2*(long)scl_freq)-8;	//(SCL_FREQ = F_CPU/(16+2*TWBR) *According to datasheet
}
 
//Puts the ATmega in Master Transmitter mode and sends a value to a register
//pre: sla - i2c address of slave
//	   reg_addr - the register to address
//	   value - the value to write in the register location
//returns: 	1-Success
//		    TWSR - Failure (The TWI failure code)
char i2cTransmit(char sla, char reg_addr, char value)
{
												//Send the start condition
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	//Clear int bit(by writing a 1), enable twi and send start
	while (!(TWCR & (1<<TWINT)));				//Wait for the interrupte bit to get set
	if(TW_STATUS != TW_START)return TWSR;
 
												//No matter what we start with a write to the slave
	TWDR = sla | TW_WRITE;						//Put the slave address in the twi data register
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the address to the slave
	while (!(TWCR & (1<<TWINT)));				//Wait for the operatation to complete
	if (TW_STATUS != TW_MT_SLA_ACK)return TWSR;	//Make sure we received an ack from the slave.
 
												//Load the register into the slave device that we want to alter
	TWDR = reg_addr;	
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the register address through the twi interface
	while (!(TWCR & (1<<TWINT)));				//Wait for operation to complete
	if (TW_STATUS != TW_MT_DATA_ACK)return TWSR;//Make sure we received an ack from the slave
 
												//Now send the actual register data to the slave
	TWDR = value;
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the register value through the twi interface
	while (!(TWCR & (1<<TWINT)));				//Wait for operation to complete
	if (TW_STATUS != TW_MT_DATA_ACK)return TWSR;//Make sure we received an ack from the slave
 
												//We're finished. Send a stop.
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	return 1;
}
 
//Reads a value from a specified register
//pre: sla - i2c address of slave
//	   reg_addr - The address of the register to read from
//	   value - a pointer to a character
//post: value is assigned the value read from the register
//returns: 1 - Success
//		   TWSR - Failur
char i2cReceive(char sla, char reg_addr, char * value)
{
												//Send the start condition
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	//Clear int bit(by writing a 1), enable twi and send start
	while (!(TWCR & (1<<TWINT)));				//Wait for the interrupte bit to get set
	if (TW_STATUS != TW_START)return TWSR;		//Check the TWI status, return if bad status.
 
												//Start Condition has been transmitted
												//Send SLA+W to TWDR
	TWDR = sla|TW_WRITE;						//Put the slave address in the twi data register
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the address to the slave
	while (!(TWCR & (1<<TWINT)));				//Wait for the operatation to complete
	if(TW_STATUS != TW_MT_SLA_ACK)return TWSR;
 
												//SLA+W has been transmitted, Ack has been received
												//Load the register into the slave device that we want to read
	TWDR = reg_addr;	
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the register address through the twi interface
	while (!(TWCR & (1<<TWINT)));				//Wait for operation to complete
	if(TW_STATUS != TW_MT_DATA_ACK)return TWSR;
 
												//Data byte has been transmitted, Ack has been received
												//Now send a 'repeated start' to switch to master receiver mode
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	//Clear int bit(by writing a 1), enable twi and send start
	while (!(TWCR & (1<<TWINT)));				//Wait for the interrupte bit to get set
	if (TW_STATUS != TW_REP_START)return TWSR;
 
												//A Repeated Start condition has been received
												//Send the SLA+R 
	TWDR = sla | TW_READ;						//Load the slave address and the read bit into the data register
	TWCR = (1<<TWINT)|(1<<TWEN);				//Send the address+R to the slave
	while(!(TWCR & (1<<TWINT)));				//Wait for the operation to complete
	if (TW_STATUS != TW_MR_SLA_ACK)return TWSR;	//Make sure we got the right ack.
 
												//SLA+R has been transmitted, Ack has been received
												//Get the value from the pre-configured register on the slave
	TWCR = (1<<TWINT)|(1<<TWEN);				//Tell the slave to send the next value and send NACK afterwards
	while(!(TWCR & (1<<TWINT)));				//Wait for the operation to complete
	if (TW_STATUS != TW_MR_DATA_NACK)return 5;	//Make sure we got the right ack.
 
												//Data byte has been received, Nack has been returned
												//Send a stop
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
 
	*value = TWDR;	
	return 1;									//Return the value we got from the register
}
 
void i2cReset(void)
{
	TWCR = 0;
}