Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

first byte get...next byte NOT get

Status
Not open for further replies.

hhhsssmmm

Member level 1
Joined
May 14, 2009
Messages
37
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,732
Howdee people.

I have just completed an I2C interface to get two PICs talking ... MASTER and SLAVE setup.

This is working......but after successfully reading the first byte from the SLAVE and displaying on MASTER LCD ....if the MASTER again requests to read another byte from the SLAVE....then the two PICs seem to lock up...or so it seems anyway....and i do not get any more bytes received from the SLAVE.

So in short my I2C link only works for the first byte reception...after which it locks up.

Please can someone help me here to fix this problem.

my setup is...

PIC18F4423 (MASTER) and PIC18F2420 (SLAVE)
Master @ 20Mhz ceramic clock
Slave @ 8MHz internal clock
compiler used C18

Below are my test codes of MASTER and SLAVE.

thank you

hhhsssmmm




Code:
MASTER CODE
--------------


void main(void)
{     

    unsigned char ABC, DEF, HIJ; //byte holding variables

    ABC = read_from_slave_PIC(0xD0); //reading from SLAVE PIC (address)

    DEF = read_from_slave_PIC(0xD0); //reading from SLAVE PIC (address)

    HIJ = read_from_slave_PIC(0xD0); //reading from SLAVE PIC (address)


    //PRINT FIRST BYTE
    SendLCD(0x80,0); //activate LCD line 1 ... col 1   
    //print the data byte on LCD
    SendLCD(ABC,1);  

       
    Delay10KTCYx(125); //250ms delay
       

    //PRINT SECOND BYTE
    SendLCD(0x81,0); //activate LCD line 1 ... col 2   
    //print the data byte on LCD
    SendLCD(DEF,1);  

   
    Delay10KTCYx(125); //250ms delay
   

    //PRINT THIRD BYTE
    SendLCD(0x82,0); //activate LCD line 1 ... col 3   
    //print the data byte on LCD
    SendLCD(HIJ,1);  


    while(1); //loop forever


} //end of main()



unsigned char read_from_slave_PIC(unsigned char address)
{

    unsigned char data_byte = 0; //variable to hold the data byte from the SLAVE

    OpenI2C(); //INITIALLIZE & Configure I2C PORT
   
    StartI2C(); //Generates a Start I2C condition
   
    IdleI2C(); //Loops until I2C BUS is Idle
   
    if(DataRdyI2C() == 0) //proceed if buffer is empty
    {           
   
        //Send WIRTE command to SLAVE ... LSB is '0' as the WRITE bit
   
        if(WriteI2C(address) == 0) //ACK not received from SLAVE                                       
        {

            I2C_Error(); //Stop and rest I2C if link between PICs fails

            while(1); //STOP program

        }       
       
        IdleI2C(); //Loops until I2C BUS is Idle    
           
    }       

    StopI2C(); //Generates a Stop I2C condition
   
    IdleI2C(); //Loops until I2C BUS is Idle   
   
    StartI2C(); //Generates a Start I2C condition
       
    IdleI2C(); //Loops until I2C BUS is Idle   
   
    if(DataRdyI2C() == 0) //proceed if buffer is empty
    {           
   
        //Send READ command to SLAVE ... LSB is '1' as the READ bit
   
        if(WriteI2C(address + 1) == 0) //ACK not received from SLAVE                                       
        {

            I2C_Error(); //Stop and rest I2C if link between PICs fails

            while(1); //STOP program

        }       
   
        IdleI2C(); //Loops until I2C BUS is Idle    
           
    }           
       
    data_byte = ReadI2C(); //read the received data from the SLAVE
   
    NotAckI2C(); //Generates a Not Ack condition after reading data
   
    StopI2C(); //Generates a Stop I2C condition
   
    IdleI2C(); //Loops until I2C BUS is Idle  

    return data_byte; //return data byte from SLAVE

}//end of read_from_slave_PIC()


void OpenI2C(void)
{

    //Reseting MSSP registers
    SSPCON1 = 0x00; // power on state
      SSPCON2 = 0x00; // power on state   

    //Selecting & Configuring I2C Master mode
    SSPCON1bits.SSPM3 = 1;
    SSPCON1bits.SSPM2 = 0;
    SSPCON1bits.SSPM1 = 0;
    SSPCON1bits.SSPM0 = 0;   
    SSPSTATbits.SMP = 1; //Slew rate set to NORMAL speed @ 100kHz   
    SSPADD = 0x63; //setting baud rate 100kHz (NORMAL)...PIC running @ 20MHz   
    SSPSTATbits.CKE = 0; //Disable SMBus   
    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit

    SSPCON1bits.SSPEN = 1; //Enable I2C Master port   

}//end of OpenI2C()


