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.

MSP430F5659 and PCU9656 led driver over I2C

Other Parts Discussed in Thread: MSP430F5659

Ok so im using the PCU9656 Led Driver over I2C.  The adress is set via hardwear and it is not a reserved address when i had no ack at all i wrote a program to send the address to every address one by one to see what acked.  well after consulting the user manual again for the led driver i believe it doesnt ack in fact on some examples where you would expect it to pull low for an ack it points out that that bite is always a 1.  so heres my issue.  The msp430F5659 doesnt seem to allow me to keep sending when the address doesnt ack.  it sets UCTXNACK to 0 and UCNACKIFG to 1.  This also seems to drop whatever is in the tx buffer and send a stop condition over the bus.  I need to know what to do about this where i can send the address and bytes without caring if there is a nack after the address or the bytes...   Any help will be greatly appriceated.

  • Also here is a screen shot from the PCU9656 of an example. notice the 9th bite that should be pulled low for an ack or left high for a nack....  thats my problem is that this led driver seems to always leave it high and the MSP430 doesnt like that.

  • The UFm I2C receiver does not acknowledge the reception of data.

    While the USCI needs this acknowledge (which cannot be disabled) the USCI cannot be used to transmit UFm I2C.

     

    But on the other hand, the UFm I2C Slave is a receive only, which makes it easy to write a small piece of transmitter software, and can be outputted on any GPIO pin (no need for open-collector) without pull-up resistors, maybe in case of long bus wires some kind of termination may be necessary.

     

    Generate a START condition (CLK high and SDA to low) for each byte to transmit (including the first address byte), shift out the 8-data bits (MSB first) + one extra ‘1’ bit and generate 9 CLK pulses, no time delay necessary. When all bytes are transferred generate a STOP condition (CLK high and SDA to high).

  • Thank you thats exactly what i expected. My plane now is to change to port mapping by entering in a veriable to the port mapping function so i can use the same pins as is being used for other devices on my i2c bus.  i understand the i2c protocol very well and i know the sda only changes when the clk line is low that being said if you have any advice on bit banging and keeping two lines in sink for this feel free to let me know and thank you.

       Robert

  • i have come across a program to bit bang but to include it in my program im having some issues in the header file there are some defines and i would like these pins to be SDA P2.0 and SCL to be P2.1 ill post the header and anything else please tell me what you think.  

    the first 8 defines is what im worried about and in case it helps ill post the .c file after

    #ifndef TWI_MASTER_H_
    #define TWI_MASTER_H_

    //#include "ioavr.h"
    //#include "inavr.h"

    /*! \brief Definition of pin used as SCL. */
    #define SCL

    /*! \brief Definition of pin used as SDA. */
    #define SDA

    /*! \brief Definition of PORT used as SCL. */
    #define PORT_SCL
    /*! \brief Definition of DDR used as SCL. */
    #define DDR_SCL
    /*! \brief Definition of PIN used as SCL. */
    #define PIN_SCL
    /*! \brief Definition of PORT used as SDA. */
    #define PORT_SDA
    /*! \brief Definition of DDR used as SDA. */
    #define DDR_SDA
    /*! \brief Definition of PIN used as SDA. */
    #define PIN_SDA

    /*! \brief Slave 8 bit address (shifted). */
    #define SLAVE_ADDRESS 0x1D

    #define READ_SDA() (PIN_SDA & (1 << SDA))
    #define SET_SDA_OUT() DDR_SDA |= (1 << SDA)
    #define SET_SDA_IN() DDR_SDA &= ~(1 << SDA)
    #define READ_SCL() (PIN_SCL & (1 << SCL))?1:0

    #define WRITE 0x0
    #define READ 0x1

    /*! \brief Delay used to generate clock */
    #define DELAY 2

    /*! \brief Delay used for STOP condition */
    #define SCL_SDA_DELAY 1

    void twi_disable();
    void twi_init();
    void toggle_scl();
    void write_scl(char x);
    char twi_start_cond(void);
    char send_slave_address(unsigned char read);
    char write_data(unsigned char* data, char bytes);
    char i2c_write_byte(unsigned char byte);
    char read_bytes(unsigned char* data, char bytes);
    char i2c_read_byte(unsigned char* data, unsigned char bytes, unsigned char index);
    void write_sda( char x);

    #endif /* TWI_MASTER_H_ */

    ---------------------------------------------------------------------------

    .c file

    #include "TWI_master.h"

    /*! \brief initialize twi master mode
    */
    void twi_init()
    {
    DDR_SCL |= (1 << SCL);
    DDR_SDA |= (1 << SDA);

    write_sda(1);
    write_scl(1);

    }

    /*! \brief disables twi master mode
    */
    void twi_disable()
    {
    DDR_SCL &= ~(1 << SCL);
    DDR_SDA &= ~(1 << SDA);

    }

    /*! \brief Sends start condition
    */
    char twi_start_cond(void)
    {
    write_sda(0);
    __delay_cycles(DELAY);

    write_scl(0);
    __delay_cycles(DELAY);
    return 1;

    }

    /*! \brief Sends slave address
    */
    char send_slave_address(unsigned char read)
    {
    return i2c_write_byte(SLAVE_ADDRESS | read );
    }

    /*! \brief Writes data from buffer.
    \param indata Pointer to data buffer
    \param bytes Number of bytes to transfer
    \return 1 if successful, otherwise 0
    */

    char write_data(unsigned char* indata, char bytes)
    {
    unsigned char index, ack = 0;

    if(!twi_start_cond())
    return 0;
    if(!send_slave_address(WRITE))
    return 0;

    for(index = 0; index < bytes; index++)
    {
    ack = i2c_write_byte(indata[index]);
    if(!ack)
    break;
    }
    //put stop here
    write_scl(1);
    __delay_cycles(SCL_SDA_DELAY);
    write_sda(1);
    return ack;

    }


    /*! \brief Writes a byte on TWI.
    \param byte Data
    \return 1 if successful, otherwise 0
    */
    char i2c_write_byte(unsigned char byte)
    {
    char bit;
    for (bit = 0; bit < 8; bit++)
    {
    write_sda((byte & 0x80) != 0);
    toggle_scl();//goes high
    __delay_cycles(DELAY);
    toggle_scl();//goes low
    byte <<= 1;
    __delay_cycles(DELAY);
    }
    //release SDA
    SET_SDA_IN();
    toggle_scl(); //goes high for the 9th clock
    //Check for acknowledgment
    if(READ_SDA())
    {
    return 0;
    }
    __delay_cycles(DELAY);
    //Pull SCL low
    toggle_scl(); //end of byte with acknowledgment.
    //take SDA
    SET_SDA_OUT();
    __delay_cycles(DELAY);
    return 1;

    }
    /*! \brief Reads data into buffer.
    \param data Pointer to data buffer
    \param bytes Number of bytes to read
    \return 1 if successful, otherwise 0
    */
    char read_bytes(unsigned char* data, char bytes)
    {
    unsigned char index,success = 0;
    if(!twi_start_cond())
    return 0;
    if(!send_slave_address(READ))
    return 0;
    for(index = 0; index < bytes; index++)
    {
    success = i2c_read_byte(data, bytes, index);
    if(!success)
    break;
    }
    //put stop here
    write_scl(1);
    __delay_cycles(SCL_SDA_DELAY);
    write_sda(1);
    return success;


    }

    /*! \brief Reads one byte into buffer.
    \param rcvdata Pointer to data buffer
    \param bytes Number of bytes to read
    \param index Position of the incoming byte in hte receive buffer
    \return 1 if successful, otherwise 0
    */
    char i2c_read_byte(unsigned char* rcvdata, unsigned char bytes, unsigned char index)
    {
    unsigned char byte = 0;
    unsigned char bit = 0;
    //release SDA
    SET_SDA_IN();
    for (bit = 0; bit < 8; bit++)
    {
    toggle_scl();//goes high
    if(READ_SDA())
    byte|= (1 << (7- bit));
    __delay_cycles(DELAY);
    toggle_scl();//goes low
    __delay_cycles(DELAY);
    }
    rcvdata[index] = byte;
    //take SDA
    SET_SDA_OUT();
    if(index < (bytes-1))
    {
    write_sda(0);
    toggle_scl(); //goes high for the 9th clock
    __delay_cycles(DELAY);
    //Pull SCL low
    toggle_scl(); //end of byte with acknowledgment.
    //release SDA
    write_sda(1);
    __delay_cycles(DELAY);
    }
    else //send NACK on the last byte
    {
    write_sda(1);
    toggle_scl(); //goes high for the 9th clock
    __delay_cycles(DELAY);
    //Pull SCL low
    toggle_scl(); //end of byte with acknowledgment.
    //release SDA
    __delay_cycles(DELAY);
    }
    return 1;

    }
    /*! \brief Writes SCL.
    \param x tristates SCL when x = 1, other wise 0
    */
    void write_scl (char x)
    {
    if(x)
    {
    DDR_SCL &= ~(1 << SCL); //tristate it
    //check clock stretching
    while(!READ_SCL());
    }
    else
    {
    DDR_SCL |= (1 << SCL); //output
    PORT_SCL &= ~(1 << SCL); //set it low

    }
    }

    /*! \brief Writes SDA.
    \param x tristates SDA when x = 1, other wise 0
    */
    void write_sda (char x)
    {
    if(x)
    {
    DDR_SDA &= ~(1 << SDA); //tristate it
    }
    else
    {
    DDR_SDA |= (1 << SDA); //output
    PORT_SDA &= ~(1 << SDA); //set it low

    }
    }
    /*! \brief Toggles SCL.
    */
    void toggle_scl()
    {
    if(PIN_SCL & (1<<SCL))
    {
    DDR_SCL |= (1 << SCL); //output
    PORT_SCL &= ~(1 << SCL); //set it low
    }
    else
    {
    DDR_SCL &= ~(1 << SCL); //tristate it
    while(!READ_SCL());
    }
    }

  • I would not share the UFm I2C with the classic bus, the electrical specifications are too different and why not having two (different) I2C busses.

    I wrote some code, try if this works;

    #include <msp430.h> 
    
    
    #define I2C_OUT	P8OUT
    #define I2C_DIR	P8DIR
    #define	USDA	BIT1
    #define USCL	BIT2
    #define Slave	0x10	// Slave address 10h
    
    unsigned char	Data[100];
    
    void MasterTransmit (unsigned char Address, unsigned char* Data, unsigned int Number);
    
    
    void main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
    	I2C_OUT |= USDA + USCL;
    	I2C_DIR |= USDA + USCL;
    
    	while (1)
    	{
    		MasterTransmit(Slave, Data, 100);
    
    		// Break
    	    __no_operation();
    	}
    }
    
    void TransmitByte (unsigned char Value)
    {
    	unsigned char	c;
    	unsigned int	i;
    	
    	// Add 9th bit
    	i = ((unsigned int)Value<<1) +1;
    
    	for (c=9; c>0; c--)
    	{
    		// Set SCL low
    		I2C_OUT &= ~USCL;
    
    		// Set bit state
    		if ((i & 0x0100) != 0) {I2C_OUT |= USDA;} else {I2C_OUT &= ~USDA;}
    		// Rotate bits
    		i <<= 1;
    
    		// Set SCL high
    		I2C_OUT |= USCL;
    	}
    
    	// Exit with SCL low
    	I2C_OUT &= ~USCL;
    
    } void MasterTransmit (unsigned char Address, unsigned char* Data, unsigned int Number) { unsigned int i; unsigned char* p; // Set START condition I2C_OUT |= USCL + USDA; I2C_OUT &= ~USDA; // Transmit address // Strip bit 0 TransmitByte((Address<<1) & 0xFE); // Transmit data p = Data; for (i=Number; i>0; i--) {TransmitByte(*p++);} // Set STOP condition I2C_OUT &= ~USDA; I2C_OUT |= USCL; I2C_OUT |= USDA; }

      Edit: Line 45 corrected

  • Thank you this seems to work.  on my chip the SCL line runs about 75.3 kHz  and the start condition seems to bounce a little.  im not sure if for the LED driver im using if ill need to generate an extra clock pulse in between bytes or if they will need to squeeze together as one long data stream (including the nack bite of course) but ill find out soon.  if you find time   I wouldn't mind getting some details on your code.  i understand the majority of it but have a couple of questions so that i understand it well.  

     In the MasterTransmit when you call TransmiteByte for the address i understand why and what your doing when you left shift it but not sure why theirs the and operator and FEh,

    In the TransmiteByte function can you explain the line where you set i equal to what it is and why the if statement is and'ed with 100h...   im assuming your accomplishing a check of the next bite one bite at a time but im just not seeing how it works exactly.

    again thank you very much and don't feel obligated to explain that stuff to me if you don't want too.

    Robert

  • After posting yesterday I changed the code today a little bit, it looks like you are using the latest version. I don’t have this device but put it on the G2xx EVM and test it with a scoop. Changed line: 45, 63 and 68, Added line: 54.

    Another case is the timing between sending a ‘0’ or a ‘1’ is a little bit different, there is a jump instruction after clearing the port bit, this will be not a problem at all but I hate such things. So I add after I2C_OUT |= USDA; 2 NOP’s and now its equal (until the optimizer change the order).

    Robert Breitenstein said:
     In the MasterTransmit when you call TransmiteByte for the address i understand why and what your doing when you left shift it but not sure why theirs the and operator and FEh,

    Originally I did this to strip bit 7 which is not part of the address but while Value is a byte, the shift moves out bit 7. After the left shift bit 0 is the R/W bit and should be ‘0’, there are CPU’s you have a rotate op-code where you can shifts in a ‘1’ and C (if you don’t take care) can use the rotate in stat of the shift op-code, but I believe MSP430 doesn’t have this feature and not even a shift (I never invest much time to search for it). So this is just to be sure, and as long the address is a constant it doesn’t waist code.

     

    Robert Breitenstein said:
    In the TransmiteByte function can you explain the line where you set i equal to what it is and why the if statement is and'ed with 100h...   im assuming your accomplishing a check of the next bite one bite at a time but im just not seeing how it works exactly.

    We have to send 8 data bits + 1 acknowledge bit, therefore I create a 9-bit word with bit 0 always ‘1’. Would we have this rotate op-code we can easily rotate-left out the bits to transmit, but instead we have to do it with the shift function. MSB goes first so bit-8 has to be compared and transmitted now, after this I shift the remaining bits (0-7) one place left so bit-7 becomes bit-8 and to be compared and transmitted next.

  • Robert Breitenstein said:
    i would like these pins to be SDA P2.0 and SCL to be P2.1

    #define SDA 0
    #define SCL 1
    #define PORT_SCL P2OUT
    #define DDR_SCL P2DIR
    #define PIN_SCL P2IN
    #define PORT_SDA P2OUT
    #define DDR_SDA P2DIR
    #define PIN_SDA P2IN

    I’d also change these:

    #define READ_SDA() ((PIN_SDA>>SDA)&1)
    #define READ_SCL() ((PIN_SCL>>SCL)&1)

  •   Thank you very much you have been most helpful im using your program with just changing the pins im using and it works iv had the led driver do lots of things already for a test function iv made and it works great...  i hate that the msp430f5659 wont work with the driver using i2c normally and had to use a "bit bang" method like in your code.  but as part of the function i can change the port mapping for the pins im using just long enough to use your method so i don't think that will be an issue.

     also the led driver im using has one annoying attribute for a intern such as myself where to turn on or off the led's i have to send a command over i2c which is an array of 6 bytes. and only two bits in each bite corresponds to a led collor (it is a rgb led where the driver was made for red green blue amber led's so there is not the same led per bite there is 1 to 3 max in a bite and another led pin in the same bite)  to make such a big program as im writing and for it to be easy and smaller to use and write i need to make a function that when the function is called i can enter simply the led number , color,  brightness, and a one or a zero for on or off.  This was easy to write the function except one part....  im writing another function to use inside of it that is ment to change one single bit in an array of 6 bytes  so that it can change the led...  every other part is correct and works fine except the function to change the correct bit in exactly what byte im trying to change in the array that gets then updated to the driver..    if you have a simple explanation of how to make a function to change one bit in an array of 6 bites i wouldn't be upset if you posted it.  either way thank you allot for your help.

    Jens-Michael Gross,  thank you for your answer on what i would need to change for the other code i was wondering about i tried the first 8 changes to the #defines exactly as you have them and it didn't seem to work most likely cause i had something else wrong. perhaps when i have more time ill try again to see if it works thank you for your help as well but for the actual project im doing i will be using Leo Bosch's suggestions.

  • Good to hear it works perfect.

    I don’t exactly understand your question, maybe you can give some more; hardware detail, point to the case in the manual and/or give a piece of your software and what the 6-bytes are containing.

     

    To Set or Clear a bit, you could use this;

    void UpdateBitByte (unsigned char Bit, unsigned char* Byte, unsigned char Value)
    {
    	unsigned char mask = (0x01<<Bit);
    
    	if (Value == 0) {*Byte &= ~mask;} else {*Byte |= mask;}
    }
    

     

  • Robert Breitenstein said:
     i hate that the msp430f5659 wont work with the driver using i2c normally

    If TI would create a new eeUSCI module and add a NACK enable bit it would be UFm-I2C compatible (except for the 5V tolerant on not 51xx devices).

  • well my code is at work and im home for the weekend but my array looks something like this 

    unsigned char LedState[7] = 

    {

    0x9D,

    0xAA,

    0xAA,

    0xAA,

    0xAA,

    0xAA,

    0xAA

    };

    Each byte controlls 4 pins to turn on off or on where pwm is enabled if the two pits associated with the pin is 00 for off 10 for on with pwm and 01 is just on with no control. AAh being 10101010 has the 4 assosiated pins on with pwm control.  now AAh has every pin on with pwm control so it makes white (pwm is another array that gets sent i already have it updated each time my function runs) what i need now is to turn on or off a single bit in any bite.  i have something somewhat written a little like yours i can post tomorrow but it changes the wrong bits.  Will yours update the bit i specify in Bit, in the byte i specify in Byte to that value i want...   in my array of course?  if so thats exactly what i would need then at the end of my function i have it send that array to the driver to update but thats easy.    

  • also this is what i first tryed but couldnt get it to work and update a single bite in my array

    void WriteBit(unsigned char *pszData,unsigned char byBitNo,unsigned char byBit)

    {

       if(byBit)

          pszData[byBitNo>>3] |= 0x80 >> (byBitNo & 0x07);

       else

          pszData[byBitNo>>3] &= ~(0x80 >> (byBitNo & 0x07 ));

    }

  • You mean something like this;

    typedef enum LED_States {
    	LED_Off			= 0,
    	LED_FullyOn		= 1,
    	LED_Dimmed		= 2,
    	LED_DimmedBlink	= 3
    } LED_States;
    
    void SetLEDstate (unsigned char LEDno, LED_States ToState, unsigned char* InArray)
    {
    	// LEDno can be omitted if InArray directly points to the right place.
    
    	unsigned char c, mask = 0;
    
    	for (c=0; c<8; c += 2)
    	{
    		mask |= (ToState<<c);
    	}
    
    	InArray[LEDno] &= mask;
    	InArray[LEDno] |= mask;
    }
    

  • sorry but im not sure im fallowing exactly if this will work then good deal but i might need you to explain it to me.  just to be sure though LED number would be like the two bites in the array that control the LED...  honestly out of the two i only care about the most significant cause it can be controlled and my over all function takes care of brightness which is another array that i have no problem with.  so for the array i have to send to the driver is

     

    unsigned char LedState[7] = 

    {

    0x9D,    // this being the address of the register and an auto increment flag so this never changes.

    0xAA,  // this bite has 4 led's it controlls ever two zeros is one LED so all 4 leds are on and controlled by pwm

    0xAA,//  beacuse they are 10   so if i want to turn an led on or off i need to change say the first 1 in 10101010 to 

    0xAA, // 00101010 to turn that one off and so on and all of this is just one byte all the bytes under 0x9D control 

    0xAA, //4 led's

    0xAA,

    0xAA

    };

    so if i wanted to turn off 2 led's specifically a certen two i may have to send

    unsigned char LedState[7] = 

    {

    0x9D,

    0x2A,  //  one bite was changed for an led the first led

    0xA2,//  then another one bite was changed for the next led i wanted to change out of the 4 this byte represents

    0xAA,

    0xAA,

    0xAA,

    0xAA

    };

    so i have a function already written that i enter the led number, color, pwm value, and a 1 or 0 for on and off

    inside the function there is a switch statement and if statements so if its led 1 and its to be turned on inside of that if statement i need a function to say change that one bit in that one byte in the array that i posted earlyer....   i would of just had it give the value you would expect if that led would be turned on but it would turn on or off other led's to change the whole byte.  in my global array ledstate

    ill test out your function out in a few min but may need some things explained like is InArray supposed to represent my array? and if so LEDno would i think be the byte that needs to get changed but i dont think it points out the bite to actually change.  

    i apologize if im frustrating i tend to understand a lot in c programming and can normally get anything to work just id hate to have to do it the hard way and do a crazy amount more if statements just to check the bytes and change the whole value when there are ways to just change one bite at a time. 

    i really do appreciate you help and patience.

  • ok i apologize i was given a function that didnt work for what i wanted and now i found my answer im sure yours worked fine but really all i needed was

    LedState[x] |= (1 << n);

    LedState[x] &= ~(1 << n);

    x being the byte in my array and n being the bit i needed to change. i haven't done much with individual bits changed this way and was led to believer it would take a special function. shows how i still don't have a ton of experience... with these in my function i will be able to accomplish my goal and everything should work fine as iv tested this on code composer at home and it should do exactly what i want i do thank you for your help.
  • Leo Bosch said:
    typedef enum LED_States { LED_Off = 0, LED_FullyOn = 1, LED_Dimmed = 2, LED_DimmedBlink = 3 } LED_States; void SetLEDstate (unsigned char LEDno, LED_States ToState, unsigned char* InArray) { // LEDno can be omitted if InArray directly points to the right place. unsigned char c, mask = 0; for (c=0; c<8; c += 2) { mask |= (ToState<<c); } InArray[LEDno] &= mask; InArray[LEDno] |= mask; }

    These are just brain-waves. Now I took a closer look to the Driver manual and wrote this piece of code, compare it with yours and take what you can use.

    Assuming 1x PCU9656 drivers each driving 8x RGB LED units.

    // UFm I2C
    #define TX_BufferLenght			7	// Max Register address + 24 x PWM
    
    // PCU9656 Driver
    #define FirstDriverAddress		0
    #define nDrivers				1
    #define nDriverLEDunits			8
    #define StateRegisterAddress	0x1D
    
    // LED Units
    #define nLEDunitItems			3	// 1-4, 3=RGB
    #define nLEDunits				(nDrivers*nDriverLEDunits)
    
    
    typedef enum LED_StateTypes {
    	LED_Off			= 0,
    	LED_FullyOn		= 1,
    	LED_Dimmed		= 2,
    	LED_DimmedBlink	= 3
    } LED_StateTypes;
    
    typedef struct LEDunitObject {
    	LED_StateTypes	State[nLEDunitItems];
    	//unsigned char	PWM[nLEDunitItems];
    } LEDunitObject;
    
    typedef struct TX_BufferObject {
    	unsigned char	Array[nDrivers][TX_BufferLenght];
    	unsigned char	Count;
    } TX_BufferObject;
    
    

    LEDunitObject	LEDunitBus[nLEDunits];
    TX_BufferObject	TX_Buffer;
    
    
    void LEDinit (void)
    {
    	unsigned char	c, cc, test = 0;
    
    	for (c=0; c<nLEDunits; c++)
    	{
    		for (cc=0; cc<nLEDunitItems; cc++)
    		{
    			LEDunitBus[c].State[cc] = (LED_StateTypes)((test++) & 0x03);	// Just for test, normally 0
    		//	LEDunitBus[c].PWM[cc] = 0;
    		}
    	}
    }
    
    void PrepareLEDstateTXbuffer (void)
    {
    	unsigned char	c, cc;
    	for (c=0; c<nDrivers; c++)
    	{
    		TX_Buffer.Array[c][0] = (StateRegisterAddress | 0x80);	// + Auto-Increment
    
    		for (cc=1; cc<TX_BufferLenght; cc++)
    		{
    			TX_Buffer.Array[c][cc] = 0;
    		}
    	}
    
    	TX_Buffer.Count = 7;
    }
    
    void PrepareLEDstateToTX (void)
    {
    	unsigned char	driver, LEDunit, busIndex, item, stateIndex, stateByte, stateGroup;
    	unsigned char*	buffer;
    
    	PrepareLEDstateTXbuffer();
    
    	for (driver=0; driver < nDrivers; driver++)
    	{
    		buffer = &TX_Buffer.Array[driver][1];
    
    		for (LEDunit=0; LEDunit < nDriverLEDunits; LEDunit++)
    		{
    			busIndex = (driver +1) * LEDunit;
    
    			for (item=0; item < nLEDunitItems; item++)
    			{
    				stateIndex = ((LEDunit * nLEDunitItems) + item);
    				stateByte = stateIndex /4;
    				stateGroup = (stateIndex %4) *2;
    
    				buffer[stateByte] |= (LEDunitBus[busIndex].State[item]<<stateGroup);
    			}
    		}
    	}
    }
    
    void TransmitLEDstate (void)
    {
    	unsigned char	driver, address = FirstDriverAddress;
    
    	for (driver=0; driver < nDrivers; driver++)
    	{
    		MasterTransmit(address++, &TX_Buffer.Array[driver][0], TX_Buffer.Count);
    	}
    }
    

     

  • yes alot like that thank you i already got the one i was working on to work right after my last post but my code is longer and probably more inefficient then yours ill have to try it

  •   thank you for helping me so much before im still using the code your wrote to transmit I2C  i now for something else have to come up with a receive function and store what is received into a array...  i know id have to send the slave address with a r/w bit of 1. then get whatever comes through but im not sure how to do that right off any ideas how to write a receive function from what youv got.  also i know the led driver wont ever talk this will be for something else on the i2c line.  any help will be greatly appreciated.

     

    also the code im talking about that im using is the one your wrote several posts back

     

    #include <msp430.h>
    #define I2C_OUT P8OUT
    #define I2C_DIR P8DIR
    #define USDA    BIT1
    #define USCL    BIT2
    #define Slave   0x10    // Slave address 10h
    unsigned char   Data[100];
    void MasterTransmit (unsigned char Address, unsigned char* Data, unsigned int Number);
    void main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
        I2C_OUT |= USDA + USCL;
        I2C_DIR |= USDA + USCL;
        while (1)
        {
            MasterTransmit(Slave, Data, 100);
            // Break
            __no_operation();
        }
    }
    void TransmitByte (unsigned char Value)
    {
        unsigned char   c;
        unsigned int    i;
        
        // Add 9th bit
        i = ((unsigned int)Value<<1) +1;
        for (c=9; c>0; c--)
        {
            // Set SCL low
            I2C_OUT &= ~USCL;
            // Set bit state
            if ((i & 0x0100) != 0) {I2C_OUT |= USDA;} else {I2C_OUT &= ~USDA;}
            // Rotate bits
            i <<= 1;
            // Set SCL high
            I2C_OUT |= USCL;
        }
        // Exit with SCL low
        I2C_OUT &= ~USCL;
    }
    void MasterTransmit (unsigned char Address, unsigned char* Data, unsigned int Number)
    {
        unsigned int    i;
        unsigned char*  p;
        // Set START condition
        I2C_OUT |= USCL + USDA;
        I2C_OUT &= ~USDA;
        // Transmit address
        // Strip bit 0
        TransmitByte((Address<<1) & 0xFE);
        // Transmit data
        p = Data;
        for (i=Number; i>0; i--) {TransmitByte(*p++);}
        // Set STOP condition
        I2C_OUT &= ~USDA;
        I2C_OUT |= USCL;
        I2C_OUT |= USDA;
    }

     

**Attention** This is a public forum