• AVR Freaks

Hot!I2C example code from Microchip

Page: 12345.. > >> Showing page 1 of 6
Author
Andy_Taiwanese
Super Member
  • Total Posts : 508
  • Reward points : 0
  • Joined: 2014/12/19 02:59:38
  • Location: 0
  • Status: offline
2017/05/28 02:46:00 (permalink)
0

I2C example code from Microchip

Hi, I've been reading the I2C datasheet for making a communication between PIC16F1824 and OZ8920(battery protection IC) So, I downloaded the I2C_EEPROM example code from Microchip.
 
I got confused with the following:
    block_address = 0x00; // Set the eeprom block address that we will write the data to
    word_address = 0x00; // Set the eeprom word address that we will write the data to
    eeprom_data = 0x55; // This is the data we are going to write

    Send_I2C_StartBit(); // send start bit
    Send_I2C_ControlByte(block_address,0); // send control byte with R/W bit set low
    Send_I2C_Data(word_address); // send word address
    Send_I2C_Data(eeprom_data); // send data byte
    Send_I2C_StopBit(); // send stop bit

 
I knew there is an address which I wanna write a data to or read a data from, but why there are two distinct addresses called "block address" and "word address"?
 
In Send_I2C_ControlByte
void Send_I2C_ControlByte(unsigned int BlockAddress,unsigned int RW_bit)
{
    PIR1bits.SSP1IF=0; // clear SSP interrupt bit

    // Assemble the control byte from device code, block address bits and R/W bit
    // so it looks like this: CCCCBBBR
    // where 'CCCC' is the device control code
    // 'BBB' is the block address
    // and 'R' is the Read/Write bit

    SSPBUF = ((device_control_code << 4) | (BlockAddress <<1)) + RW_bit; // send the control byte
    while(!PIR1bits.SSP1IF); // Wait for interrupt flag to go high indicating transmission is complete
}

 
This is not as I thought, as far as I knew, start condition should be followed by slave address+RW_bit as picture 1.
Why BlockAddress appears here? What is control byte? Is the BlockAddress the register address?
 
Then, the two same function call "Send_I2C_Data" with different arguments, one of it is word_address.
void Send_I2C_Data(unsigned int databyte)
{
    PIR1bits.SSP1IF=0; // clear SSP interrupt bit
    SSPBUF = databyte; // send databyte
    while(!PIR1bits.SSP1IF); // Wait for interrupt flag to go high indicating transmission is complete
}

Why word_address is the databyte according to parameter? I was wondering which means if I wanna write a databyte to an specified register address, I will need to write an address as the data first. But! that's a contradictory. I already specified the address which is BlockAddress. So, What exactly are block_address and word_address? The other critical point is in here, where is the ACK bit from the slave? Isn't Slave supposed to be transmitting the ACK bit after Master sending the databyte?
 
Then, after finishing the function call Send_I2C_Data, then followed by Send_I2C_StopBit. Wait....where is the ACK again?
 
Next, there is the comment below followed by:
At this point the serial eeprom is writing the data we just sent. We can either
    // wait the maximum write cycle time for the write to complete (5 ms) or we can 'poll'
    // the eeprom to see when it is done. Polling is done by sending a start bit and
    // a control byte with R/W set to a zero and checking the ACK bit coming back from
    // the eeprom. While it is still in the write cycle it will not send an ACK so
    // we can just send the startbit/control byte sequence over and over again until
    // the eeprom finally sends and ACK and then we know it is finished. Here is how
    // you can do the polling:

Why PIC needs to "poll" the eeprom? There should be only one eeprom PIC is communicating.(According to dictionary, pull means to check each channel rapidly to establish which are free, or to call for data from each terminal in turn)
 
I am very confused.... It seems the flow example do is totally different from what datasheet said.... Thanks for reading
post edited by Andy_Taiwanese - 2017/05/28 03:23:47

Attached Image(s)

#1

