• AVR Freaks

Hot!Harmony v2.06 I2C Driver Question

Author
D4ILYD0SE
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/02/12 15:34:09
  • Location: 0
  • Status: offline
2019/11/14 16:52:05 (permalink)
0

Harmony v2.06 I2C Driver Question

I am implementing I2C on a PIC32MX795 using SCL/SDA 1.  Mode I have selected is Dynamic with Interrupt (feel free to let me know if interrupt is not advisable) at 50kHz.
 
I have question(s) regarding the "DRV_I2C_TransmitThenReceive" function.  I was hoping someone has used this in the past and could assist.  In order to request data from slave, I need to tell slave what I want.  I was assuming this was the function to do this with.  Correct?  Call Slave, Write Data, Reset, Receive Data, Stop.  Something to that nature.
 
Assuming this is the correct function to use, I am having issues with the data type. 
 
DRV_I2C_BUFFER_HANDLE DRV_I2C_TransmitThenReceive ( DRV_HANDLE handle,
uint16_t address,
void *writeBuffer,
size_t writeSize,
void *readBuffer,
size_t readSize,
void *callbackContext );
 
I create a uint8_t *i2c_appWriteString [1] = 0x05; and use this when calling the function however the compiler does not like it at all.  I've attempted without the pointer as well.  It seems to be completely cool with using uint8_t *i2c_appWriteString [] = "Hello World"; but nothing more.  I've used byte, char, int... because all I want is an array of the singular byte calling the EEPROM address.  I'm clearing missing something and/or definitely misunderstanding something.  How do I send just a singular byte to the address calling the location I want from the slave?
#1

