Jump to content
43oh

Recommended Posts

Hello.

 

im trying to read from the i2c port on my g2231, i have found a i2c libary from this website link

but as I see the libary dont support repeated start. I have tried to add this, with some code I found on this forum.

im trying to read from a expander ic MCP23016. but the only thing I read is 0xFF ?. im able to write to the expander ic with no problem.

its the first time i work with i2c. thanks for looking :)

 

I have added the full code to.

 

void main(void) {
	WDTCTL = WDTPW + WDTHOLD;
	__delay_cycles(500000);
	i2c_init(); // startup i2c

	exint(); // init the expander ic

	lcdint(); // init the lcd display on the expander ic 

	lcdsendd(0x48); // H
	lcdsendd(0x45); // E
	lcdsendd(0x4C); // L
	lcdsendd(0x4C); // L
	lcdsendd(0x4F); // O

 ////////////////////////////////////// reading ///////////////////////////////////////////////
	i2c_start();
	i2c_write8(0x20 << 1);  // expander ic port write 
	i2c_write8(0x01);  // point on port 1
	i2c_rpt(); // repeated start bit 
	i2c_write8(0x21 << 1); // the read address
	readreg = i2c_read8(0x00); 
	readreg = i2c_read8(0x00);
	i2c_stop();


	lcdsendd(readreg); // write the output the the lcd display. 
	lcdsendd(readreg1);

 

this is the i2c libary

 

//code adapted from http://www.43oh.com/forum/viewtopic.php?f=9&t=139
//Kerry D. Wong
//http://www.kerrywong.com

#include "i2c.h"
#include <msp430g2231.h>

#define SDA  BIT7 //P1.7
#define SCL  BIT6 //P1.6
#define LED  BIT0 //P1.0

void i2c_init(void)
{
    P1DIR |= SCL | SDA | LED; // Set SCL, SDA and LED as Output
    P1REN |= SCL | SDA; // Set Pull-Ups on SCL and SDA

    // enable SDA, SCL, SCLK, i2c mode, MSB, output enabled, hold in reset
    USICTL0 = USIPE7 | USIPE6 | USIMST | USIOE | USISWRST;

    // USICTL0 Upper 8bit Register of 16bit USICTL Register
	// USIPE7   = P1.7 USI Mode, i2c SDA enabled
	// USIPE6   = P1.6 USI Mode, i2c SCL enabled
	// USIPE5   = P1.5 USI Mode, i2c Clock Input? (Not Set)
	// USILSB   = LSB Mode (Not Set = MSB)
	// USIMST   = Master Mode
	// USIGE    = Output Latch (Not Set = Clock Controlled)
	// USIOE    = Data Output Enable
	// USISWRST = USI Software Reset (Set to allow changing settings)

    // SMCLK / 4, and Reverse Clock Polarity
    USICKCTL = USIDIV_2 + USISSEL_2 + USICKPL;

    // USICKCTL 8bit USI Clock Control Register
	// USIDIVx  = Clock Divider (Bit7-5, USIDIV_2 = Divide by 4)
	// USISSELx = Clock Source (For Master Mode, Bit4-2, USISSEL_2 = SMCLK)
	// USICKPL  = Clock Polarity (0 = Inactive Low, 1 = Inactive High)
	// USISWCLK = Software Clock State

    // I2C Mode
    USICTL1 = USII2C;

    // USICTL1 Lower 8bit Register of 16bit USICTL Register
	// USICKPH   = Clock Phase (0 = Data Changed, then Captured, 1 = Data Captured, then Changed)
	// USII2C    = I2C mode
	// USISTTIE  = START condition Interrupt
	// USIIE     = USI Counter Interrupt
	// USIAL     = Arbitration Lost Notification
	// USISTP    = STOP condition Notification
	// USISTTIFG = START condition Int. Flag
	// USIIFG    = USI Counter Int. Flag

    // release from reset
    USICTL0 &= ~USISWRST;
}

void i2c_start(void)
{
    P1OUT |= LED;  // Turn P1.0 Led on

    // Send i2c START condition
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c START
    USICTL0 |= USIGE | USIOE; // Force Output Latch, And Enable Data Output Bit (High to Low SDA while SCL is High)
    USICTL0 &= ~USIGE; // Clear Output Latch (Return to Clock Control)
}

void i2c_stop(void)
{
	// Prepare i2c STOP condition
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c STOP
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

    // Send i2c STOP condition
    USISRL = 0xFF; // Load USISRL Lower Byte Shift Register MSB with 1 for i2c STOP
    USICTL0 |= USIGE; // Force Output Latch (Low to High SDA while SCL is High)
    USICTL0 &= ~USIOE & ~USIGE ; // Clear Data Output Enable Bit and Output Latch (Release SCL)

    P1OUT &= ~LED; // Turn P1.0 Led off
}

unsigned char i2c_write8(unsigned char c)
{
// TX
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = c; // Load USISRL Lower Byte Shift Register with 8 Bit data (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// RX
    // Data TXed. Ready to Receive (n)ACK from i2c Slave
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USICNT = 1; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    c = USISRL; // LSB of USISRL Holds Ack Status of 0 = ACK (0x00) or 1 = NACK (0x01)
    return c;
}

unsigned char i2c_read8(unsigned char acknack)
{
// RX
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USISRL = 0x00; // Clear USISRL Lower Byte Shift Register (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Copy Data to c
    unsigned char c;
    c = USISRL; // USISRL Holds Received Data

// TX
    // Data RXed. Ready to Send (n)ACK to i2c Slave
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = acknack; // Load USISRL Lower Byte Shift Register MSB with acknack (0x00 = Ack, 0xFF = Nack)
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    return c;
}

void i2c_rpt(void)
{
	  USICTL0 |= USIOE;
	  USISRL = 0xFF;
	  USICNT = 1;


	  while ( ( USICTL1 & USIIFG ) != 0x01 );
	  USICTL1 &= ~USIIFG; // likely not needed


	  __delay_cycles( 100 );


	  USISRL = 0x00;
	  USICTL0 |= USIGE + USIOE;
	  USICTL0 &= ~USIGE;


	  __delay_cycles( 100 );
}

 

i2c.c

i2c.h

main.c

Link to post
Share on other sites

I wrote that i2c. Never got a chance to look into proper last read nacking, or repeated start. For the most part, it isn't needed.

 

I just send a second start without a stop, and some chips respond fine. One chip I used that on did not like it (read out all 0xff). So the fall back was simply sending a stop and a start.

 

A i2c Repeated Start is really intended for multimaster systems, where something else might take control of the bus before your master gets/writes the information it needs. A repeated start and a stop + start are treated the same way by slave devices.

 

Also, this jumped out at me

i2c_write8(0x20 << 1);  // expander ic port write
i2c_write8(0x01);  // point on port 1
i2c_rpt(); // repeated start bit
i2c_write8(0x21 << 1); // the read address

 

From the datasheet, a 7bit write address of 0x20 (0b0100000) [Assuming you have A0,A1,A2 grounded] shifted 1 to the left would be a 8 bit address of 0x40 (0b01000000).

A 7bit read address of 0x21 (0b0100001) shifted 1 to the left would be 8 bit address of 0x42 (0b01000010).

 

You are trying to read from the wrong address (That's the write address for your port expander if a0 is pulled high). You need to shift the 7 bit to 8 bit addressing, THEN add one.

try: i2c_write8((0x20 << 1) + 1); // the read address

 

Your expanderr variable has the same issue. Read/Write bit is part of the 8bit address, not the 7bit address. Try changing that first, then if the repeated start doesn't work, fall back to stop/start. But it's really just the wrong address I'm figuring.

 

(Alternatively, you can just calculate the 8bit address, stick that in the expander and expanderr variables, and avoid any bit shifting in your code)

Link to post
Share on other sites

cool you help me a lot thanks. it work now, im able to read the last byte i wrote to the lcd

 

working read code

	  i2c_start();
	  i2c_write8(0x20 << 1);
	  i2c_write8(0x00);
	  i2c_stop();

	  i2c_start();
	  i2c_write8(0x20 << 1  | 1);
	  readreg = i2c_read8(0x0);
	  i2c_stop();
Link to post
Share on other sites
  • 2 months later...

can below code works with g2553. I wanna write rt time . how the progrm look like ds1307 is rtc

 

 

 

 

Hello.

 

im trying to read from the i2c port on my g2231, i have found a i2c libary from this website link

but as I see the libary dont support repeated start. I have tried to add this, with some code I found on this forum.

im trying to read from a expander ic MCP23016. but the only thing I read is 0xFF ?. im able to write to the expander ic with no problem.

its the first time i work with i2c. thanks for looking :smile:

 

I have added the full code to.

 

void main(void) {
	WDTCTL = WDTPW + WDTHOLD;
	__delay_cycles(500000);
	i2c_init(); // startup i2c

	exint(); // init the expander ic

	lcdint(); // init the lcd display on the expander ic 

	lcdsendd(0x48); // H
	lcdsendd(0x45); // E
	lcdsendd(0x4C); // L
	lcdsendd(0x4C); // L
	lcdsendd(0x4F); // O

 ////////////////////////////////////// reading ///////////////////////////////////////////////
	i2c_start();
	i2c_write8(0x20 << 1);  // expander ic port write 
	i2c_write8(0x01);  // point on port 1
	i2c_rpt(); // repeated start bit 
	i2c_write8(0x21 << 1); // the read address
	readreg = i2c_read8(0x00); 
	readreg = i2c_read8(0x00);
	i2c_stop();


	lcdsendd(readreg); // write the output the the lcd display. 
	lcdsendd(readreg1);

 

this is the i2c libary

 

//code adapted from http://www.43oh.com/forum/viewtopic.php?f=9&t=139
//Kerry D. Wong
//http://www.kerrywong.com

#include "i2c.h"
#include <msp430g2231.h>

#define SDA  BIT7 //P1.7
#define SCL  BIT6 //P1.6
#define LED  BIT0 //P1.0

void i2c_init(void)
{
    P1DIR |= SCL | SDA | LED; // Set SCL, SDA and LED as Output
    P1REN |= SCL | SDA; // Set Pull-Ups on SCL and SDA

    // enable SDA, SCL, SCLK, i2c mode, MSB, output enabled, hold in reset
    USICTL0 = USIPE7 | USIPE6 | USIMST | USIOE | USISWRST;

    // USICTL0 Upper 8bit Register of 16bit USICTL Register
	// USIPE7   = P1.7 USI Mode, i2c SDA enabled
	// USIPE6   = P1.6 USI Mode, i2c SCL enabled
	// USIPE5   = P1.5 USI Mode, i2c Clock Input? (Not Set)
	// USILSB   = LSB Mode (Not Set = MSB)
	// USIMST   = Master Mode
	// USIGE    = Output Latch (Not Set = Clock Controlled)
	// USIOE    = Data Output Enable
	// USISWRST = USI Software Reset (Set to allow changing settings)

    // SMCLK / 4, and Reverse Clock Polarity
    USICKCTL = USIDIV_2 + USISSEL_2 + USICKPL;

    // USICKCTL 8bit USI Clock Control Register
	// USIDIVx  = Clock Divider (Bit7-5, USIDIV_2 = Divide by 4)
	// USISSELx = Clock Source (For Master Mode, Bit4-2, USISSEL_2 = SMCLK)
	// USICKPL  = Clock Polarity (0 = Inactive Low, 1 = Inactive High)
	// USISWCLK = Software Clock State

    // I2C Mode
    USICTL1 = USII2C;

    // USICTL1 Lower 8bit Register of 16bit USICTL Register
	// USICKPH   = Clock Phase (0 = Data Changed, then Captured, 1 = Data Captured, then Changed)
	// USII2C    = I2C mode
	// USISTTIE  = START condition Interrupt
	// USIIE     = USI Counter Interrupt
	// USIAL     = Arbitration Lost Notification
	// USISTP    = STOP condition Notification
	// USISTTIFG = START condition Int. Flag
	// USIIFG    = USI Counter Int. Flag

    // release from reset
    USICTL0 &= ~USISWRST;
}

void i2c_start(void)
{
    P1OUT |= LED;  // Turn P1.0 Led on

    // Send i2c START condition
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c START
    USICTL0 |= USIGE | USIOE; // Force Output Latch, And Enable Data Output Bit (High to Low SDA while SCL is High)
    USICTL0 &= ~USIGE; // Clear Output Latch (Return to Clock Control)
}

void i2c_stop(void)
{
	// Prepare i2c STOP condition
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c STOP
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

    // Send i2c STOP condition
    USISRL = 0xFF; // Load USISRL Lower Byte Shift Register MSB with 1 for i2c STOP
    USICTL0 |= USIGE; // Force Output Latch (Low to High SDA while SCL is High)
    USICTL0 &= ~USIOE & ~USIGE ; // Clear Data Output Enable Bit and Output Latch (Release SCL)

    P1OUT &= ~LED; // Turn P1.0 Led off
}

unsigned char i2c_write8(unsigned char c)
{
// TX
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = c; // Load USISRL Lower Byte Shift Register with 8 Bit data (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// RX
    // Data TXed. Ready to Receive (n)ACK from i2c Slave
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USICNT = 1; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    c = USISRL; // LSB of USISRL Holds Ack Status of 0 = ACK (0x00) or 1 = NACK (0x01)
    return c;
}

unsigned char i2c_read8(unsigned char acknack)
{
// RX
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USISRL = 0x00; // Clear USISRL Lower Byte Shift Register (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Copy Data to c
    unsigned char c;
    c = USISRL; // USISRL Holds Received Data

// TX
    // Data RXed. Ready to Send (n)ACK to i2c Slave
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = acknack; // Load USISRL Lower Byte Shift Register MSB with acknack (0x00 = Ack, 0xFF = Nack)
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    return c;
}

void i2c_rpt(void)
{
	  USICTL0 |= USIOE;
	  USISRL = 0xFF;
	  USICNT = 1;


	  while ( ( USICTL1 & USIIFG ) != 0x01 );
	  USICTL1 &= ~USIIFG; // likely not needed


	  __delay_cycles( 100 );


	  USISRL = 0x00;
	  USICTL0 |= USIGE + USIOE;
	  USICTL0 &= ~USIGE;


	  __delay_cycles( 100 );
}
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...