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.

[SOLVED] [Moved] Enabling I2C - PIC24FJ128GB202

Status
Not open for further replies.

mrclolveira

Junior Member level 1
Joined
Oct 17, 2013
Messages
15
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
92
Hi guys,
I am using Pic24fj128gb202 on i2c aplication, but I can not make it work!
Nothing happens in the SDA/SCL pins.

I am using the following code for init
Code:
void initI2C()
{
    long Fscl = 100000;
    I2C1BRG = (FCY/(2*Fscl))-1;  // baud rate 100 KHz
    
    I2C1CONLbits.I2CEN = 0;  
    
    I2C1CONLbits.A10M = 0;
    I2C1CONLbits.SCLREL = 1;
    I2C1CONLbits.I2CSIDL = 1;
    I2C1CONLbits.DISSLW = 1;
    I2C1CONLbits.SMEN = 0;
    
    I2C1CONHbits.SDAHT = 0; 
    
    I2C1CONLbits.I2CEN = 1;    
}

I am using de SDA1/SCL1 so in the configuration bits are
Code:
I2C1SEL_DISABLE

In datasheet says:
bit 15 I2CEN: I2Cx Enable bit (writable from SW only)
1 = Enables the I2C™ module, and configures the SDAx and SCLx pins as serial port pins
0 = Disables I2C module; all I2C pins are controlled by port functions

But i cant understand what is "writable from SW only", someone can help me?
 

I2CEN bit has to be set to turn on I2C module. How are the I2C pins TRISx is set ?
 

this code was used on a PIC24FJ256GB110
Code:
// i2cFunctions.c - to drive I2C2 interface


#define USE_AND_OR
#include "i2c.h"
#include "Hardware.h"
#include "stdio.h" 
#include "timer.h" 


static int I2C2address=0; 		// address of I2C2 device

//    This routine is used to write a byte to the I2C2 bus. The input parameter data_out is written to the 
//    I2C2TRN register. If IWCOL bit is set,write collision has occured and -1 is returned, 
//    if acknowledge timeout return -2, else 0 is returned.			 
char MasterWriteI2C2(const unsigned char data_out)
{
    I2C2TRN = data_out;						// write data byte
    if(I2C2STATbits.BCL) 
       { printf("I2C Master bus collision detect %0x\n", I2C2STAT); return -1; }        /* If write collision occurs,return -1 */
    if(I2C2STATbits.IWCOL) 
       { printf("I2C write collision detect %0x\n", I2C2STAT); return -1; }        /* If write collision occurs,return -1 */
    int timeOutCount=10000;
    while(I2C2STATbits.TBF || I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT || I2C2STATbits.ACKSTAT)
       if(!timeOutCount--) { printf("\n\rMasterWriteI2C2 address %#x timeout config %#x status %#x \n\r", I2C2address, I2C2CON, I2C2STAT);	return -2; }
    //    printf(" %0x ", I2C2STAT);
    return 0;
}

//  This routine is used to write out an array to the 
// I2C2 bus.If write collision occurs,-3 is sent.If 
//  Nack is received, -2 is sent.If arrayis written 0 is returned. 				 
static unsigned int MasterPutArrayI2C2(const unsigned char * wrptr, int count)
{
    int i=0;
    while(count--)                           //transmit data
    {
        if((i=MasterWriteI2C2(*wrptr)) < 0) return i;	    // write a byte - return on error
        wrptr++;
    }
    return 0;			
}

// write to I2C2 address array wrptr of length, if sendStop is 1 send a STOP at end
int writeI2C2(const int address, const unsigned char *wrptr, int length, int sendStop)
  {
   unsigned int i2cbrg=((SYSCLK/100000L)-(SYSCLK/1111111L))-1;	/* Baud rate is set for 100 Khz */  
   unsigned int config1 = (I2C_ON | I2C_IDLE_CON | I2C_CLK_HLD	/* Configure I2C for 7 bit address mode */
     | I2C_IPMI_DIS | I2C_7BIT_ADD   | I2C_SLW_DIS | I2C_SM_DIS |
     I2C_GCALL_DIS | I2C_STR_DIS |   I2C_NACK | I2C_ACK_DIS | I2C_RCV_DIS |
     I2C_STOP_DIS | I2C_RESTART_DIS  | I2C_START_DIS);
   // problem with Master bus colision on PIC24s, see
   //   http://forum.microchip.com/tm.aspx?m=271183&mpage=1&key=
   TRISAbits.TRISA3=0;
   LATAbits.LATA3 = 0;   //where LATBx = the SDAx pin
   LATAbits.LATA3 = 1;
   OpenI2C2(config1,i2cbrg);									/* open the I2C2 device */
   //printf("\nwrite I2C2 %#x %0x %0x I2C stat %0x \n", address,config1,i2cbrg,I2C2STAT);
   IdleI2C2();
   StartI2C2();												/* send START */
   while(I2C2CONbits.SEN );									/* Wait till Start sequence is completed */
   if(MasterWriteI2C2(I2C2address=address) < 0) return -1;	/* Write Slave address and set master for transmission */
   if(MasterPutArrayI2C2(wrptr, length) < 0) return -1;		/* Transmit string of data */
   if(!sendStop) return 0;
   StopI2C2();												/* send STOP */
   while(I2C2CONbits.PEN);									/* Wait till stop sequence is completed */
   CloseI2C2();
   return 0;
}