7 Replies Related Threads

    Paul PortSol
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: Newfoundland, Canada
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/15 05:40:47 (permalink)
    5 (1)
    1. Use the MHC option under apps to generate example code to see usage of Harmony features.
     
    2. Some excerpts from my code:
    #define D_I2C_INDEX (0) //Match to MHC
    #define D_I2C_RTC_ID (0xD0) //DS3232M
    #define D_I2C_RtcAdd (0x00)
    #define D_I2C_RtcLen (7)
    #define D_I2C_MemAdd (0x14)
    #define D_I2C_MemLen (256 - 0x14)
    #define D_I2C_FullAdd (0x14)
    #define D_I2C_FullLen (256)
    const uint8_t puI2C_WriteTxRx[] = {0x00}; //Read Address 0x00 for I2C_TxRxStart
    //==============
    typedef union _TU_RTC { //DS3232M Fields from Address 0x00
        uint8_t pu257[257];// For receive use (size-1), and start at (.pu257+1)
        struct
        {
            uint8_t uAddressW; //First Byte when Writing = Target Address = 0x00
            uint8_t bcdSec; //First Byte when Reading
            uint8_t bcdMin, bcdHour, bcdDay7, bcdDate, bcdCenMonth, bcdYear99;
            uint8_t puAlarmA4[4], puAlarmB3[3];
            uint8_t uCtrl, uStat, uAge, uTempH, uTempL, Test;
            uint8_t puMem[236]; //Warning: Writes to 0xX0/0xX8 can delay Clock
        } fields;
    } TU_RTC;

    //============
    typedef struct
    { /* I2C Driver variables */
        DRV_HANDLE hI2C0;
     E_I2C_States eState;
     E_I2C_Check eCheck;//For clearing a "hung" device on the I2C lines
        DRV_I2C_BUFFER_HANDLE hBuf;
        DRV_I2C_BUFFER_EVENT eResult;//Transfer result code
        TU_RTC tRtc;
        uint8_t uRxLen;
        uint32_t uErrCycle;
        //uint32_t uErrTotal;
        uint32_t uRecoverCount;
        uint32_t uRecoverBitCount;//Typically <=8 bits need to be shifted from slave to recover I2C SDA
        bool bDetailed; //Flag: requested Detailed RTC Read = Show Detailed Status (All bytes)
        bool bFirstRead; //Flag: First RTC Read after startup (Goes To LogU)
        bool bRecoverRead;//Flag First RTC Read after a Recovery (Goes To LogD)
        bool bSetRead; //Flag: First RTC Read after RTC Set (Goes To LogU)
    } I2C_DATA;
    I2C_DATA sI2C;

    //=============
                sI2C.hI2C0 = DRV_I2C_Open(D_I2C_INDEX, DRV_IO_INTENT_READWRITE|DRV_IO_INTENT_NONBLOCKING|DRV_IO_INTENT_EXCLUSIVE );//Fail = -1 = DRV_HANDLE_INVALID 
                if(DRV_HANDLE_INVALID == sI2C.hI2C0)
                {
                    D_PRINTFn0_LogD_ERROR("I2C Init Failed");
                    sI2C.eState = I2C_InitERROR; sI2C.uErrCycle++;
                    Nop();//For Breakpoint when optimization makes other lines "unbreakable"
                    vI2C_State();
                    break;
                }//else Opened OK
                printf("I2C Handle: 0x%x (-1=fail)\n", sI2C.hI2C0);
                sI2C.bFirstRead = true;//Flag waiting for First Read of RTC
                sI2C.eState = I2C_TxRxStartDetailed;// Switch to the TransmitReceive State (First Read RTC is Detailed).

    //===============
     
      case I2C_TxRxStartDetailed://Queue the Buffer = hBuf
            {
                //DRV_I2C_BUFFER_HANDLE DRV_I2C_TransmitThenReceive( DRV_HANDLE handle, uint16_t id, void *TxBuf, size_t TxLen, void *RxBuf, size_t RxLen, void *unused);
                sI2C.hBuf = DRV_I2C_TransmitThenReceive(sI2C.hI2C0, D_I2C_RTC_ID, (void *)puI2C_WriteTxRx, sizeof(puI2C_WriteTxRx), sI2C.tRtc.pu257+1, sizeof(sI2C.tRtc.pu257)-1, NULL);
                sI2C.eState = I2C_TxRxWait;
                vI2C_State();
                break;
            }

    //=============
      case I2C_TxWait://Check Transfer Status = eResult
            {
                sI2C.eResult = DRV_I2C_TransferStatusGet(sI2C.hI2C0, sI2C.hBuf);//Check Buffer Status
                switch(sI2C.eResult)
                {
                    default: DI2C_PRINTF_Tx("I2C Tx in progress [%d]\n", sI2C.eResult); break;
                    case DRV_I2C_BUFFER_EVENT_COMPLETE: sI2C.eState = I2C_TxRxStartDetailed; DI2C_PRINTF_Transfer("I2C Tx[%lu]=OK (Err:%u)\n", sizeof(tuRtcSet), sI2C.uErrCycle); break; //Success?
                    case DRV_I2C_BUFFER_EVENT_ERROR: sI2C.eState = I2C_IDLE; D_PRINTFn_LogD_ERROR("I2C Tx Err(%u)", ++sI2C.uErrCycle); break; //Error
               }
               break;
      }

    //===========
    #2
    Paul PortSol
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: Newfoundland, Canada
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/15 05:45:12 (permalink)
    5 (1)
    Attached my full I2C interface for DS3232MZ+ (RTC+NVRAM, I2C) which may help you figure out the I2C usage (note the warning comments in the file).
    - rtc_ds3232m.c
     
    I'm sure this can be simplified, I went a bit nuts on the failure recovery and such for the RTC.
     
    Paul
    #3
    D4ILYD0SE
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/02/12 15:34:09
    • Location: 0
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/15 10:01:12 (permalink)
    0
    Man, this is a lot for my mediocre programming self to digest.  But I shall dive into it.  Thank you!
     
    Also, I have used the I2C example apps.  What's available is the Master Sender.  Sends "Hello World."  With some modification, I am able to send that on a regular basis (code definitely needs some failure scenario work).  But that still leaves me with the issue of trying to send a singular byte.  The byte I want to send is not represented in ASCII.  So I can't change "Hello World" to like... "A"  I still have a data type misunderstanding/issue.
     
    Anyways, back to digesting.
    post edited by D4ILYD0SE - 2019/11/15 10:05:57
    #4
    Paul PortSol
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: Newfoundland, Canada
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/18 05:26:31 (permalink)
    5 (1)
    In C to specify a binary array instead of a string use:
    const char pcString[] = "abcd";//Length = 5 including final NUL
    const uint8_t pbArray[4] = { 'a', 'b', 'c', 'd' };//Length = exactly 4
     
    Note that the text string can be NULL terminated, while the array must be exact size specified because a NULL is just a data zero.
    uLength=sizeof(pcString);//5
    send(pcString, sizeof(pcString)-1);//Send without trailing NUL
    uLength=sizeof(pbArray);//4
    send(pbArray, sizeof(pbArray));
     
    Note also that in C strings and arrays use pointers, to send a single byte you need to have a 1 byte long array, or pass the pointer to the byte instead of the byte itself.
    uint8_t uByte;
     
    uByte = 0xFF;
    send(&uByte, 1);//Using pointer to single byte
    send(&uByte, sizeof(uByte));
     
    Paul
    #5
    D4ILYD0SE
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/02/12 15:34:09
    • Location: 0
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/20 11:37:15 (permalink)
    0
    Yeah, I stumbled upon that the other day and it was one of those face palm moments.  But I do thank you.
     
    Turns out, though.  My actual issue is my circuit.  I'm using a I2C isolation chip that is capable of 1Mbps, however, the ACK sent by the slave device is literally ON then immediately OFF which is too fast for the isolation chip.  Directly connected, the micro has now issue seeing that.  So for anyone out there, the I2C drivers do work.  They do, however, need work in terms of errors.  Driver will get hung up if something bizarre happens.
    #6
    ric
    Super Member
    • Total Posts : 24624
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Harmony v2.06 I2C Driver Question 2019/11/20 16:11:46 (permalink)
    5 (1)
    The slave should keep driving SDA low for the entire SCL high time of the ACK cycle. What is yours doing?

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    D4ILYD0SE
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/02/12 15:34:09
    • Location: 0
    • Status: offline
    Re: Harmony v2.06 I2C Driver Question 2019/11/21 10:32:31 (permalink)
    0
    ric
    The slave should keep driving SDA low for the entire SCL high time of the ACK cycle. What is yours doing?


    Taking what you said to heart, what appears to be happening is the Master going back to high and the slave pulling down for the ACK thus... a "blip."  Which means that's actually normal.
     
    So it's back to the drawing board as to why the isolator chip is not working.  Either way, drivers work. lol  
    #8
    Jump to:
    © 2019 APG vNext Commercial Version 4.5