-/*****************************************************************************\r
-*\r
-* Atmel Corporation\r
-*\r
-* File : TWI_Master.c\r
-* Compiler : IAR EWAAVR 2.28a/3.10c\r
-* Revision : $Revision: 1.13 $\r
-* Date : $Date: 24. mai 2004 11:31:20 $\r
-* Updated by : $Author: ltwa $\r
-*\r
-* Support mail : avr@atmel.com\r
-*\r
-* Supported devices : All devices with a TWI module can be used.\r
-* The example is written for the ATmega16\r
-*\r
-* AppNote : AVR315 - TWI Master Implementation\r
-*\r
-* Description : This is a sample driver for the TWI hardware modules.\r
-* It is interrupt driveren. All functionality is controlled through \r
-* passing information to and from functions. Se main.c for samples\r
-* of how to use the driver.\r
-*\r
-*\r
-****************************************************************************/\r
-\r
-#include <avr/io.h>\r
-#include <avr/interrupt.h>\r
-#include "avr_twi_master.h"\r
-\r
-//static unsigned char TWI_buf[ TWI_BUFFER_SIZE ]; // Transceiver buffer\r
-static unsigned char *TWI_buf;\r
-static unsigned char TWI_msgSize; // Number of bytes to be transmitted.\r
-static unsigned char TWI_sendStop;\r
-static unsigned char TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE.\r
-\r
-union TWI_statusReg TWI_statusReg = {0}; // TWI_statusReg is defined in TWI_Master.h\r
-\r
-/****************************************************************************\r
-Call this function to set up the TWI master to its initial standby state.\r
-Remember to enable interrupts from the main application after initializing the TWI.\r
-****************************************************************************/\r
-void TWI_Master_Initialise(void)\r
-{\r
- TWBR = TWI_TWBR; // Set bit rate register (Baudrate). Defined in header file.\r
-// TWSR = TWI_TWPS; // Not used. Driver presumes prescaler to be 00.\r
- TWDR = 0xFF; // Default content = SDA released.\r
- TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.\r
- (0<<TWIE)|(0<<TWINT)| // Disable Interupt.\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.\r
- (0<<TWWC); //\r
-} \r
- \r
-/****************************************************************************\r
-Call this function to test if the TWI_ISR is busy transmitting.\r
-****************************************************************************/\r
-unsigned char TWI_Transceiver_Busy( void )\r
-{\r
- return ( TWCR & (1<<TWIE) ); // IF TWI Interrupt is enabled then the Transceiver is busy\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to fetch the state information of the previous operation. The function will hold execution (loop)\r
-until the TWI_ISR has completed with the previous operation. If there was an error, then the function \r
-will return the TWI State code. \r
-****************************************************************************/\r
-unsigned char TWI_Get_State_Info( void )\r
-{\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI has completed the transmission.\r
- return ( TWI_state ); // Return error state.\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to send a prepared message. The first byte must contain the slave address and the\r
-read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read\r
-from the slave. Also include how many bytes that should be sent/read including the address byte.\r
-The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
-then initialize the next operation and return.\r
-****************************************************************************/\r
-void TWI_Start_Transceiver_With_Data(\r
- unsigned char *msg, unsigned char msgSize, unsigned char sendStop )\r
-{\r
-// unsigned char temp;\r
-\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
-\r
- TWI_msgSize = msgSize; // Number of data to transmit.\r
- TWI_sendStop = sendStop;\r
- TWI_buf = msg; // store our current message\r
- TWI_statusReg.all = 0; \r
- TWI_state = TWI_NO_STATE ;\r
- TWCR = (1<<TWEN)| // TWI Interface enabled.\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
- (0<<TWWC); //\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.\r
-The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
-then initialize the next operation and return.\r
-****************************************************************************/\r
-void TWI_Start_Transceiver( void )\r
-{\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
- TWI_statusReg.all = 0; \r
- TWI_state = TWI_NO_STATE ;\r
- TWCR = (1<<TWEN)| // TWI Interface enabled.\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
- (0<<TWWC); //\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call\r
-TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the\r
-data when they have arrived. Include a pointer to where to place the data and the number of bytes\r
-requested (including the address field) in the function call. The function will hold execution (loop)\r
-until the TWI_ISR has completed with the previous operation, before reading out the data and returning.\r
-If there was an error in the previous transmission the function will return the TWI error code.\r
-****************************************************************************/\r
-unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )\r
-{\r
- unsigned char i;\r
-\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
-\r
- if( TWI_statusReg.lastTransOK ) // Last transmission competed successfully. \r
- { \r
- for ( i=0; i<msgSize; i++ ) // Copy data from Transceiver buffer.\r
- {\r
- msg[ i ] = TWI_buf[ i ];\r
- }\r
- }\r
- return( TWI_statusReg.lastTransOK ); \r
-}\r
-\r
-// ********** Interrupt Handlers ********** //\r
-/****************************************************************************\r
-This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;\r
-that is whenever a TWI event has occurred. This function should not be called directly from the main\r
-application.\r
-****************************************************************************/\r
-ISR( TWI_vect )\r
-{\r
- static unsigned char TWI_bufPtr;\r
- \r
- switch (TWSR)\r
- {\r
- case TWI_START: // START has been transmitted \r
- case TWI_REP_START: // Repeated START has been transmitted\r
- TWI_bufPtr = 0; // Set buffer pointer to the TWI Address location\r
- case TWI_MTX_ADR_ACK: // SLA+W has been tramsmitted and ACK received\r
- case TWI_MTX_DATA_ACK: // Data byte has been tramsmitted and ACK received\r
- if (TWI_bufPtr < TWI_msgSize)\r
- {\r
- TWDR = TWI_buf[TWI_bufPtr++];\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| //\r
- (0<<TWWC); // \r
- }else // Send STOP after last byte\r
- {\r
- TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully.\r
- if (TWI_sendStop)\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
- (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition\r
- (0<<TWWC); //\r
- else\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // DO NOT Initiate a STOP condition\r
- (0<<TWWC); //\r
- }\r
- break;\r
- case TWI_MRX_DATA_ACK: // Data byte has been received and ACK tramsmitted\r
- TWI_buf[TWI_bufPtr++] = TWDR;\r
- case TWI_MRX_ADR_ACK: // SLA+R has been tramsmitted and ACK received\r
- if (TWI_bufPtr < (TWI_msgSize-1) ) // Detect the last byte to NACK it.\r
- {\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
- (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after reception\r
- (0<<TWWC); // \r
- }else // Send NACK after next reception\r
- {\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send NACK after reception\r
- (0<<TWWC); // \r
- } \r
- break; \r
- case TWI_MRX_DATA_NACK: // Data byte has been received and NACK tramsmitted\r
- TWI_buf[TWI_bufPtr] = TWDR;\r
- TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully. \r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
- (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.\r
- (0<<TWWC); //\r
- break; \r
- case TWI_ARB_LOST: // Arbitration lost\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a (RE)START condition.\r
- (0<<TWWC); //\r
- break;\r
- case TWI_MTX_ADR_NACK: // SLA+W has been tramsmitted and NACK received\r
- case TWI_MRX_ADR_NACK: // SLA+R has been tramsmitted and NACK received \r
- case TWI_MTX_DATA_NACK: // Data byte has been tramsmitted and NACK received\r
-// case TWI_NO_STATE // No relevant state information available; TWINT = �0�\r
- case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition\r
- default: \r
- TWI_state = TWSR; // Store TWSR and automatically sets clears noErrors bit.\r
- // Reset TWI Interface\r
- TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins\r
- (0<<TWIE)|(0<<TWINT)| // Disable Interupt\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests\r
- (0<<TWWC); //\r
- }\r
-}\r