This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430G2231: USI-I2C and SSD1306

Part Number: MSP430G2231
Other Parts Discussed in Thread: MSP430G2553

Tool/software: Code Composer Studio

I want to use my SSD1306 with my MSP430G2231 using I2C (USI).

This is my working code for MSP430G2553:

#include <msp430.h>

/*
0xAE,  // Display off
0x81,  // set contrast controll register
0x7F,  // contrast Wert 127 ok

0x20,  // Set Memory Adress Mode
0x01,  // Vertical Adressing Mode

0x21,  // Set Column Adress
0x00,  // Start Adress 0
0x7F,  // End Adress 127

0x22,  // Set Page Adress
0x00,  // Start Adress 0
0x07,  // End Adress 7

0x40,  // set start line adress 0

0xA0,  // Column Adress mapped to SEG0

0xA8,  // set multiplex ratio
0x3F,  // maximum

0xC0,  // Set COM Output Scan Direction to normal mode

0xD3,  // set display offset
0x00,  // 0

0x8D,  // Set Charge Pump Setting
0x14,  // ON

0xDA,  // set com pins hardware conf
0x12,  // alternative + disable remap

0xD5,  // set display clock divide + freq
0x80,  // divide by 1 and medium freq

0xD9,  // set pre charge preriod
0x22,  // medium (reset value)

0xDB,  // set vcomh
0x20,  // 0.77 x Vcc

0xA4,  // Output follows RAM Content

0xAF  // Display on*/


const unsigned char Init[] = {0xAE,0x81,0x07,0x20,0x01,0x21,0x00,0x7F,0x22,0x00,0x07,0x40,0xA0,0xA8,0x3F,0xC0,0xD3,0x00,0x8D,0x14,0xDA,0x12,0xD5,0x80,0xD9,0x22,0xDB,0x20,0xA6,0xA4,0xAF};

//const unsigned char Init[] = {0xAE,0x81,0x07,0x20,0x01,0x21,0x00,0x7F,0x22,0x00,0x07,0x40,0xA0,0xA8,0x3F,0xD3,0x00,0x8D,0x14,0xD5,0x80,0xD9,0x22,0xDB,0x20,0xA6,0xA4,0xAF};


const unsigned char Mod[] = {0xA5};

unsigned int i = 0;
//unsigned int I = 0;

void printC(const unsigned char* Array, unsigned int length){

	UCB0CTL1 = UCSWRST;
	UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;			// I2C master mode
	UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
	UCB0BR0 = 0x40;                          // < 100 kHz
	UCB0I2CSA = 0x3C;                       // address
	UCB0CTL1 &= ~UCSWRST;
	IE2 |= UCB0TXIE;				// Enable TX ready interrupt
	__disable_interrupt();
	UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition


	__bis_SR_register(LPM3_bits + GIE);

	unsigned int c;
	for(c = 0; c < length; c++){
		//__bis_SR_register(LPM3_bits + GIE);
		UCB0TXBUF = 0x80;
		__bis_SR_register(LPM3_bits + GIE);
		UCB0TXBUF = Array[c];
		__bis_SR_register(LPM3_bits + GIE);
	}

	UCB0CTL1 |= UCTXSTP;
	IE2 &= ~UCB0TXIE;

}

void printS(void){
	UCB0CTL1 = UCSWRST;
	UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;			// I2C master mode
	UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
	UCB0BR0 = 0x40;                          // < 100 kHz
	UCB0I2CSA = 0x3C;                       // address
	UCB0CTL1 &= ~UCSWRST;
	IE2 |= UCB0TXIE;				// Enable TX ready interrupt
	__disable_interrupt();
	UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

	__bis_SR_register(LPM3_bits + GIE);;
}

void printD(const unsigned char Data){
	UCB0TXBUF = Data;
	__bis_SR_register(LPM3_bits + GIE);
}

void printE(void){
	UCB0CTL1 |= UCTR + UCTXSTP;
}


void main(void){
    WDTCTL = WDTPW + WDTHOLD;

    DCOCTL = CALDCO_8MHZ;				//DCO setting = 8MHz
    BCSCTL1 = CALBC1_8MHZ;				//DCO setting = 8MHz

    // Configure Pins for I2C
    P1SEL |= BIT6 + BIT7;                  // Pin init
    P1SEL2 |= BIT6 + BIT7;                  // Pin init


    printC(Init,31);

    __delay_cycles(8000000);

    printC(Mod,1);

    /*
    printS();



    UCB0TXBUF = 0x00;
    __bis_SR_register(LPM3_bits + GIE);


    unsigned int i;
    for(i = 500; i > 0; i--){
    	printD(0xFF);
    	printD(0x00);
    }
    printE();*/

    while(1);

}


