Rev 2248 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*****************************************************************************************************************************
* File: twimaster.c
*
* Purpose: setup of I2C (TWI)
*
* Functions: extern void i2c_init (void); // initialize I2C
* extern void i2c_start (void); // Start I2C
* extern void i2c_reset(void); // resert I2C
* extern void i2c_stop (void); // Stop I2C
* extern void i2c_write_byte (char byte); // write 1 Byte
*
*****************************************************************************************************************************/
#include "twimaster.h"
#include "main.h"
volatile unsigned char twi_state = 0;
unsigned char motor=0;
unsigned char motorread=0, MissingMotor=0;
unsigned char motor_rx[16], motor_rx2[16];
unsigned char MotorPresent[MAX_MOTORS]; // #define MAX_MOTORS 4
unsigned char MotorError[MAX_MOTORS];
unsigned int I2CError=0;
// *************************************************************************************************************************************
// Initzialize I2C (TWI)
//
void i2c_init(void)
{
//--------------------------------------------------------------------------------------------------------------------
// TWSR = TWI Status Register containing: TWS7 TWS6 TWS5 TWS4 TWS3 TWPS1 TWPS0
//
TWSR = 0; // TWSR TWI Status Register
//--------------------------------------------------------------------------------------------------------------------
// TWBR = TWI Bit Rate Register containing: TWBR7 TWBR6 TWBR5 TWBR4 TWBR3 TWBR2 TWBR1 TWBR0
// set TWI Bit Rate Register // SYSCLK = 16000000 and SCL_CLOCK = 200000
TWBR = ((SYSCLK/SCL_CLOCK)-16)/2; // selects the division factor for the bit rate generator
}
// *************************************************************************************************************************************
//-------------------------------------------------------------------------------------------------------------------------------------
// Start I2C
//
void i2c_start(void)
{
// ---------------------------------------------------------------------------
// TWCR = TWI Control Register -> TWINT TWEA TWSTA TWSTO TWWC TWEN TWIE
// TWINT = TWI interrupt flag - to be set to one, to reset the TWINT Flag
// TWSTA = TWI start and should be set to one, that TWI is started as Master.
// TWEN = TWI enable -> now TWI/I2C is working properly.
// TWIE = TWI Interrupt enable is the TWIE Bit -> should be set
//
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
// Stop I2C
//
void i2c_stop(void)
{
// ---------------------------------------------------------------------------
// TWCR = TWI Control Register -> TWINT TWEA TWSTA TWSTO TWWC TWEN TWIE
// TWINT = TWI interrupt flag - to be set to one, to reset the TWINT Flag
// TWSTO = TWI STOP Condition Bit (TWSTO = 1) -> now will be stoped
// TWEN = TWI enable -> TWI/I2C is working properly
//
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
// I2C Reset
//
void i2c_reset(void)
{
i2c_stop();
twi_state = 0;
motor = TWDR; // TWI Data Register (TWDR) siehe S 227
motor = 0; // ist das letzte gesendete oder empfangene Byte
TWCR = 0x80;
TWAMR = 0;
TWAR = 0;
TWDR = 0;
TWSR = 0;
TWBR = 0;
i2c_init();
i2c_start();
i2c_write_byte(0);
}
//-------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------------
// write via I2C
//
void i2c_write_byte(char byte)
{
TWSR = 0x00;
TWDR = byte; // sende dieses Byte via TWI Data Register
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------------
// write byte via I2C
//
void I2C_WriteByte(int8_t byte)
{
// move byte to send into TWI Data Register
TWDR = byte;
// clear interrupt flag (TWINT = 1)
// enable i2c bus (TWEN = 1)
// enable interrupt (TWIE = 1)
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------------
// ein Byte gelesen und sendet ACK
//
void I2C_ReceiveByte(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWEA);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------------
// I2C empfing das letzte Byte und sendet kein ACK
//
void I2C_ReceiveLastByte(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------------------------
// Interrupt I2C
//
ISR (TWI_vect)
{
static unsigned char missing_motor;
switch(twi_state++)
{
//----------------------------------------------------------------------------------------------------------------------------
// write Motor-Data
//----------------------------------------------------------------------------------------------------------------------------
case 0:
while(Mixer.Motor[motor][0] <= 0 && motor < MAX_MOTORS) motor++; // #define MAX_MOTORS 2
if(motor == MAX_MOTORS) // writing finished -> now read
{
motor = 0;
twi_state = 3;
if(motorread==0) i2c_write_byte(0x53); // Read-Adress of: Motor 1 = 0x53 / 2 = 0x55 / 3 = 0x57 / 4 = 0x59
if(motorread==1) i2c_write_byte(0x57);
}
else
{
if(motor==0) i2c_write_byte(0x52); // Write-Adress of: Motor 1 = 0x52 / 2 = 0x54 / 3 = 0x56 / 4 = 0x58
if(motor==1) i2c_write_byte(0x56);
}
break;
case 1:
i2c_write_byte(Motor[motor++]);
break;
case 2:
// TWSR TWI Status Register -> TWS7 TWS6 TWS5 TWS4 TWS3 - TWPS1 TWPS0
// Data byte has been transmitted; NOT ACK has been received
if(TWSR == 0x30)
{
if(!missing_motor) missing_motor = motor; //
if(++MotorError[motor-1] == 0) MotorError[motor-1] = 255; //
}
i2c_stop();
I2CTimeout = 10; // counted down every 2ms = watchdog
twi_state = 0;
i2c_start();
break;
//----------------------------------------------------------------------------------------------------------
// read Motor-Data
//----------------------------------------------------------------------------------------------------------
case 3:
if(TWSR != 0x40) // Error?
{ // send 1. Byte to be read
MotorPresent[motorread] = 0;
motorread++;
if(motorread >= MAX_MOTORS) motorread = 0; // #define MAX_MOTORS 2
i2c_stop();
twi_state = 0;
}
else
{
MotorPresent[motorread] = ('1' - '-') + motorread;
I2C_ReceiveByte();
}
//MissingMotor = missing_motor;
MissingMotor = 0;
missing_motor = 0;
break;
case 4: // read 1. Byte and send 2. Byte
motor_rx[motorread] = TWDR;
I2C_ReceiveLastByte(); // no acknowledge
break;
case 5:
motor_rx2[motorread++] = TWDR; // read 2. Byte
if(motorread >= MAX_MOTORS) motorread = 0; // #define MAX_MOTORS 4
i2c_stop();
twi_state = 0;
break;
//----------------------------------------------------------------------------------------------------------------------------------
// write Gyro-Offset
//----------------------------------------------------------------------------------------------------------------------------------
case 8:
i2c_write_byte(0x98); // Address of DAC see DAC Manual page 17
break;
case 9:
i2c_write_byte(0x10); // byte sent to chanel A
break;
case 10:
i2c_write_byte(AnalogOffsetNick); // offset sent to DAC
break;
case 11:
i2c_write_byte(0x80); // The 2nd Byte does not care = 0x80 (Dummy)
break;
case 12:
i2c_stop();
I2CTimeout = 10;
i2c_start();
break;
case 13:
i2c_write_byte(0x98); // Address of DAC see DAC Manual page 17
break;
case 14:
i2c_write_byte(0x12); // byte sent to chanel B
break;
case 15:
i2c_write_byte(AnalogOffsetRoll); // offset sent to DAC
break;
case 16:
i2c_write_byte(0x80); // The 2nd Byte does not care = 0x80 (Dummy)
break;
case 17:
i2c_stop();
I2CTimeout = 10;
i2c_start();
break;
case 18:
i2c_write_byte(0x98); // Address of DAC see DAC Manual page 17
break;
case 19:
i2c_write_byte(0x14); // byte sent to chanel C
break;
case 20:
i2c_write_byte(AnalogOffsetGier); // offset sent to DAC
break;
case 21:
i2c_write_byte(0x80); // The 2nd Byte does not care = 0x80 (Dummy)
break;
case 22:
i2c_stop();
I2CTimeout = 10;
twi_state = 0;
break;
default: twi_state = 0;
break;
}
TWCR |= 0x80; // TWWC: TWI Write Collision Flag is set to 1
}
//-----------------------------------------------------------------------------------------------------------------------------------