All pastes #2004060 Raw Edit

TI Launchpad I2C Master example

public c v1 · immutable
#2004060 ·published 2010-11-27 20:36 UTC
rendered paste body
//******************************************************************************//	I2C Master//	double byte read//	single byte write////  5 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://  Inits a 2x16 display, inits the USI and continually polls the slave for data//  to display.  In this demo mode it writes a byte to the slave after 50 read transactions//  (every 50 start conditions not every 50 bytes)  Only accepts 2 bytes from the slave//  because I lost my variable byte code.  First byte is displayed on the first line and //  the second byte on the second line right after each is recieved.  The display routines //  are called from within the USI ISR which I'm sure has a performance penalty especially //  in data transfer rate.//  See below for more on display routines and pinout.  Could be repurposed easily.//  See also: slave code at http://pastebin.ca/2004021////  To do://  Get the various intervals off of a wait loop and onto a timer interrupt//  Redevelop the variable length code//	//  Compiles with CCS to ____bytes flash and uses ____ bytes RAM//******************************************************************************#include  <msp430g2231.h>//My display routinesvoid formatAndSend(char data);void dispClear(int arg);void dispSend4(char data);void dispSend8(char data);void dispGo(int row, int col);void wait(int max);char rs=0;					//(0,1) register select for displaychar SLV_data = 0x00;char SLV_Addr = 0x50; 		// Address is 0x48 << 1 bit + 1 for Readchar toggle1;				// just a var to switch between first and second bytechar RWbit = 1;				// (0,1) 0= writeto slave, 1= read from slavechar counter1=0;			//just a counter to insert write cycles for funint I2C_State = 0; 			// State variablevoid main(void){	volatile unsigned int i; 		// Use volatile to prevent removal	//Clocks	WDTCTL = WDTPW + WDTHOLD; 		// Stop watchdog	if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF){while(1);}			// If calibration constants are erased do not load, trap CPU!!	BCSCTL1 = CALBC1_1MHZ; // Set DCO	DCOCTL = CALDCO_1MHZ;	//Pin Setup	P1SEL &= 0x06;  //clear 39, don't care 0xC0	P1REN =  0xC6;  //set 0xC0, clear 0x39	P1DIR |= 0x39;  //set 0x39	P2SEL =  0x00;  //clear 0xC0	P2DIR =  0xFF;  //set 0xC0	P2REN =  0x00;  //clear 0xC0	//Display init	rs=0;	dispSend4(0x20);	dispSend8(0x28);	dispSend8(0x0e);	dispSend8(0x06);	rs=1;	//Display form	dispSend8('1');	dispSend8(':');	dispGo(2,1);	dispSend8('2');	dispSend8(':');	dispGo(1,1);	//USI init	USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;	// Port & USI mode setup	USICTL1 = USII2C+USIIE;					  	// Enable I2C mode & USI interrupt	USICKCTL = USIDIV_3+USISSEL_2+USICKPL;		// Setup USI clocks: SCL = SMCLK/8 (~120kHz)	USICNT |= USIIFGCC;  						// Disable automatic clear control	USICTL0 &= ~USISWRST;  						// Enable USI	USICTL1 &= ~USIIFG;  						// Clear pending flag	_EINT();	while(1){		counter1++;			//Counter1 is used to send a write to the Slave once every 50 transactions		if(counter1 > 49){			counter1=0;			RWbit = 0;			SLV_Addr = 0x50;		}		else{			RWbit = 1;			SLV_Addr = 0x51;		}		dispGo(1,7);		formatAndSend(counter1);		dispSend8(' ');		formatAndSend(SLV_Addr);	//Shows the slave address including RWbit				USICTL1 |= USIIFG; 						// Set flag and start communication		LPM0;  									// CPU off, await USI interrupt		_NOP();  								// Used for IAR		for (i = 0; i < 5000; i++);  			// Dummy delay between communication cycles	}}/******************************************************// USI interrupt service routine////	States							Function//	-----------------				-------------//	0 - 2 - 4 	 					setup always happens//		 	 \//			  10 					nack recieved, end//			  or//			  18 - 20 - 10			Write byte to slave//			  or//			  6 - 14 - 16 - 8 - 10 	read bytes from slave////  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){	switch(I2C_State){				case 0:		//Generate start condition		//Prep address to send		//case 0 is manually tiggered by setting the interrupt flag			USISRL = 0x00; 						// Generate Start Condition			USICTL0 |= USIGE+USIOE;			USICTL0 &= ~USIGE;			USISRL = SLV_Addr;//(SLV_Addr | RWbit); 		// Build and transmit address, R/W = 1			USICNT = (USICNT & 0xE0) + 0x08; 	// Bit counter = 8, TX Address			I2C_State = 2; 						// Go to next state: receive address (N)Ack			break;		case 2:		//Byte(address + R/W) just sent		//prep to recieve bit from slave, ack or nack			USICTL0 &= ~USIOE;					// SDA = input			USICNT |= 0x01;  					// Bit counter = 1, receive (N)Ack bit			I2C_State = 4; 						// Go to next state: check (N)Ack			break;		case 4:		//bit just recieved		//RWbit=1->Read			//Ack ->prep to receive byte and continue communication			//Nack->prep for issuing STOP condition		//RWbit=0->Write			//prep to send byte			if (RWbit == 1){			//Read Code				if (USISRL & 0x01){ 								// If Nack received Prep Stop Condition					USICTL0 |= USIOE;					USISRL = 0x00;					USICNT |=  0x01; 				// Bit counter = 1, SCL high, SDA low					I2C_State = 10;  				// Go to next state:				}				else{ 							// Ack received, Receive Data from slave					USICNT |=  0x08; 				// Bit counter = 8, RX data					I2C_State = 6; 					// Go to next state:				}			}				else{			//Write Code					USISRL = 77;				USICTL0 |= USIOE;  					// SDA = output					USICNT |=  0x08; 					// TX a byte				I2C_State = 18;			}			break;		case 6: 			//First Byte just recieved		//Formated display of data		//Prep to send N/Ack bit			USICTL0 |= USIOE;  					// SDA = output			dispGo(1,3);			formatAndSend(USISRL);  			USICNT |= 0x01;  					// Bit counter = 1, send (N)Ack bit			I2C_State = 14;						// Go to next state			break;		case 8: 			//Bit just sent		//Prep Stop Condition			USICTL0 |= USIOE;  					// SDA = output			USISRL = 0x00;			USICNT |=  0x01; 					// Bit counter = 1, SCL high, SDA low			I2C_State = 10;  					// Go to next state: generate Stop			break;		case 10:		//coming from case 8 or 4 or __		//Generate Stop Condition			USISRL = 0x0FF;  					// USISRL = 1 to release SDA			USICTL0 |= USIGE;  					// Transparent latch enabled			USICTL0 &= ~(USIGE+USIOE);			// Latch/SDA output disabled			I2C_State = 0; 						// Reset state machine for next transmission			LPM0_EXIT; 							// Exit active for next transfer			break;					case 14: 			//Just sent bit		//Prep to recieve second byte			USICTL0 &= ~USIOE;					// SDA = input			USICNT |=  0x08; 					// Bit counter = 8, RX data			I2C_State = 16; 					// Go to next state: Test data and (N)Ack			break;		case 16: 			//Second Byte just recieved		//Formated display of data		//Prep to send N/Ack bit			USICTL0 |= USIOE;  					// SDA = output			dispGo(2,3);			formatAndSend(USISRL);  			USICNT |= 0x01;  					// Bit counter = 1, send (N)Ack bit			I2C_State = 8; 						// Go to next state: prep stop			break;					case 18:		//Just wrote byte to slave		//prep to recieve bit			USICTL0 &= ~USIOE;					// SDA = input			USICNT |= 0x01;  					// Bit counter = 1, receive (N)Ack bit			I2C_State = 20;			break;					case 20:		//just recieved bit		//prep to stop			USICTL0 |= USIOE;			USISRL = 0x00;			USICNT |=  0x01; 				// Bit counter = 1, SCL high, SDA low			I2C_State = 10;  				// Go to next state:			break;				}	USICTL1 &= ~USIIFG;  						// Clear pending flag}//******************************************************************************//	Display routines for use with a HD44780 series display driver chip//  My display uses a HD44780A00////  PINOUT//  P1.0	E		enable/clock//  P1.3	RS		register select ,1=char data, 0=commands//  P1.4	DB4		data LSB//  P1.5	DB5//  P2.6	DB6//  P2.7	DB7		data MSB//******************************************************************************void formatAndSend(char data){//To turns an 8-bit unsigned integer value into //three decimal digits and sends to display	char temp;	temp=(data/100)+0x30;	dispSend8(temp);	temp=((data/10)%10)+0x30;	dispSend8(temp);	temp=(data%10)+0x30;	dispSend8(temp);}void dispClear(int arg){//arg	Action//---   ------------------// 0	clear whole screen// 1	clear first line// 2	clear second line//else	clear whole screenchar i=0;switch (arg){	case 1:		dispGo(1,1);		for(i=0;i<16; i++){		dispSend8(0x20);}		dispGo(1,1);		break;	case 2:		dispGo(2,1);		for(i=0;i<16; i++){		dispSend8(0x20);}		dispGo(2,1);		break;	case 0:	default:		rs = 0;		dispSend8(0x01);		rs = 1;		dispGo(1,1);		break;	}}void dispGo(int row, int col){//Move cursor to row and columnchar send=0;	send=(((row-1)*0x40)+(col-1))|0x80;	rs=0;	dispSend8(send);	rs=1;}void dispSend4(char data){//takes the 4 MSB bits of data and formats for //this pin set up	int pulsewidth;	if (rs==1) {pulsewidth=10;P1OUT |= 0x08;}//set the clock rate and set the RS line	else {pulsewidth=50;P1OUT &= 0xf7;}	//set up the data output	P1OUT = ((0x30 & data) | (0xcf & P1OUT));	P2OUT = data;  //six bits have no pins	//Pulse the E line	wait(pulsewidth);		//wait time	  	P1OUT |= 0x01;			//clock high	wait(pulsewidth);		//wait time	  	P1OUT ^= 0x01;			//clock low}void dispSend8(char data){//breaks 8 bits into two 4 bit chunks for sending to the display//lower 4 bits of sent data are ignored	dispSend4(data);	data= data<<4;	dispSend4(data);	}void wait(int max){	int i=0;	for(i=0;i<max; i++);	//wait time		}