Jump to content
43oh

Interfacing the Launchpad with MAX6956 I2C LED driver


Recommended Posts

As promised here: http://www.43oh.com/forum/viewtopic.php?f=10&t=1015

 

MAX6956 is an I2C LED driver / port expander, here is a demo:

 

/*
*  Interfacing MSP430G2231 to MAX6956 I2C LED driver and I/O expander

Pins   MSP430G2231                  MAX6956
       1 DVCC        -----------   28 V+
       8 P1.6/SCL    -----------   26 SCL
       9 P1.7/SDA    -----------   25 SDA
      14 DVSS        -----------    2 GND    -----------   GND
                                    3 GND    -----------   GND
                                    4 AD0    -----------   GND
                                   27 AD1    -----------   GND  
                                    1 ISET   -/\/39K\/\-   GND
                                   12 P19    -----------   LED1
                                   13 P20    -----------   LED2
                                   14 P21    -----------   LED3
                                    8 P15    ----/ -----   GND

Upon startup, LED1-3 will light up for about 1.5 seconds, then LED2-3 will start glowing intermittently.
While a button on P15 is pushed, LED1 will change brightness. 

*/

#include 

#define PIN_CS      BIT1
#define PIN_SCL     BIT6
#define PIN_SDA     BIT7     
#define DELAY       40000

#define MAX6956_ADDR    0x80
#define ACK         0x00
#define NACK        0xFF

void i2c_init(void)
{
   BCSCTL1 = CALBC1_1MHZ;                                  // Set DCO
   DCOCTL = CALDCO_1MHZ;
   P1REN |= PIN_SCL | PIN_SDA;                             // Enable pullup resistors for I2C termination 
   P1OUT |= PIN_SCL | PIN_SDA;
   USICTL0 = USIPE7 | USIPE6 | USIMST | USISWRST;                     // SDA enable, SCL enable, Master mode, release
   USICTL1 =  USII2C  | USIIE ;  // USICKPH;                   // CKPH = 1, I2C, Interrupt Enable;
   USICKCTL = USIDIV_7 | USISSEL_2 | USICKPL;              // Clock / 128, SMCLK, SCL inactive is high
   USICTL0 &= ~USISWRST;                                    // Release from reset
}

void timer_init(void)
{
   TACTL = TASSEL_2 | MC_0;        // SMCLK, stop timer
   TACCTL0 = CCIE;                 // Enable timer compare interrupt
} 

void sleep(unsigned int count)
{
   TACCR0 = count;             // Load top value in compare register
   TACTL |= TACLR | MC_1;      // Clear counter, start timer in up mode
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   TACTL &= ~MC_1;             // Stop timer
}

void i2c_tx_start(void)
{
   USISRL = 0;
   USICTL0 |= USIGE | USIOE;     // Latch enable, SDA enable
   USICTL0 &= ~USIGE;          // Latch disable
}

void i2c_tx_stop(void)
{
   USICTL0 |= USIOE;           // SDA enable
   USISRL = 0;
   USICNT = 1;                 // Transmit 1 bit
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   USISRL = 0xFF;
   USICTL0 |= USIGE;           // Latch enable
   USICTL0 &= ~(USIGE | USIOE); // Latch disable, SDA disable
}

unsigned char i2c_tx_byte(unsigned char byte)
{
   USICTL0 |= USIOE;
   USISRL = byte;
   USICNT = 8;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   USICTL0 &= ~USIOE;          // SDA disable
   USICNT = 1;                 // Receive ACK bit
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   return USISRL & BIT0;       // Return ACK = first bit of USISRL 
}

unsigned char i2c_rx_byte(void)
{
   unsigned char v;
   USICTL0 &= ~USIOE;
   USICNT = 8;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   v = USISRL;
   return v;
}   

void i2c_tx_ack(unsigned char ack)
{
   USICTL0 |= USIOE;
   USISRL = ack;              // Send ACK/NACK bit
   USICNT = 1;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
}    


void max6956_send(unsigned char addr, unsigned char data)
{
   i2c_tx_start();
   i2c_tx_byte(MAX6956_ADDR);
   i2c_tx_byte(addr);
   i2c_tx_byte(data); 
   i2c_tx_stop();
}

unsigned char max6956_recv(unsigned char addr)
{
   unsigned char v;
   i2c_tx_start();
   i2c_tx_byte(MAX6956_ADDR);
   i2c_tx_byte(addr);
   i2c_tx_stop();
   i2c_tx_start();
   i2c_tx_byte(MAX6956_ADDR | BIT0);
   v = i2c_rx_byte();              // Read and send NACK to stop transmission
   i2c_tx_ack(NACK);
   i2c_tx_stop();
   return v;
}

