• AVR Freaks

Hot!I2C communication with two PIC18F47Q10. Does anyone know how to do this?

Author
ishkabum
Starting Member
  • Total Posts : 58
  • Reward points : 0
  • Joined: 2020/09/24 07:42:09
  • Location: Washington DC
  • Status: offline
2020/10/30 12:23:52 (permalink)
0

I2C communication with two PIC18F47Q10. Does anyone know how to do this?

I'm using the MCC generated routines. 
 
The slave has its user-generated interrupt routine which should just display the word to LEDs. This should be the simplest routine to demonstrate this functionality. The master is enabling the serial port, setting start condition and then just sends out using the MCC-generated Write1ByteRegister() function. It appears as I debug that it's not actually writing to the buffer at all. Does anyone know what's going on? This part of this project is really testing my determination.
 
Master:

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"
#include "mcc_generated_files/i2c1_master.h"

uint8_t dataToSend = 0x8F;

void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
    
    SSP1CON1bits.SSPEN = 1;
    SSP1CON2bits.SEN = 1;

    while (1)
    {
        I2C1_Write1ByteRegister(8, SSP1BUF, dataToSend); //Send to slave
        dataToSend++;

    }
}

 
By the way the dataToSend++ line was only written to give myself a breakpoint for debugging. It doesn't get to that line. Odd
 
Slave
#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/i2c1_slave.h"

void slaveReadingISR(void);

uint8_t dataInput = 0;
uint8_t lastInput = 0;

void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
    I2C1_SlaveSetReadIntHandler(slaveReadingISR);
    
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    I2C1_Open();
    
    while (1)
    {
    }
}

void slaveReadingISR(void)
{
    dataInput = I2C1_Read(); //Read word --> dataInput
    LATC = dataInput;
}

 
Any help will be appreciated.
 
 
post edited by ishkabum - 2020/10/31 08:24:31
#1

