All pastes #2004021 Raw Edit

TI Launchpad I2C slave example

public c v1 · immutable
#2004021 ·published 2010-11-27 20:18 UTC
rendered paste body
//******************************************************************************//	I2C Slave Transmitter//	variable length multi byte read//	single byte write////	6 OCT 2010//  Comments updated 27 NOV 2010 but still incomplete.//  free to use for non-commercial use with attribution.//  Some parts from or inspired by TI example code by//  Z. Albus, R. B. Elliott and H. Grewal.////	Posted as requested in the TI Launchpad Group//  http://groups.google.com/group/ti-launchpad/topics//  About://  The idea was to have a routine that only sends updated data//  LenToSend is the first byte out when read followed by the bytes in the //  dataOut[] array.  When no data is to be sent(no changes) the first byte is 0//  to confirm no changes and not use a nack.//  When being read it should transmit lenToSend and the whole 'buffer' upto //  dataOut[lenToSend] unless terminated early by the master.//  This routine will recieve one byte for commands or to set a mode or whatever //  but no interepretation is done in this code except to set a simulated data counter.//  The LED at P1.1 turns on when communication starts and turns off after STOP bit.  Good for //  trouble shooting and can be deleted.//	//  Compiles with CCS to ____bytes flash and uses ____ bytes RAM//	////******************************************************************************#include  <msp430g2231.h>char dataIn = 2;					//incoming byte from the master is stored herechar lenToSend=2;char dataOut[4]={0,50,100,150};		//New data to transmit containerchar dataIndex=0;					//array index for dataOut, also amount of data sentchar SLV_Addr = 0x50;				// Address is 0x48<<1 to make room for RWbitchar RWbit=0;						// 1=read(S to M), 0=write(M to S)int I2C_State = 0;					// State variablevoid main(void){  WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF){while(1);}			// If calibration constants erased, trap CPU   BCSCTL1 = CALBC1_1MHZ;               // Set DCO  DCOCTL = CALDCO_1MHZ;  P1OUT = 0xC0;                        // P1.6 & P1.7 Pullups  P1REN |= 0xC0;                       // P1.6 & P1.7 Pullups  P1DIR = 0xFF;                        // Unused pins as outputs  P2OUT = 0;  P2DIR = 0xFF;  USICTL0 = USIPE6+USIPE7+USISWRST;    // Port & USI mode setup  USICTL1 = USII2C+USIIE+USISTTIE;     // Enable I2C mode & USI interrupts  USICKCTL = USICKPL;                  // Setup clock polarity  USICNT |= USIIFGCC;                  // Disable automatic clear control  USICTL0 &= ~USISWRST;                // Enable USI  USICTL1 &= ~USIIFG;                  // Clear pending flag  _EINT();  while(1){    LPM0;                              // CPU off, await USI interrupt  }}/******************************************************// USI interrupt service routine////	States				Function//	-----------------	-------------//	2 - 4 - 26			Wrong Address//		 \//		  8 - 24 - 26	Write//		   \//			10 - 14		Read//			|//			12(multi-reloop, back to 10)//////  The main thing to remember about the USI ISR is that it is //  most often triggered by the bit counter running out.//*****************************************************/#pragma vector = USI_VECTOR__interrupt void USI_TXRX (void){	if (USICTL1 & USISTTIFG){     			// Start entry?		I2C_State = 2;               		// Enter 1st state on start				//This with state 2 logic should catch any start condition	}	switch(I2C_State){		case 0: //Idle, should not get here			break;		case 2: 		//Got a Start Condition		//Prep to recieve Address + R/W bit			P1OUT |= 0x01;             		// LED on: Sequence start			USICNT = (USICNT & 0xE0) + 0x08;// Bit counter = 8, RX Address			USICTL1 &= ~USISTTIFG;			// Clear start flag			I2C_State = 4;           		// Go to next state: check address			break;		case 4: // Process Address and send (N)Ack		//USISRL= Address + R/W		//Prep bit to send		//address match->prep Ack		//address miss ->prep Nack			USICTL0 |= USIOE;      		// SDA = output			if ((USISRL & 0xFE) == SLV_Addr){  					// Address Match				if (USISRL & 0x01){				//if address match then save/set RWbit					RWbit = 1;				}				else{					RWbit = 0;				}				USISRL = 0x00;         		//Load Ack to send				I2C_State = 8;         					}			else{			// Address Miss				USISRL = 0xFF;         		//Load NAck to Send				I2C_State = 26;         	//next state: prep for next Start			}			USICNT |= 0x01;          		//Bit counter = 1, send (N)Ack bit			break;		case 8: // Send Data byte		// branch on RWbit		// R/W=1:read :Prep to transmit byte		// R/W=0:write:Prep to recieve byte			if (RWbit == 1){			//Read code 			//prep to TX data				dataIndex=0;				//reset counter				USICTL0 |= USIOE;			//SDA = output				USISRL = dataOut[dataIndex];//Load data byte to be sent				I2C_State = 10;					}			else{			//Write code 			//prep to RX data				USICTL0 &= ~USIOE;			// SDA = input				I2C_State = 24;				//			}			USICNT |=  0x08;				//Bit counter = 8, TX data			break;		case 10:		//Second data byte was just sent		//prep to recieve ack or nack		//logic to continue transfers or shutdown			USICTL0 &= ~USIOE;       		// SDA = input			USICNT |= 0x01;          		// Bit counter = 1, receive (N)Ack			dataIndex++;			if(dataIndex >= lenToSend){			//Check if all data has been sent				I2C_State = 14;				//no more data 			}			else{				I2C_State = 12;				// more data			}			break;					case 12:		//repeated send loop state, send back to 10 for reloop checking		//bit just recieved		//prep next byte to be sent			USICTL0 |= USIOE;				// SDA = output			USISRL = dataOut[dataIndex];	//Load data byte to be sent			USICNT |=  0x08;				// Bit counter = 8, TX data			I2C_State = 10;								break;				case 14:		//Ack or nack just recieved		//Reset machine after read command		//Prep for next Start Condition			dataOut[0]++;            		// Increment Slave data			dataOut[1]--;					// this and previous line are to modulate dummy or											// simulated data and should be deleted for other use.			USICTL0 &= ~USIOE;       		// SDA = input			I2C_State = 0;           		// Reset state machine			P1OUT &= ~0x01;        			// LED off			break;					case 24:		//Byte just recieved		//prep to send Ack		//goto closing state			dataIn = USISRL;			// save the byte that was just recieved			lenToSend = dataIn;			USICTL0 |= USIOE;      		// SDA = output			USISRL = 0x00;         		// Send Ack			USICNT |= 0x01;          	// Bit counter = 1, send (N)Ack bit			I2C_State = 26;			break;					case 26: 		//Reset Machine		//Prep to wait for Start Condition			USICTL0 &= ~USIOE;       		// SDA = input			I2C_State = 0;           		// Reset state machine			P1OUT &= ~0x01;        			// LED off			break;    }	USICTL1 &= ~USIIFG;                  	// Clear pending flags}