// read from I2C2 device address
// initially send tx_data (length tx_length), restart and read rx_length bytes into rs_data
int readI2C2(int address, unsigned char *tx_data, int tx_length, unsigned char * rx_data, int rx_length)
{
   //int i;
   unsigned int i2c_data_wait= 11152;
   //printf("\n\rread I2C2 %#x ", address);
   writeI2C2(address,tx_data, tx_length, 0);		// send address and register number etc
   RestartI2C2();     							// send RESTART ready for a read!
   while(I2C2CONbits.RSEN );						// wait for restart complete 
   if(MasterWriteI2C2(address+1)<0)return -1;	/* Write Slave address and set master for read */   
   if(MastergetsI2C2(rx_length, rx_data, i2c_data_wait)!=0)return -1;	// read data from slave
   // uart2_puts("\n\rread  ");
   // for(i=0;i<rx_length;i++) { printHex(rx_data[i],uart2_putchar); uart2_putchar(' ');}
   StopI2C2();									/* send stop */  
   while(I2C2CONbits.PEN);						/* Wait till stop sequence is completed */
   CloseI2C2();									// close I2C2 device
   return 0;
}
 

this code was used on a PIC24FJ256GB110
Code:
// i2cFunctions.c - to drive I2C2 interface


#define USE_AND_OR
#include "i2c.h"
#include "Hardware.h"
#include "stdio.h" 
#include "timer.h" 


static int I2C2address=0; 		// address of I2C2 device

//    This routine is used to write a byte to the I2C2 bus. The input parameter data_out is written to the 
//    I2C2TRN register. If IWCOL bit is set,write collision has occured and -1 is returned, 
//    if acknowledge timeout return -2, else 0 is returned.			 
char MasterWriteI2C2(const unsigned char data_out)
{
    I2C2TRN = data_out;						// write data byte
    if(I2C2STATbits.BCL) 
       { printf("I2C Master bus collision detect %0x\n", I2C2STAT); return -1; }        /* If write collision occurs,return -1 */
    if(I2C2STATbits.IWCOL) 
       { printf("I2C write collision detect %0x\n", I2C2STAT); return -1; }        /* If write collision occurs,return -1 */
    int timeOutCount=10000;
    while(I2C2STATbits.TBF || I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT || I2C2STATbits.ACKSTAT)
       if(!timeOutCount--) { printf("\n\rMasterWriteI2C2 address %#x timeout config %#x status %#x \n\r", I2C2address, I2C2CON, I2C2STAT);	return -2; }
    //    printf(" %0x ", I2C2STAT);
    return 0;
}

//  This routine is used to write out an array to the 
// I2C2 bus.If write collision occurs,-3 is sent.If 
//  Nack is received, -2 is sent.If arrayis written 0 is returned. 				 
static unsigned int MasterPutArrayI2C2(const unsigned char * wrptr, int count)
{
    int i=0;
    while(count--)                           //transmit data
    {
        if((i=MasterWriteI2C2(*wrptr)) < 0) return i;	    // write a byte - return on error
        wrptr++;
    }
    return 0;			
}