18 Replies Related Threads

    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/30 17:33:40 (permalink)
    +2 (2)
    Hi,
    Yes, I have done that in several ways, between various PIC devices, but not PIC18F47Q10.
    The MSSP peripherals in __Q10  is very similar to  many other 8-bit PIC devices with MSSP.
    There are many threads in this forum dealing with similar questions.
    Be aware that there are also many mistakes around, also in code from Microchip.
     
    In Master code, do Not mess with:   SSP1CON2bits.SEN = 1;
    before calling:   I2C1_Write1ByteRegister(...);
    It will cause the MSSP hardware to start working,
    and cause confusion inside I2C1_Write1ByteRegister(),
    cause a Bus Collision flag bit to be raised in PIR3bits.BCL1IF
    The generated code in:  i2c1_master.c  is Not prepared to detect this, is Not able to handle the problem,
    and do Not report the failure to application code. 
     
    There are some questions that always get asked when a thread like this is started:
    Are Pull-up resistors in place, and connected to the right pins? 
    Are port registers correctly set up for Digital Input?
        That is Not Analog and Not Output.
    Q10 is a device with PPS remapping, are I2C Outputs mapped to the same pins as I2C Input? 
     
    To investigate a question like this, a complete program project demonstrating the problem,
    including all files made by MCC, and MPLAB X files holding project information.
    See this thread and messge about 'Package' facility:
    https://www.microchip.com/forums/FindPost/1155821
     
    About I2C communication between microcontrollers,
    there is my experience that it is easier to develop and debug Master software,
    using a known good hardware slave device, like a I2C EEPROM, I2C Temperature sensor, or RTC  Clock.
     
    When you have Master code that work, then you may try Slave code. 
    It is my experience that it is easier to debug Slave code, with Slave and Master code running in the same microcontroller, using 2 different MSSP peripherals.
     
        Mysil
    #2
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/30 23:49:30 (permalink)
    +1 (1)
    Hi,
    About Master code:
    In:   "mcc_generated_files/examples/i2c1_master_example.c"
    there are a selection of application interface functions.
    These are quite similar to functions earlier generated by Foundation Services Library,
    and used by MikroE Click examples.
    Actually Foundation Services:   "mcc_generated_files/drivers/i2c_simple_master.c"
    may still be generated, and should provide interface functions with names compatible with earlier code.
     
    The function you have tried to call,
        I2C1_Write1ByteRegister(8, regIndex, dataToSend); //Send to slave
    Actually will try to transfer 3 bytes.
    After a Start signal, it will send the I2C slave Address with R/W bit = 0 for a Write to the slave.
    Code will check if there is ACK or NACK response. If there is no answer, then transfer will be terminated with a Stop signal sequence. 
    If there is ACK response, driver will send 'regIndex' byte, and then 'dataToSend' byte.
    This is with the assumption that many I2C slave devices, will use the first byte after Address,
    as a operation code, or register index in the slave.
    Changing the 'dataToSend' value for each transfer, is good for test communication with another microcontroller.
     
    Note, that there is no indication from I2C1_Write1ByteRegister(...); wether communication was successfull, or failed.
     
    About Slave code:
    i2c2_slave.c   have a number of small building blocks for making a DIY slave program.
    There are a number of hardware interface functions,
    a number of function pointers that may be set to call your own CallBack functions when something happen,
    and a Interrupt Handler that will call one of the Callbacks when something happen.
    There are also 3 global variables:  i2c2WrData;   i2c2RdData;   i2c2SlaveAddr;
    that have the latest slave address received, last data byte received, and the next byte to transmit.
     
    There is no description that I have seen, of how to bring it all together.
    Maybe there may be some example code somewhere, I do not know.
     
    You may call:  I2C2_Open();  or  I2C1_Open(); as you have in slave code already, 
    set a breakpoint in:  "interrupt_manager.c"    and see what happens.
     
        Mysil
     
     
     
    #3
    ishkabum
    Starting Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2020/09/24 07:42:09
    • Location: Washington DC
    • Status: offline
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/31 08:10:28 (permalink)
    0
    Mysil, thanks for your comments, they've helped me to understand better what's going on. I removed the manual setting of SSPEN, SEN as I look further into the MCC routines and see that they set these bits at appropriate points. It appears in my case the WriteNBytes routine with N=1 is the appropriate function to use. Of course, I could have noted this myself with careful inspection, but when getting on the phone with Microchip Support it would have been nice if the rep knew that and didn't instruct me to use Write1ByteRegister instead. They really don't know how to use this.
     
    I read into sizing considerations for the pull-up resistors and added 10kOhm resistors to Data and Clock lines tying to VDD for my case using 100kHz baud. I have not measured bus capacitance which is another consideration. What I was seeing is that the SSP1BUF in master did get filled with the address shifted by 1, but then it ended up stuck in I2C1_MasterWaitForEvent waiting for SSP1IF to go high and break out. However I was attempting to use the Master without interrupts, so I'm not sure if that's actually possible with this code. It seems if I want to use the routines from the MCC example I do have to enable I2C interrupts and create a handler.
     
    Updated master code is as follows:
     

    #include "mcc_generated_files/mcc.h"
    #include "mcc_generated_files/examples/i2c1_master_example.h"
    #include "mcc_generated_files/i2c1_master.h"

    uint8_t dataToSend = 0x55;

    void main(void)
    {
        // Initialize the device
        SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

        while (1)
        {
            I2C1_WriteNBytes(8, dataToSend, 1); //Send to slave
            dataToSend++;
            
            //__delay_ms(1000);

        }
    }

     
    SSPEN goes high, SEN goes high, but it gets stuck at the line within WriteNBytes: 
    while(I2C1_BUSY == I2C1_Close()); // sit here until finished.

    The SSP1BUF does take the address shifted by 1, but when I debug the slave it never goes into its interrupt handler and the master stays stuck in busy. SSPM is loaded with the right values for master (8) and slave (6). SSPEN goes high for both.
    post edited by ishkabum - 2020/10/31 09:01:17
    #4
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/31 10:45:02 (permalink)
    +1 (1)
    Hi, 
    Code for I2C Master mode may be generated without interrupts, or with interrupts, by MCC.
    If you are using functions in:
      "i2c_master_example.c"  then there is no real benefit in generating master code with interrupt handling.
    The code will block at:        while(I2C_BUSY == I2C_Close()); // sit here until finished.
    anyway. 
     
    There is code inside the driver that will inspect the Interrupt Flag:   PIR3bits.SSP1IF
    to find when operation is completed. 
    This do not mean that Interrupt code is needed, or should be enabled.
    But it should not cause errors either.
     
    If code is generated to use interrupt handling, then Global and Peripheral interrupts must be enabled in the main program.
     
        Mysil
    #5
    NorthGuy
    Super Member
    • Total Posts : 6404
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/31 11:13:36 (permalink)
    +2 (2)
    If you don't specifically need I2C and only need end-to-end communications (as opposed to a network), then UART is much easier to implement than I2C.
    #6
    ishkabum
    Starting Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2020/09/24 07:42:09
    • Location: Washington DC
    • Status: offline
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/10/31 11:54:24 (permalink)
    +1 (1)
    NorthGuy
    If you don't specifically need I2C and only need end-to-end communications (as opposed to a network), then UART is much easier to implement than I2C.


    I think I will take your suggestion and try just doing UART, because it does not specifically need to be I2C. The thought occurred to me the other day while I was stuck but I hadn't made that decision yet.. Just the thought of starting on something new and bypassing this mess makes me happy.
     
    Edit: WOW, you weren't kidding. After spending some 2 weeks trying to get I2C to work I got UART doing what I wanted first try in like 10 minutes. hahahahahahahahaha yes. onto other things.
    post edited by ishkabum - 2020/10/31 14:55:31
    #7
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 04:08:27 (permalink)
    0
    Hi,
    UART is a 'fire and forget  protocol',
    you try to transmit something, and computer have no way to tell if anyone is recieving the message,
    if the message is correct or garbled, or if the message is understood.
     
    This may be good enough if you want to dump diagnostic messages from a device in development,
    if a person is typing in text manually, and is supposed to observe the result before proceeding, or in similar cases.
     
    This is unless you add communication protocol in software, like Modbus,  LIN bus, ... there are many.
     
        Mysil
    #8
    oliverb
    Super Member
    • Total Posts : 342
    • Reward points : 0
    • Joined: 2009/02/16 13:12:38
    • Location: 0
    • Status: offline
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 04:38:00 (permalink)
    0 (2)
    FWIW the acknowledgement process in I2C isn't great, and I believe it wasn't unusual for devices to simply ignore it. It IS an enormous help with starting out with an unfamiliar device though, as having a confirmation that the device was successfully addressed is a big help compared to SPI where you can spend a long time looking at a "brick" if you don't nail the protocol exactly. What I'm saying is that even with I2C you'll probably have to implement some kind of protocol.
     
    There USED to be some good demo code to emulate a RAM device. There was a program posted to the forum for an older PIC type, and I seem to recall the MCC-generated code for a PIC18FxxK42 implementing RAM too. This is a good starting point as although there are limitations you can implement a crude interface just by using the array as a "mailbox".
     
    Things have probably got more complicated recently though (I'm out of touch). I'm used to the master implementation being old-school "blocking" code, but there appears to be a move towards buffered interrupt-controlled transfer which is a wonderful thing if you can manage it but much harder to learn.
     
    If you're starting out then I'd highly recommend playing with a software master implementation, mainly because you can use a debugger to single-step the code and see the pins change state, meaning you'll be able to directly measure whether the device acknowledged or not. I have used a software master to communicate with another PIC, though I'd quite like to convert it to a nonblocking implementation.
    #9
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 07:18:44 (permalink)
    0
    Hi,
    With two pic microcontrollers with I2C communication,
    you will need two PICkit or other debug tools, and 2 MPLAB  programs running at the same time.
    When you hit a breakpoint in slave code, and step with debugger,
    then one step too far, will make master code run away and end up in failed communication states, that do not happen when slave is running.
     
    It can be done, but is not easy, I have tried.
     
    On the other hand, hardware slave devices made for SMbus specifications,
    have timeout in hardware after about 10 milliseconds, so if you are not done with debugging within that time,
    slave will reset, and expect new start signal and address. So debugging master code with such a slave, may become confusing.
     
    It is MCC that push for using the same code both in Non-interrupt blocking code,
    and in code using interrupt service. 
     
    Code that actually use interrupts to perform I2C transfer in a non-blocking way, tend to become more complicated both in driver, and in application code.
    Also, interrupts to service I2C transfer operations, tend to become more complex and time-consuming,
    than other interrupt processing,
    so in a small microcontroller with only one interrupt vector, like all PIC16 devices, interrupt processing for I2C may become painful if there are other time-critical interrupts.
     
        Mysil
    post edited by Mysil - 2020/11/01 07:20:32
    #10
    ishkabum
    Starting Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2020/09/24 07:42:09
    • Location: Washington DC
    • Status: offline
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 08:31:44 (permalink)
    0
    Mysil
    Hi,
    With two pic microcontrollers with I2C communication,
    you will need two PICkit or other debug tools, and 2 MPLAB  programs running at the same time.
    When you hit a breakpoint in slave code, and step with debugger,
    then one step too far, will make master code run away and end up in failed communication states, that do not happen when slave is running.
     
    It can be done, but is not easy, I have tried.

    I have a Curiosity board + PICkit 4 and have tried to debug two interconnected but I can't connect the grounds + VDD so it doesn't work together. I would need another PICkit. If the application can withstand the delay I might be able to just send back from slave to master for confirmation before printing. It is for sending characters from keyboard and commands between PICs, so yeah messing up a character would mean the device doesn't work. But I'm not sure how much that would actually happen until I try it. Even if there's a fraction of a second delay between press and print due to multiple back and forths confirming the message, that would still be easier in UART.
     
    I've really tried to keep my determination strong and read up on I2C, check all the flags and registers, but I'm stuck on I2C and the Microchip support has led me with wrong info and just generally not been able to help. You guys on the forum are the best resource I have, I've looked through old threads and all that, but it hasn't been enough to get it to work. I didn't think it would be so hard. The last time I spoke with support they told me that I should buy a $700 logic analyzer. I really don't think that should be necessary. 
     
    Mysil
    Also, interrupts to service I2C transfer operations, tend to become more complex and time-consuming,
    than other interrupt processing,
    so in a small microcontroller with only one interrupt vector, like all PIC16 devices, interrupt processing for I2C may become painful if there are other time-critical interrupts.

    I did initially try to do without interrupts because I thought it would be easier. You were telling me that WriteNBytes should still work even though it's looking at SSP1IF. So it appears I was pretty close, but still I wasn't able to make it work. I was wondering if debugging works with I2C, support told me it does but if there's that time-out then I don't think it would. I don't think using I2C impossible but for now I'm abandoning it unfortunately as it's proven to be too difficult.
    post edited by ishkabum - 2020/11/01 08:33:29
    #11
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 11:04:52 (permalink)
    0
    Hi,
    I have no doubt, a logic analyzer is a useful instrument for studying communication signals,
    and debugging microcontroller software. 
     
    But it do not have to cost $700, 
    although Saleae Logic is well recognized, and have good software.
    I do not know if Logic 4  is available any more, it was plagued with cheap clones.
     
    Actually, hardware for a logic analyzer for signal frequencies up to some MHz,
    is actually not very complicated or expensive.
    It is development of software for presentation and control of all the features,
    that make it a product of commercial value, together with cost of marketing and support.
     
    A Logic analyzer is also a suitable subject for some open source development
    Here is an alternative with lower cost: https://www.sparkfun.com/products/15033
     
    Or a oscilloscope with 2 channels, may be even better for studying I2C signals.
     
    Actually, there is hardware needed for 2 channels with sampling rate up to about 100 kHz,
    available in about every PC computer. See Visual Analyser http://www.sillanumsoft.org/
     
    Here is a low cost alternative, it can do one analog channel and 4 logic channels:
    https://www.picotech.com/.ta-logger/drdaq/overview
    The styling may seem somewhat strange, but it is actually a serious company.
    I have a more expensive 4 channel instrument from the same company, and use it regularly, for timing measurements, and also for I2C if needed.
     
    Some people will say that they prefer a instrument with it's own screen, and real knobs.
    There is a wide range of capabilities and price: https://www.tek.com/oscilloscope
     
        Mysil
    post edited by Mysil - 2020/11/01 12:03:16
    #12
    upand_at_them
    Super Member
    • Total Posts : 739
    • Reward points : 0
    • Joined: 2005/05/16 07:02:38
    • Location: Pennsylvania
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 11:50:37 (permalink)
    0
    MysilA Logic analyzer is also a suitable subject for some open source development
    Here is an alternative with lower cost: https://www.sparkfun.com/products/15033

     
    And there are even lower cost ones on eBay.  FWIW, all are likely made in China.
    #13
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/01 12:28:57 (permalink)
    0
    Hi,
    There is a video here:  https://www.eevblog.com/f...clone-saleae-logic-16/
    and a open source project  sigrok  : https://sigrok.org/
     
        Mysil
     
    Edit:
    Also see trossin  thread here showing how to use a PIC18  microcontroller for Logic Analyzer: 
    https://www.microchip.com...FindPost/1156316 
     
        Mysil
    post edited by Mysil - 2020/11/05 03:28:43
    #14
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: I2C communication with two PIC18F47Q10. Does anyone know how to do this? 2020/11/05 04:15:27 (permalink)
    0
    Hi,
    There is an alarming statement in message #14:
    I have a Curiosity board + PICkit 4 and have tried to debug two interconnected but I can't connect the grounds

    Why?
     
    If connecting communication lines between PIC microcontrollers, then (ground)VSS lines should also be connected.
    If two debug tools, like Curiosity board and PICkit 4 is connected to the same PC computer, then there is ground connection thru screen of USB connectors.
    If there is other communication or power supply equipment, then all should be conneected to the same ground (PE).
     
    If there are two different computers connected to Curiosity board and PICkit 4,
    then it is my opinion that Chassis of both computers should be connected together, before any other connections are made.
    If one of the computers is a laptop with a power adapter connected to mains power with a 2 pin plug,
    or powered from a outlet that is not grounded, then grounding the chassis together may be especially important.
     
    Anyway, I2C connections between separate boards should be done with twisted pair wiring,
    one signal wire twisted with ground wire for SDA, and another pair for SCL signal and Vss.
    Vcc or Vdd should not be connected between boards if there are separate power supplies for each board.
     
        Mysil
    post edited by Mysil - 2020/11/05 06:01:31
    #15
    Jump to:
    © 2020 APG vNext Commercial Version 4.5