// USCI_B0 Data ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void){
	IFG2 &= ~UCB0TXIFG;
	__bic_SR_register_on_exit(LPM3_bits);               // Wakeup main code
}

This is my code for the MSP430g2231. Most of is is based on the MSP430G2x21/G2x31 Demo - I2C Master Transmitter / Reciever, multiple bytes.

#include <msp430.h>

//const unsigned char Init[] = {0xAE,0x81,0x07,0x20,0x01,0x21,0x00,0x7F,0x22,0x00,0x07,0x40,0xA0,0xA8,0x3F,0xC0,0xD3,0x00,0x8D,0x14,0xDA,0x12,0xD5,0x80,0xD9,0x22,0xDB,0x20,0xA6,0xA4,0xAF};
const unsigned char Init[] = {0x80,0xAE,0x80,0x81,0x80,0x07,0x80,0x20,0x80,0x01,0x80,0x21,0x80,0x00,0x80,0x7F,0x80,0x22,0x80,0x00,0x80,0x07,0x80,0x40,0x80,0xA0,0x80,0xA8,0x80,0x3F,0x80,0xC0,0x80,0xD3,0x80,0x00,0x80,0x8D,0x80,0x14,0x80,0xDA,0x80,0x12,0x80,0xD5,0x80,0x80,0x80,0xD9,0x80,0x22,0x80,0xDB,0x80,0x20,0x80,0xA6,0x80,0xA4,0x80,0xAF};
const unsigned char Mod[] = {0x80,0xA5};

//#define number_of_bytes   5                 // How many bytes?

unsigned int number_of_bytes;
unsigned int bla;

void Master_Transmit(void);
void Master_Recieve(void);

void Setup_USI_Master_TX(void);
void Setup_USI_Master_RX(void);

char MST_Data[];// = 0x55;                       // Variable for transmitted data
//char SLV_Addr = 0x78;
int I2C_State, Bytecount, Transmit = 0;     // State variable
void Data_TX (void);
void Data_RX (void);
int main(void)
{
  volatile unsigned int i;                  // Use volatile to prevent removal

  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog
  if (CALBC1_1MHZ==0xFF)					// If calibration constants erased
  {
    while(1);                               // do not load, trap CPU!!
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;

  P1OUT = 0xC0;                             // P1.6 & P1.7 Pullups, others to 0
  P1REN |= 0xC0;                            // P1.6 & P1.7 Pullups
  P1DIR = 0xFF;                             // Unused pins as outputs
  P2OUT = 0;
  P2DIR = 0xFF;



  while(1)
  {
	number_of_bytes = 62;
	bla = 0;
    Master_Transmit();
    __no_operation();                       // Used for IAR
    __delay_cycles(2000000);

	number_of_bytes = 2;
	bla = 1;
    Master_Transmit();
    __no_operation();                       // Used for IAR

    __delay_cycles(800000);
 }
}

/******************************************************
// USI interrupt service routine
// Data Transmit : state 0 -> 2 -> 4 -> 10 -> 12 -> 14
// Data Recieve  : state 0 -> 2 -> 4 -> 6 -> 8 -> 14
******************************************************/
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USI_VECTOR))) USI_TXRX (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(I2C_State,14))
    {
      case 0: // Generate Start Condition & send address to slave
              P1OUT |= 0x01;                // LED on: sequence start
              Bytecount = 0;
              USISRL = 0x00;                // Generate Start Condition...
              USICTL0 |= USIGE+USIOE;
              USICTL0 &= ~USIGE;
              if (Transmit == 1){
                USISRL = 0x78;              // Address is 0x48 << 1 bit + 0 (rw)
              }
               if (Transmit == 0){
               USISRL = 0x79;               // 0x91 Address is 0x48 << 1 bit
                                            // + 1 for Read
               }
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address
              I2C_State = 2;                // next state: rcv address (N)Ack
              break;

      case 2: // Receive Address Ack/Nack bit
              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: // Process Address Ack/Nack & handle data TX

 if(Transmit == 1){
              USICTL0 |= USIOE;             // SDA = output
              if (USISRL & 0x01)            // If Nack received...
              { // Send stop...
                USISRL = 0x00;
                USICNT |=  0x01;            // Bit counter=1, SCL high, SDA low
                I2C_State = 14;             // Go to next state: generate Stop
                P1OUT |= 0x01;              // Turn on LED: error
              }
              else
              { // Ack received, TX data to slave...
              if(bla){USISRL = Init[Bytecount];}
              else{USISRL = Mod[Bytecount];}
              //USISRL = MST_Data[Bytecount];            // Load data byte
              USICNT |=  0x08;              // Bit counter = 8, start TX
              I2C_State = 10;               // next state: receive data (N)Ack
              Bytecount++;
              P1OUT &= ~0x01;               // Turn off LED
              break;
              }
 } if(Transmit == 0){

              if (USISRL & 0x01)            // If Nack received
              { // Prep Stop Condition
                USICTL0 |= USIOE;
                USISRL = 0x00;
                USICNT |=  0x01;            // Bit counter= 1, SCL high, SDA low
                I2C_State = 8;              // Go to next state: generate Stop
                P1OUT |= 0x01;              // Turn on LED: error
              }
              else{ Data_RX();}             // Ack received


}
              break;

case 6: // Send Data Ack/Nack bit
              USICTL0 |= USIOE;             // SDA = output
              if (Bytecount <= number_of_bytes-2)
              {                             // If this is not the last byte
                USISRL = 0x00;              // Send Ack
                P1OUT &= ~0x01;             // LED off
                I2C_State = 4;              // Go to next state: data/rcv again
                Bytecount++;
                }

              else //last byte: send NACK
              {
                USISRL = 0xFF;              // Send NAck
                P1OUT |= 0x01;              // LED on: end of comm
                I2C_State = 8;              // stop condition
              }
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
              break;

      case 8: // Prep Stop Condition
              USICTL0 |= USIOE;             // SDA = output
              USISRL = 0x00;
              USICNT |=  0x01;              // Bit counter= 1, SCL high, SDA low
              I2C_State = 14;               // Go to next state: generate Stop
              break;

      case 10: // Receive Data Ack/Nack bit
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack bit
              I2C_State = 12;               // Go to next state: check (N)Ack
              break;

      case 12: // Process Data Ack/Nack & send Stop
    	  USICTL0 |= USIOE;
          if (Bytecount == number_of_bytes){// If last byte
          	  USISRL = 0x00;
           	  I2C_State = 14;               // Go to next state: generate Stop
           	  P1OUT |= 0x01;
           	  USICNT |=  0x01;
          }        // set count=1 to trigger next state
          else{
           	  P1OUT &= ~0x01;             // Turn off LED
              Data_TX();                  // TX byte
          }
          break;

      case 14:// 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 xmt
              LPM0_EXIT;                    // Exit active for next transfer
              break;
    }

  USICTL1 &= ~USIIFG;                       // Clear pending flag
}


