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
}