• AVR Freaks

PIC I2C Maste receive works once, and then hangs.

Author
FermiTin
New Member
  • Total Posts : 9
  • Reward points : 0
  • Joined: 2019/05/10 08:05:19
  • Location: 0
  • Status: offline
2019/11/30 08:24:08 (permalink)
0

PIC I2C Maste receive works once, and then hangs.

Hello,
 
I have PIC18F24k22 as a master and PIC18F14k22 as a slave. I2C Master to slave data sending works. I am also able to receive data from the slave into the master... Once. Then, as in the code shown, it looks like it tries only once to received data, then somewhere hangs. Any ideas? Can't get a ossciloscope at this time...
 
I am just going to upload my whole project, will be simpler i think.
https://drive.google.com/...zvtiohQAcZ?usp=sharing

Main_Module_3 is the main board (PIC18F24k22) Master. All the I2C code is written as I2C_master.c etc...
Wire_module is the slave board (PIC18F14K22). All of the I2C code is pretty much the same, just adapted for the slave part.

If you want, i can post I2C code seperatly, but then there will be a lot of unknown variables.
#1

4 Replies Related Threads

    Mysil
    Super Member
    • Total Posts : 3488
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC I2C Maste receive works once, and then hangs. 2019/11/30 12:23:55 (permalink)
    0
    Hi,
    Have found and downloaded the files, and just started looking into what is there.
    Doesn't look to bad at first.
    Have seen in  I2C_Master_Init() that it seem to enable interrupts, IEC1bits.SSPIE,  GIE and PEIE.
    This may trip you up when running, if there isn't  interrupt service code to handle those interrupts that occur.
    With the type of I2C_Master code you are writing, interrupts are not needed.
     
    When testing and debugging I2C_Slave code, I usually find it easier  to use a single PIC to run both Master and Slave code on 2 different I2C peripherals on the same microcontroller, at first.
    Then the master do not run away when you stop for debugging in slave code.
    When that work successfullly, you may try with slave code on the other microcontroller.
    With a different I2C slave address for each slave.
     
        Mysil
    #2
    Mysil
    Super Member
    • Total Posts : 3488
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC I2C Maste receive works once, and then hangs. 2019/11/30 21:12:49 (permalink)
    +1 (1)
    Hi,
    Have tried the master code, on a similar PIC18, and got it to work,
    reading a number of bytes from a known good I2C slave running on another PIC microcontroller.
    This is code to read a number of bytes in sequence, using the building blocks in your program:
    //Read multiple bytes from slave. 
    signed char I2C_Master_Read_Nbytes_With_Address(unsigned char ReadData[], unsigned char NRead, unsigned short address){
        unsigned char index = 0;

        if (SSPSTATbits.S)            /* Check that Bus is not in use already. */
            return -2;
        
        I2C_Master_Start();             
        while(SSPCON2bits.SEN);          /* This have been taken care of inside I2C_MasterStart() */
        
        if (PIR2bits.BCLIF)              /* Check if Bus Collision have happened. */
        {    PIR2bits.BCLIF = 0;
            return -3;                     /* Return with error flag. */
        }
        I2C_Master_Write(address | 1);   /* To make sure that address is a Read address, use (address | 1); */
        
        if (SSPCON2bits.ACKSTAT)         // NACK have been detected inside I2C_Master_Write
            return -2;                   // and transfer have been stopped, go back to square One.

        while (NRead)                       /* Loop to read multiple bytes. */
        {   SSPCON2bits.RCEN = 1;
            while(SSPCON2bits.RCEN);

            ReadData[index] = SSPBUF;
            index++;
            if (NRead > 1)
            {   SSPCON2bits.ACKDT = 0;      // ACK to continue receiving
                SSPCON2bits.ACKEN = 1;      //Start sending ACK
            }
            else                            /* Last byte in transfer have been received. */
            {   SSPCON2bits.ACKDT = 1;      //NACK to finish receiving
                SSPCON2bits.ACKEN = 1;      //Start sending NACK
            }
            while (SSPCON2bits.ACKEN);      /* Wait for Acknowledge signal to complete. */
            NRead --;
        }
        I2C_Master_Stop();

        PIR1bits.SSPIF = 0;
        return 0;
    }  

     
    Here is a snippet for the header file:
    /**
       @Description
        Read multiple bytes from slave.
       @Param
            ReadData[]    Pointer to array or buffer to receive data from slave
       @Param
            NBytes        Number of bytes to ask for.
       @Param
            Address       I2C Bus address of slave.
        
       @Returns
            Error code
     */
    signed char I2C_Master_Read_Nbytes_With_Address(unsigned char ReadData[], unsigned char NRead, unsigned short address);  

     
    Note, that there are some inconsistencies in the building blocks of your I2C code.
    In some functions, state of previous transfer is checked by:  I2C_Master_Wait();
    before the next transfer is started.
    Some functions use one of the 5 action bits in SSPCON2  register to wait for operation to complete,
    other functions use the interrupt flag PIR1bits.SSPIF  to wait for operation to complete.
    Some functions Clear the Interrupt Flag bit  SSPIF = 0; after operation is complete, other do not.
    If you really want to use SSPIF bit for checking,
    I think it is better to Clear the flag in the same function, before the operation is started. 
    Assuming that some other function have cleared the SSPIF bit, is risky.
     
    There are 2 generally different ways to use the 5 action bits in SSPCON2 for checking completion of I2C master operations.
    One way, is to use the individual bits:  SEN, PEN, RSEN, RCEN and ACKEN before leaving the function that started the operation. It is done that way in  I2C_Master_Stop(), and several other functions.
     
    The other way is to check that previous operation is completed,
    by calling I2C_Master_Wait();  Before the next operation is started.
    This may be a little faster, since you may let the I2C hardware work,
    while the program prepare the next operation, or do something else.
     
    I haven't looked into the slave code yet.
     
    Regards,
        Mysil
    #3
    FermiTin
    New Member
    • Total Posts : 9
    • Reward points : 0
    • Joined: 2019/05/10 08:05:19
    • Location: 0
    • Status: offline
    Re: PIC I2C Maste receive works once, and then hangs. 2019/12/01 23:00:27 (permalink)
    0
    Wow, thank you Mysil. I will try it this week. Thank you.
    #4
    Mysil
    Super Member
    • Total Posts : 3488
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC I2C Maste receive works once, and then hangs. 2019/12/02 17:22:51 (permalink)
    0
    Hi,
    Here are two package projects attached, that are able to write and read test arrays.
     
    Logic for slave module was to simplistic.
    There are 4 possible states for 2 bits
        ( SSPSTATbits.D_nA == 1)    Data,  second and following bytes.
        ( SSPSTATbits.D_nA == 0)    Address, first byte in transfer.
        ( SSPSTATbits.R_nW == 1)    Read, as seen by Master.
        ( SSPSTATbits.R_nW == 0)    Write, as seen by Master.
    And all 4 combinations have to be handled.
     
    I have not made any attempt to debug the application logic.
     
    Regards,
        Mysil
    #5
    Jump to:
    © 2019 APG vNext Commercial Version 4.5