• AVR Freaks

Hot!Deciding between I2C or UART

Author
acharnley
Super Member
  • Total Posts : 523
  • Reward points : 0
  • Joined: 2016/05/01 06:51:28
  • Location: 0
  • Status: offline
2020/03/30 12:49:27 (permalink)
0

Deciding between I2C or UART

I'm about to begin on inter-chip communication between a PIC16F1779 and a TI cc2541 BLE module. This module supports UART or I2C.

I only have two pins available. Data transfer is expected to be very low at probably a few 10's of bytes per second. The CPU on the PIC16 is moderately busy servicing interrupts and I'd like to keep the communication overhead light so as not to bottleneck how reactive it is to these.
 
Having not worked with I2C before, how much of the overhead work is done within the PIC16 peripheral? Are there any scenarios where the CPU is locked up in while loops or can it be all interrupt based like the UART? Finally, with i2C working between two chips on the same PCB, what error checking do you recommend, if any? This would have to be implemented with UART due to the baud rate error.

Any recommendations or related advice much appreciated before I begin. I took a quick look at the I2C foundation library Microchip offers (the newer ones) and it looks like a measure of work over UART to implement as there's no example code anywhere on how it works.
post edited by acharnley - 2020/03/30 13:29:58
#1

15 Replies Related Threads

    davea
    Super Member
    • Total Posts : 228
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/03/30 14:22:52 (permalink)
    +1 (1)
    UART is very simple to use 1 ISR per TX byte (fill an array sent it 10-20 instructions in ISR)  
    RX has a 2 CHR buffer (better not to use it if data is ODD number of bytes)
    I2C has some while loops, very short
    but when things go wrong, very hard to troubleshoot
    post edited by davea - 2020/03/30 14:25:15
    #2
    ric
    Super Member
    • Total Posts : 26942
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Deciding between I2C or UART 2020/03/30 14:34:21 (permalink)
    +1 (1)
    Yes I2C involves a lot more overhead per byte than UART.
    On the other hand, I2C is completely  controlled by the master, and can be slowed or paused at any time under control of the Master.
    So, as long as you implement it as a state machine, you can service it whenever your MCU is not busy doing other things, so it can be very low impact. No need for interrupts at all.
     

    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!
    #3
    acharnley
    Super Member
    • Total Posts : 523
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/03/30 15:46:15 (permalink)
    0
    The previous foundation services i2c library looked hugely complex whereas the new one appears to be little more than lots of bit setters. Unfortunately I can't find any documentation anywhere but perhaps I don't need it just an understanding of how i2c works and away I go.
     
    The master/slave won't be communicating at the same time. It'll be a case of the slave (BLE) receives a command/data and passes to the master (PIC) which will then respond. With this in mind will 'write collision', 'receive overflow' and 'bus collision' still require managing?



    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <xc.h>
    #include "device_config.h"
    #include "i2c_driver.h"

    #pragma warning disable 520        

    inline void i2c_driver_close(void)
    {
        SSP1CON1bits.SSPEN = 0;
    }

    /* Interrupt Control */
    inline void mssp_enableIRQ(void)
    {
        PIE1bits.SSP1IE = 1;
    }

    inline __bit mssp_IRQisEnabled(void)
    {
        return PIE1bits.SSP1IE;
    }

    inline void mssp_disableIRQ(void)
    {
        PIE1bits.SSP1IE = 0;
    }

    inline void mssp_clearIRQ(void)
    {
        PIR1bits.SSP1IF = 0;
    }

    inline void mssp_setIRQ(void)
    {
        PIR1bits.SSP1IF = 1;
    }

    inline __bit mssp_IRQisSet(void)
    {
        return PIR1bits.SSP1IF;
    }

    inline void mssp_waitForEvent(uint16_t *timeout)
    {
        //uint16_t to = (timeout!=NULL)?*timeout:100;
        //to <<= 8;

        if(PIR1bits.SSP1IF == 0)
        {
            while(1)// to--)
            {
                if(PIR1bits.SSP1IF) break;
                __delay_us(100);
            }
        }
    }

    __bit i2c_driver_open(void)
    {
        if(!SSP1CON1bits.SSPEN)
        {
            SSP1STAT = 0x00;
            SSP1CON1 = 0x28;
            SSP1CON2 = 0x00;
            SSP1ADD = 3;
            return true;
        }
        else
            return false;
    }

    __bit i2c_driver_initSlaveHardware(void)
    {
        if(!SSP1CON1bits.SSPEN)
        {

            SSP1CON1 |= 0x06; //setup I2C Slave (7-bit Addressing)
            SSP1STAT = 0x00;
            SSP1CON2 = 0x00;
            
            SSP1CON1bits.SSPEN = 1;
            return true;
        }
        return false;
    }

    inline void i2c_driver_resetBus(void)
    {
        
    }

    inline void i2c_driver_start(void)
    {
        SSP1CON2bits.SEN = 1;
    }

    inline void i2c_driver_restart(void)
    {
        SSP1CON2bits.RSEN = 1;
    }

    inline void i2c_driver_stop(void)
    {
        SSP1CON2bits.PEN = 1;
    }

    inline __bit i2c_driver_isNACK(void)
    {
        return SSP1CON2bits.ACKSTAT;
    }

    inline void i2c_driver_startRX(void)
    {
        SSP1CON2bits.RCEN = 1;
    }

    inline char i2c_driver_getRXData(void)
    {
        return SSP1BUF;
    }

    inline void i2c_driver_setAddr(char addr)
    {
        SSP1ADD = addr;
    }

    inline void i2c_driver_setMask(char mask)
    {
        SSP1MSK = mask;
    }

    inline void i2c_driver_TXData(char d)
    {
        SSP1BUF = d;
    }

    inline char i2c_driver_getAddr(void)
    {
        return SSP1ADD;
    }

    inline void i2c_driver_sendACK(void)
    {
        SSP1CON2bits.ACKDT = 0;
        SSP1CON2bits.ACKEN = 1; // start the ACK/NACK
    }

    inline void i2c_driver_sendNACK(void)
    {
        SSP1CON2bits.ACKDT = 1;
        SSP1CON2bits.ACKEN = 1; // start the ACK/NACK
    }

    inline void i2c_driver_releaseClock(void)
    {
        SSP1CON1bits.CKP = 1;
    }

    inline __bit i2c_driver_isBufferFull(void)
    {
        return SSP1STATbits.BF;
    }

    inline __bit i2c_driver_isStart(void)
    {
        return SSP1STATbits.S;
    }

    inline __bit i2c_driver_isAddress(void)
    {
        return !SSP1STATbits.D_nA;
    }

    inline __bit i2c_driver_isStop(void)
    {
        return SSP1STATbits.P;
    }

    inline __bit i2c_driver_isData(void)
    {
        return SSP1STATbits.D_nA;
    }

    inline __bit i2c_driver_isRead(void)
    {
        return SSP1STATbits.R_nW;
    }

    inline __bit i2c_driver_isWriteCollision(void)
    {
        return SSP1CON1bits.WCOL;
    }

    inline __bit i2c_driver_isReceiveOverflow(void)
    {
        return SSP1CON1bits.SSPOV;
    }

    inline void i2c_driver_clearBusCollision(void)
    {
        PIR2bits.BCL1IF = 0; // clear the bus collision.
    }

    inline void i2c_driver_setBusCollisionISR(interruptHandler handler){
        i2c_driver_busCollisionISR = handler;
    }

    inline void i2c_driver_setI2cISR(interruptHandler handler){
        i2c_driver_i2cISR = handler;
    }



    #4
    ric
    Super Member
    • Total Posts : 26942
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Deciding between I2C or UART 2020/03/30 15:53:40 (permalink)
    +1 (1)
    In I2C, the slave cannot spontaneously send data to the Master, the Master must poll the slave regularly to fetch data.
    That's the difference with USART. That lets the slave send whenever it wants
     
    The I2C Master will never get "write collision", "bus collision", or "receive overflow" if there is not another master on the bus.

    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!
    #5
    acharnley
    Super Member
    • Total Posts : 523
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/03/31 03:49:25 (permalink)
    0
    Hmm, I'm seeing potential overhead.

    The PIC responds to commands from the BLE chip, so it makes sense I think to make the BLE master. When the BLE receives a command/data it forwards it onto the PIC and will await for an acknowledgement or data for sending out.
     
    If the PIC (being slave) can't send this return data automatically, is it frequently responding to interrupt requests from the master for the permission to send? In which case the frequently would have a hit on data transfer speed, and also take up CPU time. Or can you load a buffer up with data and the peripheral hardware will send it out when it receives the permission from master?
    #6
    ric
    Super Member
    • Total Posts : 26942
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Deciding between I2C or UART 2020/03/31 03:55:57 (permalink)
    0
    Are you talking about UART, or I2C?
    If the PIC is time critical, I would NOT recommend making it an I2C slave, only Master.
     
    post edited by ric - 2020/03/31 03:57:26

    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
    acharnley
    Super Member
    • Total Posts : 523
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/03/31 05:32:28 (permalink)
    0
    I2C. If I make the PIC master does that mean it's polling the slave to see if any data is there? That's sounds worse!
    #8
    ric
    Super Member
    • Total Posts : 26942
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Deciding between I2C or UART 2020/03/31 12:20:25 (permalink)
    0
    That depends upon your definition of worse.
    Everything is controlled by the PIC, so you can do it when you're not busy doing something else.
    It doesn't matter of the I2C code pauses while an interrupt is being serviced.
     
    These are all tradeoffs that only YOU know the anwer to.
     

    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!
    #9
    acharnley
    Super Member
    • Total Posts : 523
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/03/31 12:36:48 (permalink)
    0
    If I know which questions to ask!

    I take it this is the main overhead over UART, granting the slave permission to respond?

    I still query why the PIC is better at being the master. A request comes in as APP -> BLE -> I2C -> PIC. The PIC wont push data unless a command is received first. If I make the PIC master then that means it must poll the slave frequently (grant it permission to "talk") to see if a command has been received, whereas if the BLE is master it only needs to grant the permission once a command has been received?
     
    The I2C won't be time critical, so true I could make that a task within the main loop rather than make it interrupt based.
     
     
    #10
    Hen
    Starting Member
    • Total Posts : 51
    • Reward points : 0
    • Joined: 2018/10/24 04:01:44
    • Location: 0
    • Status: online
    Re: Deciding between I2C or UART 2020/04/01 22:13:35 (permalink)
    0
    If interrupt is for what ever reason not available...
     
    If the BLE burst data rate is lower than the PIC capability, UART is probably the way to go.
    If not, I guess a PIC I2C master is required.
     
    Example:
    If the BLE bit rate is 115200 (±5%), the PIC UART receive task latency must be less than about 165µs.
    #11
    Antipodean
    Super Member
    • Total Posts : 1841
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re: Deciding between I2C or UART 2020/04/02 02:07:46 (permalink)
    0
    If you are looking at two processors on the same board or in the same box then I would suggest what is known as the TI-Link protocol.
    http://ubasics.com/adam/electronics/ti/link/tilink.shtml
    advantages are that it does not matter what the relative speeds of the processors are (one can be extremely fast, the other very slow) as the transfer rate is determined by the handshaking between the processors. It could be interrupt driven, but I would implement a state machine running at the lowest priority background task. another advantage is that you do not need any specific hardware peripherals, just any two pins with controllable tristate and a couple of pullup resistors. The protocol is bidirectional and quite simple so shouldn't take much code space at all.
     
    If using it between boards within a box then twisted pair with ground should be quite sufficient without shielding unless a very noisy environment. Worst case the transfer speed could be slugged in software to minimise any interference.
     
     
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #12
    ric
    Super Member
    • Total Posts : 26942
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Deciding between I2C or UART 2020/04/02 02:10:04 (permalink)
    0
    First sentence in post#1
    ... and a TI cc2541 BLE module. This module supports UART or I2C.

    So there's only two choices.

    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!
    #13
    Antipodean
    Super Member
    • Total Posts : 1841
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re: Deciding between I2C or UART 2020/04/02 03:33:53 (permalink)
    0
    ric
    First sentence in post#1
    ... and a TI cc2541 BLE module. This module supports UART or I2C.

    So there's only two choices.


    ah, that is what comes from catching up on posts when tired ... pink: pink
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #14
    rpg7
    Super Member
    • Total Posts : 1401
    • Reward points : 0
    • Joined: 2003/11/07 12:47:35
    • Status: offline
    Re: Deciding between I2C or UART 2020/04/02 04:36:42 (permalink)
    +1 (1)
    From experience, when you want asynchronous communication, the simplest is to use the UARTs. IIC will involve a lot of polling, especially as you don't have another pin to indicate 'data available' to the master from the slave. 115200 baud is about 10000 char per second, a small circular buffer filled using RX interrupts is easily examined in the main loop. IMNVHO using  IIC for this will be an exercise in self-flagellation.
     
    edit: I meant async at the byte level.
    post edited by rpg7 - 2020/04/02 04:37:43
    #15
    davea
    Super Member
    • Total Posts : 228
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: Deciding between I2C or UART 2020/04/02 08:44:46 (permalink)
    0
    acharnley
    I only have two pins available. Data transfer is expected to be very low at probably a few 10's of bytes per second. of

    then use a low baud rate, then you could poll the IF bits in main
    and you would be DONE by now...
    #16
    Jump to:
    © 2020 APG vNext Commercial Version 4.5