void NotAckI2C(void)
{

    SSPCON2bits.ACKDT = 1; // set acknowledge bit for NOT ACK

    SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence

}//end of NotAckI2C()


void IdleI2C(void)
{

    //Test and wait until I2C module is idle
    while ( (SSPCON2 & 0x1F) | (SSPSTATbits.R_W) )

        continue; //keep looping until idle

}//end of IdleI2C()


unsigned char DataRdyI2C(void)
{

    if(SSPSTATbits.BF == 1)  // test if buffer full bit is set    

        return 1;          // data in SSPBUF register

    else

        return 0;          // no data in SSPBUF register

}//end of DataRdyI2C()


unsigned char ReadI2C(void)
{

    SSPCON2bits.RCEN = 1;     // enable master for 1 byte reception

    while (SSPSTATbits.BF == 0); // wait until byte received 

    while(PIR1bits.SSPIF == 0); //wait for interrupt

    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit

    return SSPBUF;    // return with read byte

}//end of ReadI2C()


unsigned char WriteI2C(unsigned char data_out)
{

    SSPCON2bits.ACKSTAT = 1; //reset ACK bit flag

    SSPBUF = data_out;       // write single byte to SSPBUF

    if(SSPCON1bits.WCOL == 1)  // test if write collision occurred
    {

        SSPCON1bits.WCOL = 0;     //Reset collision bit

        while(SSPSTATbits.BF == 1);   // wait until write cycle is complete                                

    }

    while(PIR1bits.SSPIF == 0); //wait for interrupt

    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit

    if(SSPCON2bits.ACKSTAT == 0) //Was there an ACK sent from DS1307?

        return 1; //DS1307 sent ACK

    else

        return 0; //No ACK was sent

}//end of WriteI2C()


void StartI2C(void)
{

    SSPCON2bits.SEN = 1; //Initiate Start condition

    while(PIR1bits.SSPIF == 0); //wait for interrupt

    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit

}//end of StartI2C()


void StopI2C(void)
{

    SSPCON2bits.PEN = 1; //Generate Stop condition

    while(PIR1bits.SSPIF == 0); //wait for interrupt

    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit   

}//end of StopI2C()


void I2C_Error(void)
{   

    IdleI2C(); //Loops until I2C BUS is Idle        

    StopI2C(); //Generates a Stop I2C condition

    IdleI2C(); //Loops until I2C BUS is Idle               

}//end of I2C_Error()






SLAVE CODE
------------


void main(void)
{       

    //Reseting MSSP registers
    SSPCON1 = 0x00; // power on state
    SSPCON2 = 0x00; // power on state   
   
    //I2C SLAVE mode, 7 bit address, with Start & Stop bits interrupts enabled
    SSPCON1bits.SSPM3 = 1;
    SSPCON1bits.SSPM2 = 1;
    SSPCON1bits.SSPM1 = 1;
    SSPCON1bits.SSPM0 = 0;   
    SSPSTATbits.SMP = 1; //Slew rate set to NORMAL speed @ 100kHz   
    SSPADD = 0xD0; //SLAVE address is (7bit). Lsb is R/W flag bit
    SSPSTATbits.CKE = 0; //Disable SMBus   

    SSPCON1bits.CKP = 1; //Clock Released       
   
    SSPCON1bits.SSPEN = 1; //Enable I2C Master port                    
   
    SSPCON1bits.SSPOV = 0; //Clear Buffer Overflow

    PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit
   
    INTCONbits.INT0IF = 0;  //Reset the INT0 External Interrupt Flag bit

    INTCON = 0b10010000;  //Enables all high priority interrupts
                            //Disables all low priority peripheral interrupts
                          //Disable the TMR0 overflow interrupt
                          //Enables the INT0 external interrupt
                          //Disables the RB port change interrupt   
 

    d0 = SSPBUF; //clears BF


    d0 = 'R';  //assign data byte to be sent to MASTER   


    while(1); //loop forever


} //end of main()


void HighInterrupt (void)
{

    if(PIR1bits.SSPIF == 1) //if MSSP interrupt
    {   

        if(SSPSTATbits.S == 1) // Slave receives address/data after start
         {     
 
            if(SSPSTATbits.R_W == 1)    // Read request from master
            {                 
 
               SSPBUF = d0;             //load data byte for transmit           
   
               SSPCON1bits.CKP = 1;        // Release SCL line to start transmit              

               while(SSPSTATbits.BF == 1);    //stay here until BF is cleared
 
            }   
 
            //recieve data from master
            if (SSPSTATbits.D_A == 1)        // Data [not address]                                                

                d3 = SSPBUF;                 // get data           

        }

        if(SSPSTATbits.BF == 1) //buffer is full so empty it

            d4 = SSPBUF; // read buffer to clear flag

        PIR1bits.SSPIF = 0; //reset MSSP interrupt flag bit   

    }

}//end of HIGH ISR
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top