void sense(void)
{
   static unsigned char g=0;
   if (!(max6956_recv(0x2F) & BIT0))       // Send No-op command and check bit 0 = button pushed
       max6956_send(0x19, g++ << 4);       // Increase brightness of LED on port 19
}   

void leds(unsigned char v)
{
   max6956_send(0x1A, v | (0x0F-v) << 4);  // control brightness of LEDs on ports 20-21 
   sense();
}

void main(void)
{
   signed char i=0;               

   WDTCTL = WDTPW + WDTHOLD;   // Disable WDT
   i2c_init();
   timer_init();
   _enable_interrupts();

   max6956_send(0x0C, 0x00);            // set ports 16-19 to LED
   max6956_send(0x0D, 0x00);            // set ports 20-23 to LED
   max6956_send(0x0B, 0xFF);            // set ports 12-15 to GPIO Input with pullup
   max6956_send(0x33, 0x01);            // Port 19 on
   max6956_send(0x34, 0x01);            // Port 20 on
   max6956_send(0x35, 0x01);            // Port 21 on
   max6956_send(0x07, 0x01);            // Display test on
   _delay_cycles(1500000);     //  ~ 1.5s pause
   max6956_send(0x07, 0x00);            // Display test off
   max6956_send(0x04, BIT0 | BIT6);     // Individual segment current control, normal operation
   for (;
   {
       for (i=0; i<0x10; i++)
       {
           leds(i);
           sleep(DELAY);
       }
       for (i=0x0F; i>=0; i--)
       {
           leds(i);
           sleep(DELAY);
       }
   }
}

#pragma vector=USI_VECTOR
__interrupt void usi_interrupt(void)
{
   USICTL1 &= ~USIIFG;             // Clear interrupt flag
   _low_power_mode_off_on_exit();  // Return from LPM
}

#pragma vector=TIMERA0_VECTOR
__interrupt void timer_A_interrupt(void)
{
   _low_power_mode_off_on_exit();  // Return from LPM
}

Link to post
Share on other sites

Here is a slightly modified version that implements a repeat start on I2C.

 

It is explained here:

http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/105688.aspx

 

/*
*  Interfacing MSP430G2231 to MAX6956 I2C LED driver and I/O expander

Pins   MSP430G2231                  MAX6956
       1 DVCC        -----------   28 V+
       8 P1.6/SCL    -----------   26 SCL
       9 P1.7/SDA    -----------   25 SDA
      14 DVSS        -----------    2 GND    -----------   GND
                                    3 GND    -----------   GND
                                    4 AD0    -----------   GND
                                   27 AD1    -----------   GND  
                                    1 ISET   -/\/39K\/\-   GND
                                   12 P19    -----------   LED1
                                   13 P20    -----------   LED2
                                   14 P21    -----------   LED3
                                    8 P15    ----/ -----   GND

Upon startup, LED1-3 will light up for about 1.5 seconds, then LED2-3 will start glowing intermittently.
While a button on P15 is pushed, LED1 will change brightness. 

*/

#include 

#define PIN_CS      BIT1
#define PIN_SCL     BIT6
#define PIN_SDA     BIT7     
#define DELAY       40000

#define MAX6956_ADDR    0x80
#define ACK         0x00
#define NACK        0xFF

void i2c_init(void)
{
   BCSCTL1 = CALBC1_1MHZ;                                  // Set DCO
   DCOCTL = CALDCO_1MHZ;
   P1REN |= PIN_SCL | PIN_SDA;                             // Enable pullup resistors for I2C termination 
   P1OUT |= PIN_SCL | PIN_SDA;
   USICTL0 = USIPE7 | USIPE6 | USIMST | USISWRST;                     // SDA enable, SCL enable, Master mode, release
   USICTL1 =  USII2C  | USIIE ;  // USICKPH;                   // CKPH = 1, I2C, Interrupt Enable;
   USICKCTL = USIDIV_7 | USISSEL_2 | USICKPL;              // Clock / 128, SMCLK, SCL inactive is high
   USICTL0 &= ~USISWRST;                                    // Release from reset
}

void timer_init(void)
{
   TACTL = TASSEL_2 | MC_0;        // SMCLK, stop timer
   TACCTL0 = CCIE;                 // Enable timer compare interrupt
} 

void sleep(unsigned int count)
{
   TACCR0 = count;             // Load top value in compare register
   TACTL |= TACLR | MC_1;      // Clear counter, start timer in up mode
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   TACTL &= ~MC_1;             // Stop timer
}

void i2c_tx_start(void)
{
   USISRL = 0;
   USICTL0 |= USIGE | USIOE;     // Latch enable, SDA enable
   USICTL0 &= ~USIGE;          // Latch disable
}

void i2c_tx_rpt_start(void)
{
   USICTL0 |= USIOE;           // SDA enable
   USISRL = 0xFF;              // Set MSB of USISRL to high
   USICNT = 1;                 // Transmit 1 bit for a surplus clock cycle
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   i2c_tx_start();
}


void i2c_tx_stop(void)
{
   USICTL0 |= USIOE;           // SDA enable
   USISRL = 0;
   USICNT = 1;                 // Transmit 1 bit
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   USISRL = 0xFF;
   USICTL0 |= USIGE;           // Latch enable
   USICTL0 &= ~(USIGE | USIOE); // Latch disable, SDA disable
}

unsigned char i2c_tx_byte(unsigned char byte)
{
   USICTL0 |= USIOE;
   USISRL = byte;
   USICNT = 8;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   USICTL0 &= ~USIOE;          // SDA disable
   USICNT = 1;                 // Receive ACK bit
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   return USISRL & BIT0;       // Return ACK = first bit of USISRL 
}

unsigned char i2c_rx_byte(void)
{
   unsigned char v;
   USICTL0 &= ~USIOE;
   USICNT = 8;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
   v = USISRL;
   return v;
}   

void i2c_tx_ack(unsigned char ack)
{
   USICTL0 |= USIOE;
   USISRL = ack;              // Send ACK/NACK bit
   USICNT = 1;
   _low_power_mode_0();        // Sleep in LPM0 until interrupt
}    

void max6956_send(unsigned char addr, unsigned char data)
{
   i2c_tx_start();
   i2c_tx_byte(MAX6956_ADDR);
   i2c_tx_byte(addr);
   i2c_tx_byte(data); 
   i2c_tx_stop();
}

unsigned char max6956_recv(unsigned char addr)
{
   unsigned char v;
   i2c_tx_start();
   i2c_tx_byte(MAX6956_ADDR);
   i2c_tx_byte(addr);
   i2c_tx_rpt_start();             // Generate a repeat start
   i2c_tx_byte(MAX6956_ADDR | BIT0);
   v = i2c_rx_byte();              // Read and send NACK to stop transmission
   i2c_tx_ack(NACK);
   i2c_tx_stop();
   return v;
}

void sense(void)
{
   static unsigned char g=0;
   if (!(max6956_recv(0x2F) & BIT0))       // Send No-op command and check bit 0 = button pushed
       max6956_send(0x19, g++ << 4);       // Increase brightness of LED on port 19
}   

void leds(unsigned char v)
{
   max6956_send(0x1A, v | (0x0F-v) << 4);  // control brightness of LEDs on ports 20-21 
   sense();
}

void main(void)
{
   signed char i=0;               

   WDTCTL = WDTPW + WDTHOLD;   // Disable WDT
   i2c_init();
   timer_init();
   _enable_interrupts();

   max6956_send(0x0C, 0x00);            // set ports 16-19 to LED
   max6956_send(0x0D, 0x00);            // set ports 20-23 to LED
   max6956_send(0x0B, 0xFF);            // set ports 12-15 to GPIO Input with pullup
   max6956_send(0x33, 0x01);            // Port 19 on
   max6956_send(0x34, 0x01);            // Port 20 on
   max6956_send(0x35, 0x01);            // Port 21 on
   max6956_send(0x07, 0x01);            // Display test on
   _delay_cycles(1500000);     //  ~ 1.5s pause
   max6956_send(0x07, 0x00);            // Display test off
   max6956_send(0x04, BIT0 | BIT6);     // Individual segment current control, normal operation
   for (;
   {
       for (i=0; i<0x10; i++)
       {
           leds(i);
           sleep(DELAY);
       }
       for (i=0x0F; i>=0; i--)
       {
           leds(i);
           sleep(DELAY);
       }
   }
}

#pragma vector=USI_VECTOR
__interrupt void usi_interrupt(void)
{
   USICTL1 &= ~USIIFG;             // Clear interrupt flag
   _low_power_mode_off_on_exit();  // Return from LPM
}

#pragma vector=TIMERA0_VECTOR
__interrupt void timer_A_interrupt(void)
{
   _low_power_mode_off_on_exit();  // Return from LPM
}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...