113 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 02:50:37 (permalink)
    +2 (2)
    That example code is plainly for talking to an EEPROM, which is not what you are talking to.
    You may get some ideas from it, but you certainly can't use most of it.
     
     
    #2
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 02:51:58 (permalink)
    0
    To qhb:
     
    Sorry, you mean EEPROM is different from QZ8920 IC?
    #3
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 02:55:16 (permalink)
    0
    I have to use PIC to communicate with operation register in QZ8920, indirectly access the EEPROM register, as picture

    Attached Image(s)

    #4
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:06:37 (permalink)
    +1 (1)
    Can you post a full datasheet of this device? (I can't google it...)
     
    Even if it has EEprom along its other features, hardly its access will be the same as standard EEproms (I think)

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #5
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:10:24 (permalink)
    +1 (1)
    To CinziaG:
    Of course I can, here is the link:
    https://www.dropbox.com/s...wg8dPN0fSVTg2ddTa?dl=0
    complement on 6/1:
    Please don't spread this document out to others, my boss said this document is classified, sorry!
     
     
    post edited by Andy_Taiwanese - 2017/05/31 20:02:44
    #6
    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:16:43 (permalink)
    +1 (1)
    It's mentioned in here http://www.o2micro.com/products/o2m_indust_auto_brochure_1012.pdf
    but I haven't found a  datasheet.
     
    #7
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:20:27 (permalink)
    0
    sounds nice, thanks Smile
    let's see

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #8
    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:23:32 (permalink)
    +3 (3)
    That is a very complex chip/
    I would STRONGLY recommend you get your I2C code working on a more standard chip (say an EEPROM), and only when you've got that working, move on to this one.
     
    #9
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:27:03 (permalink)
    +1 (1)
    WOW! passwords, PEC, many many registers... Smile
    Yeah it is complicated. Even better, I'd suggest you try communicating a with TC74 temperature sensor (that you can sample from Microchip)...

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #10
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:52:29 (permalink)
    +1 (1)
    To both masters qhb and Cinziag:
     
    My honor company gave me a week to solve this because the deadline is closing.....I have no choice.
     
    Could you give me some suggestion? Maybe some example code? I need to fight against the time  
    #11
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 03:55:33 (permalink)
    +1 (1)
    To qhb and Cinziag:
    I even have no test board for easier communication but only this one. My only mission is get value from some addresses, other controls will be done through hardware. 
     
    #12
    Mysil
    Super Member
    • Total Posts : 3488
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 04:11:10 (permalink)
    +1 (1)
    Hi,
    Address and address may mean several different things,
    and example code isn't always clear about what it mean.
     
    There may be:
        I2C slave address, the first byte transmitted from Master following a Start or Repeat Start signal.
     
        I2C slave register number, register_index, the second byte from I2C master in a write operation to the battery protection IC.
     
        EEPROM address, in a Memory device, or a slave device with EEPROM in addition to other functions.
     
    Then, in a device with EEPROM inside, the slave may not be able to respond for some time, while EEPROM storage is actually beeing updated.
    In Microchip EEPROM memory devices, slave will Not acknowledge (NACK) the I2C slave address,  while EEPROM memory cells are beeing programmed with updated values.
     
    Polling the EEPROM memory device, means to send a I2C slave write address, and test the ACK or NACK bit,
    to find if a previous write operation might still be going on.
    Also, if the I2C slave device may somehow have been disconnected, the response will be NACK.
     
    Then, to make more confusion, some Microchip datasheets, and example code for EEPROM devices,
    use the term 'Control byte' when explaining about I2C slave address.
    For EEPROM, or other memory devices with more than 256 bytes of memory, multiple bytes will be needed to transfer a memory address.
     
       Mysil
    #13
    Andy_Taiwanese
    Super Member
    • Total Posts : 508
    • Reward points : 0
    • Joined: 2014/12/19 02:59:38
    • Location: 0
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 04:20:01 (permalink)
    0
    To Mysil:
     
    Sorry, I am dizzy with my eyes hurting. I can't think right now.
    Very thankful you replied my questions, I will read it.
     
    May I ask you if I wanna make a communication with this protection IC, What search key can I type for googling? I'm in win or go home situation.
    #14
    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 04:49:37 (permalink)
    +4 (4)
    Andy_Taiwanese
    To both masters qhb and Cinziag:
     
    My honor company gave me a week to solve this because the deadline is closing.....I have no choice.
     
    Could you give me some suggestion? Maybe some example code? I need to fight against the time  

    Sorry to be harsh, but I don't think you're going to make it.
    NOW is the time to get someone who knows what they are doing to help out, and that will probably cost you.
    I'm not in a position to do it, but another member may be able to.
     
    Otherwise, you are really trying to run before you can walk. You have to take the development process one step at a time, not leap straight into a very complex stage without getting the foundations right.
     
    #15
    rodims
    Super Member
    • Total Posts : 1532
    • Reward points : 0
    • Joined: 2009/02/10 11:08:59
    • Location: 51.9627, 7.6262
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 05:02:29 (permalink)
    +2 (2)
    While writing on a comment I saw qhb's answer and I think that's the best answer we can give.
    Probability is low that anyone here can help you with the special chip (the functionality of the chip).
    It's already a challenge to get it working (for you/with you) on the low level with i2c. And this is the 'minor' part, though you did not tell, what you are expected to do. If your task is done when you can e.g. just read one byte from the device, then things are different. Already 'writing' is more difficult.
     
    So here is my original comment, but it should not encourage you to take a wrong decision.
     
    Andy_Taiwanese
    To qhb: Sorry, you mean EEPROM is different from QZ8920 IC?


    Yes, for your point of view it is NOT an EEPROM.  The chip also has eeprom memory to hold the parameters, but as qhb said, it is not a 'classic' eeprom. You should not try to make your Microchip eeprom i2c code 1:1 running, this will lead you in the wrong direction with 'blocks' and memory organisation. This leads to questions as you already asked them "Why BlockAddress appears here? What is control byte? Is the BlockAddress the register address?"
     
    Of course it also contains the basic i2c code, but that's the portion you either would have to extract, or otherwise start with other example code.
     
    You need simple i2c code to read and write to the chip registers, but since this is a very complex chip (and also looking at your previous posts), it would really be better to test your i2c code with a simpler i2c device. May be even on another development board with a similar PIC. 
    You probably will not be able to write to the chip registers without a certain procedure, since the registers are write protected.
     
    Currently you think you do not have time to waste with another i2c chip, but under the bottom line you will save time, if you split your work into two parts. 
    a) Get / write i2c code which is known (proven) to work or which you can test with a much more simpler i2c device.
    b) Once that code works go back and try to use it with the QZ8920.
    Also you first should try to read some of its registers (it does not matter whether its eeprom or not behind the register addresses).  This should give certain (reproducible) constant values for different registers.
    Only if thats working continue to write something.
     
     
     
     
     
    #16
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 05:05:54 (permalink)
    +3 (3)
    I can help with my generic SW I2C that works fine on any pic and ay pin;
    we can start with the simplest device (as i wrote above) and then get to the details of your project.
     
     

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #17
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 09:18:43 (permalink)
    +2 (2)
    C source:

    // -------------------------------------------------------------------------------------
    char DoI2CMO(BYTE temp) {                            // Master, output (CLK negativo): entra in W il byte
        BYTE tempC;

                                                    // PRIMA fare DoI2CStart!!
        tempC=8;
        setDataOutput();

        do {
    //  clrwdt            ; gia' in Delay_uS - OCCHIO con lib30 no!!
            if(temp & 0x80)                    // MSB first
                SPI_232_IO=1;                    // DATA=1
            else
                SPI_232_IO=0;                    // DATA=0

            temp <<= 1;

            Delay_1uS();                        // serve un minimo di ritardo tra il settaggio di DATA e la salita di CLK
            SPI_232_O=1;
            Delay_SPI();
            SPI_232_O=0;
            Delay_SPI();
            }    while(--tempC);

        setDataInput();
        Delay_SPI();
        SPI_232_O=1;
        setClockHigh();                    // aspetto ACK
    //        Per WAIT_STATE dello slave (CLK basso)... NON e' chiaro se PRIMA o DOPO ACK... (PicBell lo fa dopo!)
    //            questo lo controlla SEMPRE!
        Delay_SPI();

        if(SPI_232_I)
            tempC=-1;                                        // Z=1 se ACK=OK (basso), altrimenti Z=0 e W!=0
        else
            tempC=0;

        SPI_232_O=0;

        return tempC;

        }


    void DoI2CStart(void) {                        // Master, start (CLK negativo)

        SPI_232_IO=1;                        // imposto DATA=1 e CLK=0
        setDataOutput();
    //    bcf PORTA,SPI_232_O            ;    CLK=0        ... e' gia' cosi' ...
        Delay_SPI();
        SPI_232_O=1;
    //    setClockHigh();                    // CLK=1 (qui sarebbe giusto, + che aspettare, dare errore BUS_ARBITRATION...)
        Delay_SPI();
        SPI_232_IO=0;                        // DATA=0 ; data line goes low during high clock for start bit
        Delay_SPI();
        SPI_232_O=0;                        // CLK=0
        Delay_SPI();
        }

    void DoI2CStop(void) {                // Master, stop (CLK negativo) (non usato con SHT11)
                                                        // (SHT11 non e' del tutto I2C compatibile ...)
        setDataOutput();
    //    bcf PORTA,SPI_232_O            ; CLK=0        ... e' gia' cosi'...
        SPI_232_IO=0;                            // DATA=0
        Delay_SPI();
        SPI_232_O=1;
        setClockHigh();                    // CLK=1
        Delay_SPI();
        SPI_232_IO=1;                        // DATA=1 ; data goes high while clock high for stop bit
        Delay_SPI();

        SPI_232_O=1;
        setClockHigh();                    // CLK=1
        // questa e' un'altra attesa, per i dispos. (tipo PICBELL, PICWDI2C) che il WAIT lo fanno DOPO lo STOP!

        SPI_232_O=0;                        // CLK=0
        Delay_SPI();
        }

    BYTE DoI2CMI(char temp2) {            // Master, input (CLK negativo): esce in W il byte se C=0 o C=1=errore
                                                    //   entra W=1 se bisogna dare ACK allo slave o 0 se no
        BYTE temp,tempC;

                                                    // PRIMA fare DoI2CStart!!
        tempC=8;
        temp=0;
        setDataInput();

        do {
    //  clrwdt            ; gia' in Delay_uS
            Delay_SPI();
    //    call  setClockHigh            ; CLK=1    fare? boh?
            SPI_232_O=1;
            Delay_SPI();

            temp <<= 1;                            // MSB first
            if(SPI_232_I)
                temp |= 1;

            SPI_232_O=0;

            }    while(--tempC);

        setDataOutput();

        if(temp2)                            // invio ACK come richiesto (Z=1 se stop cioe' ACK=1, Z=0 cioe' ACK=0)
            SPI_232_IO=0;                // DATA=0
        else
            SPI_232_IO=1;                // DATA=1

        SPI_232_O=1;
        Delay_SPI();
        SPI_232_O=0;
        Delay_SPI();

        return temp;

        }

    void setClockHigh(void) {
        unsigned int n=40000;
    // Gestisce WAIT_STATE dello slave (CLK basso)... che puo' succedere SEMPRE!
        
        SPI_232_O=1;

        SPI_232_O_TRIS=1;                // CLK e' input

        do {
            ClrWdt();
            Delay_1uS();
            } while(!SPI_232_OI && n--);

        SPI_232_O_TRIS=0;                // CLK e' output

    // restituire errore se CLK non rilasciato?
        }


     
     

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #18
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 09:21:02 (permalink)
    +1 (1)
    H include file:

     

    char DoI2CMO(BYTE);
    BYTE DoI2CMI(char);
    void DoI2CStart(void);
    void DoI2CStop(void);
    void setClockHigh(void);
    #define setDataOutput()    { SPI_232_I_TRIS=0; }                // DATA e' output
    #define setDataInput() { SPI_232_I_TRIS=1; }                // DATA e' input
        
     
    #define DELAY_SPI_FAST 5
    #define Delay_SPI() __delay_us(DELAY_SPI_FAST /*DelaySPIVal*/)
    #define Delay_1uS() __delay_us(1)
    #define Delay_uS(x) __delay_us(x)
    #define Delay_mS(x) __delay_ms(x)
    #define Delay_1mS() Delay_mS(1)
     
     
    // pins definitions, can be moved anywhere
            #define SPI_232_I             PORTAbits.RA15
            #define SPI_232_IO             LATAbits.LATA15
            #define SPI_232_I_TRIS             TRISAbits.TRISA15
            #define SPI_232_O             LATAbits.LATA14
            #define SPI_232_OI             PORTAbits.RA14
            #define SPI_232_O_TRIS             TRISAbits.TRISA14

     
    post edited by CinziaG - 2017/05/28 09:23:52

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #19
    CinziaG
    die fucking humans
    • Total Posts : 3145
    • Reward points : 0
    • Joined: 2016/12/07 14:20:36
    • Location: Wien
    • Status: offline
    Re: I2C example code from Microchip 2017/05/28 09:22:53 (permalink)
    +1 (1)
    Usage example:

        DoI2CStart();
        DoI2CMO(0x90 | (q << 1));        // mando address (FORZO WR)
        DoI2CMO(0);
        DoI2CStart();
        DoI2CMO(0x91 | (q << 1));        // mando address (FORZO RD)
        n=DoI2CMI(0);
        DoI2CStop();



     
    q is the sub-address of TC74 device (0..7, check its datasheet by microchip),
    and in n the temperature is returned.
     
    0x90/0x91 is the address of TC74 plus the R/W bit.
     
     

    in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
    my most wonderful creations here
    https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
    #20
    Page: 12345.. > >> Showing page 1 of 6
    Jump to:
    © 2019 APG vNext Commercial Version 4.5