// write to I2C2 address array wrptr of length, if sendStop is 1 send a STOP at end
int writeI2C2(const int address, const unsigned char *wrptr, int length, int sendStop)
  {
   unsigned int i2cbrg=((SYSCLK/100000L)-(SYSCLK/1111111L))-1;	/* Baud rate is set for 100 Khz */  
   unsigned int config1 = (I2C_ON | I2C_IDLE_CON | I2C_CLK_HLD	/* Configure I2C for 7 bit address mode */
     | I2C_IPMI_DIS | I2C_7BIT_ADD   | I2C_SLW_DIS | I2C_SM_DIS |
     I2C_GCALL_DIS | I2C_STR_DIS |   I2C_NACK | I2C_ACK_DIS | I2C_RCV_DIS |
     I2C_STOP_DIS | I2C_RESTART_DIS  | I2C_START_DIS);
   // problem with Master bus colision on PIC24s, see
   //   http://forum.microchip.com/tm.aspx?m=271183&mpage=1&key=
   TRISAbits.TRISA3=0;
   LATAbits.LATA3 = 0;   //where LATBx = the SDAx pin
   LATAbits.LATA3 = 1;
   OpenI2C2(config1,i2cbrg);									/* open the I2C2 device */
   //printf("\nwrite I2C2 %#x %0x %0x I2C stat %0x \n", address,config1,i2cbrg,I2C2STAT);
   IdleI2C2();
   StartI2C2();												/* send START */
   while(I2C2CONbits.SEN );									/* Wait till Start sequence is completed */
   if(MasterWriteI2C2(I2C2address=address) < 0) return -1;	/* Write Slave address and set master for transmission */
   if(MasterPutArrayI2C2(wrptr, length) < 0) return -1;		/* Transmit string of data */
   if(!sendStop) return 0;
   StopI2C2();												/* send STOP */
   while(I2C2CONbits.PEN);									/* Wait till stop sequence is completed */
   CloseI2C2();
   return 0;
}


// read from I2C2 device address
// initially send tx_data (length tx_length), restart and read rx_length bytes into rs_data
int readI2C2(int address, unsigned char *tx_data, int tx_length, unsigned char * rx_data, int rx_length)
{
   //int i;
   unsigned int i2c_data_wait= 11152;
   //printf("\n\rread I2C2 %#x ", address);
   writeI2C2(address,tx_data, tx_length, 0);		// send address and register number etc
   RestartI2C2();     							// send RESTART ready for a read!
   while(I2C2CONbits.RSEN );						// wait for restart complete 
   if(MasterWriteI2C2(address+1)<0)return -1;	/* Write Slave address and set master for read */   
   if(MastergetsI2C2(rx_length, rx_data, i2c_data_wait)!=0)return -1;	// read data from slave
   // uart2_puts("\n\rread  ");
   // for(i=0;i<rx_length;i++) { printHex(rx_data[i],uart2_putchar); uart2_putchar(' ');}
   StopI2C2();									/* send stop */  
   while(I2C2CONbits.PEN);						/* Wait till stop sequence is completed */
   CloseI2C2();									// close I2C2 device
   return 0;
}

I can't use I2C.h, because its not bluid for PIC24FJ128GB202 yet :sad:
 

What device are you communicating with I2C ? EEPROM ?
 

yes, its a eeprom, AT24CM01 - Atmel
 

How are the I2C pins TRISx is set ?
Not necessary, setting I2CEN transfers the pin control to the I2C module.

I2C1SEL_DISABLE
What does this setting mean? Which compiler are you using? "I2C1SEL_DISABLE" isn't Microchip syntax, I think.

What do you expect to see? SDA and SCL will be in tristate before after your initI2C() routine. If you are executing any other meaningful code, you should show it.
 

I've programmed this eeprom with a PIC18F, and works fine. But for this pic i just dont know what is this "writable from SW only".

- - - Updated - - -

I am using XC16 compiler.

I2C1SEL: Alternate I2C1 Location Select bit

following the full code
Code:
#define envia_restart_i2c1()  I2C1CONLbits.RSEN = 1;
#define envia_start_i2c1()  I2C1CONLbits.SEN = 1;
#define envia_stop_i2c1()   I2C1CONLbits.PEN = 1;
#define escreve_mestre_i2c1(x) I2C1TRN = x;

void send_ack()
{
    I2C1CONLbits.ACKDT = 0;
    I2C1CONLbits.ACKEN = 1;    
}
void send_nack()
{
    I2C1CONLbits.ACKDT = 1;
    I2C1CONLbits.ACKEN = 1;
}

void send_i2c1()
{
    Nop();
    Nop();
    Nop();
    Nop();
    
    while(I2C1CONLbits.SEN || I2C1CONLbits.PEN || I2C1CONLbits.RCEN || I2C1CONLbits.ACKEN || I2C1STATbits.TRSTAT);
}

