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 }