void Data_TX (void){
    		  if(bla){USISRL = Init[Bytecount];}
    		  else{USISRL = Mod[Bytecount];}
              //USISRL = MST_Data++;          // Load data byte
              USICNT |=  0x08;              // Bit counter = 8, start TX
              I2C_State = 10;               // next state: receive data (N)Ack
              Bytecount++;
}

void Data_RX (void){
	USICTL0 &= ~USIOE;                  // SDA = input --> redundant
        USICNT |=  0x08;                    // Bit counter = 8, RX data
        I2C_State = 6;                      // Next state: Test data and (N)Ack
        P1OUT &= ~0x01;                     // LED off
        }


void Setup_USI_Master_TX (void)
{
  __disable_interrupt();
  Bytecount = 0;
  Transmit = 1;
  USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;  // Port & USI mode setup
  USICTL1 = USII2C+USIIE;                   // Enable I2C mode & USI interrupt
  USICKCTL = USIDIV_7+USISSEL_2+USICKPL;    // USI clk: SCL = SMCLK/128
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
  __enable_interrupt();
}


void Setup_USI_Master_RX (void)
{
  __disable_interrupt();
  Bytecount = 0;
  Transmit = 0;
  USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;  // Port & USI mode setup
  USICTL1 = USII2C+USIIE;                   // Enable I2C mode & USI interrupt
  USICKCTL = USIDIV_7+USISSEL_2+USICKPL;    // USI clks: SCL = SMCLK/128
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
  __enable_interrupt();

}

void Master_Transmit(void){
	Setup_USI_Master_TX();
    USICTL1 |= USIIFG;                      // Set flag and start communication
    LPM0;                                   // CPU off, await USI interrupt
    __delay_cycles(10000);                  // Delay between comm cycles
}
void Master_Recieve(void){
	Setup_USI_Master_RX();
	USICTL1 |= USIIFG;                        // Set flag and start communication
	LPM0;                                     // CPU off, await USI interrupt
	__delay_cycles(10000);                    // Delay between comm cycles
}

**Attention** This is a public forum