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.

Incorrect data coming on PCF8574 via I2C

Other Parts Discussed in Thread: PCF8574

Dear all,

I am using TIVA C Launchpad for this study. I am using I2C from PB2 and PB3 pins and connected through PCF8574. Pull up resistor at I2C pins are of 4.7kOhm. On IC PCF8574 I have connected cathode of LEDs. So when I drive pin P0, P1, P2, P3 to zero the LEDs should glow.

Now the problem is in my program if I write from 0 to 9 the four LEDs should glow. Till 9 LED glow perfectly but as I write A it starts with 1 again.

Below is the waveform coming:

and below is the code:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//! - I2C0 peripheral
//! - GPIO Port B peripheral (for I2C0 pins)
//! - I2C0SCL - PB2
//! - I2C0SDA - PB3
//
// Number of I2C data packets to send.
//
//*****************************************************************************
#define NUM_I2C_DATA 3

//*****************************************************************************
#define SLAVE_ADDRESS 0x20

void I2C_data(unsigned char data)
{
	    I2CMasterDataPut(I2C0_BASE,data);
		I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
		 while(I2CMasterBusy(I2C0_BASE)!=false)
		       {
		        	;
		       }
		 SysCtlDelay(15000000);
		 I2CMasterDataPut(I2C0_BASE,data);
		 I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
		  while(I2CMasterBusy(I2C0_BASE)!=false)
		 	       {
		 	        	;
		 	       }
		 SysCtlDelay(15000000);
		 I2CMasterDataPut(I2C0_BASE,data);
		 I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
}

void I2C_String_Display(unsigned char *str)
{


 while(*str)
 {
	 I2C_data(*str);
	 str++;
 }
return;

}

int main(void)
{
    //
    // Set the clocking to run directly from the external crystal/oscillator.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    //
    // The I2C0 peripheral must be enabled before use.
    //
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    //
    // For this example I2C0 is used with PortB[3:2].  The actual port and
    // pins used may be different on your part, consult the data sheet for
    // more information.  GPIO port B needs to be enabled so these pins can
    // be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    //
    // Configure the pin muxing for I2C0 functions on port B2 and B3.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    //
    // Select the I2C function for these pins.  This function will also
    // configure the GPIO pins pins for I2C operation, setting them to
    // open-drain operation with weak pull-ups.  Consult the data sheet
    // to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

    //
    // Enable loopback mode.  Loopback mode is a built in feature that is
    // useful for debugging I2C operations.  It internally connects the I2C
    // master and slave terminals, which effectively let's you send data as
    // a master and receive data as a slave.
    // NOTE: For external I2C operation you will need to use external pullups
    // that are stronger than the internal pullups.  Refer to the datasheet for
    // more information.
    //
   HWREG(I2C0_BASE + I2C_O_MCR) = I2C_MCR_MFE ;

    //
    // Enable and initialize the I2C0 master module.  Use the system clock for
    // the I2C0 module.  The last parameter sets the I2C data transfer rate.
    // If false the data rate is set to 100kbps and if true the data rate will
    // be set to 400kbps.  For this example we will use a data rate of 100kbps.
    //
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);

    // Tell the master module what address it will place on the bus when
    // communicating with the slave.  Set the address to SLAVE_ADDRESS
    // (as set in the slave module).  The receive parameter is set to false
    // which indicates the I2C Master is initiating a writes to the slave.  If
    // true, that would indicate that the I2C Master is initiating reads from
    // the slave.
    //
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);


        // Place the data to be sent in the data register
        //
       I2CMasterDataPut(I2C0_BASE,0x00);
       // I2CMasterDataPut(I2C0_BASE,data);
        //
        // Initiate send of data from the master.  Since the loopback
        // mode is enabled, the master and slave units are connected
        // allowing us to receive the same data that we sent out.
        //
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(I2C0_BASE)!=false)
       {
        	;
       }
       // SysCtlDelay(15000000);
        I2C_String_Display("A");

}


Please let me know if there is something wrong in the sting defined. Because if I write through single command or without pointer it is working correctly. But with string pointer it does not. 

 

  • Is not your post's title (very) far, "off-mark?" Yours is a "C" programming issue - and has been well answered in your (near identical) recent post.
  • Hello,

    sorry for being off mark. Yes it is my "c" programming issue . There is something wrong with this pointer thing.
  • Indeed - suggest you "edit" your post's title to "better" reflect your, "C tutorial" request. This will "save" hapless others from misdirecting their time/effort.
    Most all "C" texts devote much coverage to pointers. And - armed w/your MCU and IDE - cannot you quickly/easily experiment - and build mastery? (the MCU-IDE combination proves a splendid learning lab)
  • First, I very much echo cb1's comment, although I suspect there's more than a C language issue involved

    Second, I very highly recommend you get PC-Lint or equivalent and use it before every compile

    Third, it's not clear what you are actually attempting to do here (the chip certainly will not display strings). Can you show a sample of what "works" and tell us what output you expect for the string example.

    Fourth you have a number of type conflicts. They do not necessarily cause a problem but they do suggests confusion about types which may reflect a deeper confusion.
    - First "A" is type char * not unsigned char *.
    - Second the argument to I2C_data should be uint8_t not unsigned char. This is a style issue more than a type conflict. Using the int type makes it clear that you are dealing with an integer not a character, and using the int type will have type issues later.

    General rule of thumb: strings and characters should only be represented by plain char (unless dealing with wide characters). Small integers (IE bytes) should be represented by the appropriate *int8_t type.

    Robert