unsigned char read_master_i2c1()
{
    I2C1CONLbits.RCEN = 1;
    send_i2c1();
    I2C1STATbits.I2COV = 0;
    return(I2C1RCV);
}

void initI2C()
{
    long Fscl = 100000;
    I2C1BRG = (FCY/(2*Fscl))-1;  // baud rate 100 KHz
    
    I2C1CONLbits.I2CEN = 0;  
    
    I2C1CONLbits.A10M = 0;
    I2C1CONLbits.SCLREL = 1;
    I2C1CONLbits.I2CSIDL = 1;
    I2C1CONLbits.DISSLW = 1;
    I2C1CONLbits.SMEN = 0;
    
    I2C1CONHbits.SDAHT = 0; 
    
    I2C1CONLbits.I2CEN = 1;    
}

void write_eeprom_i2c(unsigned int endereco, unsigned char dado)
{
    unsigned char endereco_high, endereco_low;
    endereco_high = endereco>>8;
    endereco_low  = endereco;
    
    envia_start_i2c1();
    send_i2c1();
    
    escreve_mestre_i2c1(0b10100000);
    
    send_i2c1();
    escreve_mestre_i2c1(endereco_high);
    send_i2c1();
    escreve_mestre_i2c1(endereco_low);
    send_i2c1();
    escreve_mestre_i2c1(dado);
    send_i2c1();
    envia_stop_i2c1();
    __delay_ms(10);
}

char read_eeprom_i2c(unsigned int endereco)
{
    unsigned char endereco_high, endereco_low;
    unsigned char dado;
    
    endereco_high = endereco>>8;
    endereco_low  = endereco;
    
    envia_start_i2c1();
    send_i2c1();
    
    escreve_mestre_i2c1(0b10100000);
    
    send_i2c1();
    escreve_mestre_i2c1(endereco_high);
    send_i2c1();
    escreve_mestre_i2c1(endereco_low);
    send_i2c1();
    envia_restart_i2c1();
    send_i2c1();
    escreve_mestre_i2c1(0b10100001);
    
    send_i2c1();
    dado = read_master_i2c1();
    send_nack();
    send_i2c1();
    
    envia_stop_i2c1();
    return(dado);
    
}

int main(int argc, char** argv) {
    
    initUart3();
    
    initI2C();
    while(1)
    {
        if(bufferU3[0] == 'a')
        {
            write_eeprom_i2c(255,'Z');
            U3Write("OK");
        }
        if(bufferU3[0] == 's')
        {
            char dado[2];
            dado[0] = ':';
            dado[1] = read_eeprom_i2c(255);
            U3Write(dado);
        }
    }
}
 

Last edited:

But for this pic i just dont know what is this "writable from SW only".
It doesn't make sense. Most bits in the register are "writable from software only". I don't see the statement in any other popular PIC24F datasheet.

Instead of guessing about it's meaning, check if I2CEN is set with a MPLAB hardware debugger if you have doubts it is.
 

zip attached, thanks
 

Attachments

  • Teste.X.zip
    82.2 KB · Views: 67

Post #10 is updated. See it regarding I2C1SEL. If you are using ASCL1 and ASDA1 pins for I2C then maybe you have to disable ADC on those pins and make the pins digital IO. I don't know whether configuring those pins for I2C will disable ADC or not.
 
Last edited:

I am using SDA1 and SCL1,

Pin 18 - TDO/C1INC/C2INC/C3INC/RP9/SDA1/T1CK/CTED4/CN21/RB9
Pin 17 - TCK/RP8/SCL1/USBOEN/CTED10/CN22/RB8

to set the I2CSEL, I followed the panel on MPLAB
i2csel.png
 

Why is I2CEN bit 0 ? With that setting I2C will be OFF.

Code:
I2C1CONLbits.I2CEN = 0;
 

But in the end is set to
Code:
    I2C1CONLbits.I2CEN = 0;  
    
    I2C1CONLbits.A10M = 0;
    I2C1CONLbits.SCLREL = 1;
    I2C1CONLbits.I2CSIDL = 1;
    I2C1CONLbits.DISSLW = 1;
    I2C1CONLbits.SMEN = 0;
    
    I2C1CONHbits.SDAHT = 0; 
    
    I2C1CONLbits.I2CEN = 1;
 

After a lot time i notice the comparator analog function in the RB9, so i disable this
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top