PIC18F26K22 i2c hardware help please

Discussion in 'Embedded Systems and Microcontrollers' started by portreathbeach, Jun 30, 2014.

  1. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I've managed to get the SPI hardware function of the PIC18F26K22 to work on serial 1, and the DAC function to work on the DAC output pin, but I can't get the i2c to work on serial 2.

    Please can someone tell me which registers need to be changed to get it to work.

    So far I have this:
    Code ( (Unknown Language)):
    1.  
    2.     TRISC = 0x00;
    3.     TRISB = 0x00010010;             // RB4 and RB1 inputs (i2c)
    4.     TRISA = 0b00001100;
    5.  
    6.     ANSELA = 0b00001100;            // All digital apart from RA3
    7.     ANSELB = 0x00;                  // All digital
    8.     ANSELC = 0x00;                  // All digital
    9.  
    10.     ADCON0bits.CHS = 0b11110;       // DAC
    11.  
    12.     CM1CON0 = 0x00;                 // comparitor 1 off
    13.    
    14.     CCP1CON = 0x00;
    15.  
    16.     PWM1CON = 0x00;
    17.     SRCON0 = 0x00;                  // SR latch control
    18.     SRCON1 = 0x00;                  // SR latch control
    19.  
    20.     PMD1 = 0b0001000;               // peripheral module disable CCP5
    21.     SSP1STAT = 0b01000000;          // data transfer on rising edge (bit 6 = 1)
    22.     SSP1CON1 = 0b00100000;          // SPI enable, master mode FOSC/4
    23.  
    24.     SSP2ADD = 0b00011000;           // i2c speed
    25.     SSP2CON1 = 0b00101000;          // i2c master mode
    26.     SSP2CON2 = 0;                   // clear control bits
    27.  
    28.  
    29.     OSCCON |= 0b01110000;            // 16MHz (bits 6,5,4 set to 111)
    30.  
    31. // CM2CON1bits.C1RSEL = 1;         // FVR BUF1 is routed to C1 Vref (RA3)
    32.  
    33.     VREFCON0bits.FVREN = 1;         // fixed voltage reference enabled
    34.     VREFCON0bits.FVRST = 1;         // fixed voltage output is ready to use
    35. // VREFCON0bits.FVREN = 0b10;      // voltage reference is 2.048v
    36.  
    37.     VREFCON1bits.DACEN = 1;         // DAC enabled
    38.     VREFCON1bits.DACLPS = 1;        // positive reference source
    39.     VREFCON1bits.DACOE = 1;         // DAC voltage output enabled
    40.     VREFCON1bits.DACPSS = 0b00;     // use VDD as reference
    41. // VREFCON1bits.DACPSS = 0b01;     // use VREF+ as reference
    42.     VREFCON1bits.DACNSS = 0;        // use VSS as -ve reference
    43.  
    This sets up the registers for the SPI on serial 1, the DAC, but the i2c on serial 2 doesn't seem to work.

    Also, has anyone got any sample code to get the bus running, I have this so far:

    Code ( (Unknown Language)):
    1. void i2c_start( void ){
    2.  
    3.     SSP2CON2bits.SEN = 1;
    4.     while(SSP2CON2bits.SEN == 0);       // Wait for condition to be sent
    5. }
    6.  
    7. //....................................................................
    8. // Sends the Repeated Start condition
    9. //....................................................................
    10. void i2c_repstart( void ){
    11.  
    12.     SSP2CON2bits.RSEN = 1;              // Enable Repeated Start condition
    13.     while(SSP2CON2bits.RSEN);        // Wait for condition to be sent
    14. }
    15.  
    16. //....................................................................
    17. // Sends the Stop condition
    18. //....................................................................
    19. void i2c_stop( void )
    20. {
    21.     SSP2CON2bits.PEN = 1;               // Enable Stop condition
    22.     while(SSP2CON2bits.PEN == 0);       // Wait for condition to be sent
    23. }
    24.  
    25. //....................................................................
    26. // Writes a byte to the I2C bus
    27. //....................................................................
    28. unsigned char i2c_write( unsigned char data )
    29. {
    30. //    i2c_idle();
    31.         PIR3bits.SSP2IF = 0;            // clear the SSP transmit finished interrupt flag
    32.         SSP2BUF = data;          // Loads the buffer with provided data
    33.         while(!PIR3bits.SSP2IF);        // wait for SSP interrupt flag to say transmit is finished
    34.     return(!SSP2CON2bits.ACKSTAT);  // Returns 1 if slave acknowledged
    35. }

    Basically, after I setup the registers, I call the i2c_start function and then the the i2c_write function with some data, then the stop function over and over and try to scope what I see. I see nothing on either pin.

    I would really like to get this working, or I'll have to return to my trusty bit banging routine which works perfectly.
     
  2. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,388
    497
    Write out in words your i2c procedure.
     
  3. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I know how the i2c protocol works as I have a bitbang version I wrote which communicates with a real time clock module to read and write to it, but I cannot get the hardware version on my PIC to work.

    Basically, I can't get my clock pulses of data pulses to display on my scope.

    To try to see if the SSP2 port is working I am simply calling

    i2c_Start, then sending some data with i2c_write, then i2c_stop. I am sending this in a loop just to see if anything is happening. Here is the updated code as I realise some of it was wrong:

    Code ( (Unknown Language)):
    1. //....................................................................
    2. // Waits for the I2C bus to go into Idle mode
    3. //....................................................................
    4. void i2c_idle()
    5. {
    6.     while ( ( SSP2CON2 & 0x1F ) || ( SSP2STAT & 0x04 ) ); //only continues when there is not imortant bit set
    7. }
    8.  
    9. //....................................................................
    10. // Sends the Start condition
    11. //....................................................................
    12. void i2c_start( void ){
    13.  
    14.      i2c_idle();
    15.      SSP2CON2bits.SEN=1;
    16.      while(SSP2CON2bits.SEN);
    17. }
    18.  
    19. //....................................................................
    20. // Sends the Repeated Start condition
    21. //....................................................................
    22. void i2c_repstart( void ){
    23.  
    24.     SSP2CON2bits.RSEN = 1;              // Enable Repeated Start condition
    25.     while(SSP2CON2bits.RSEN);        // Wait for condition to be sent
    26. }
    27.  
    28. //....................................................................
    29. // Sends the Stop condition
    30. //....................................................................
    31. void i2c_stop( void )
    32. {
    33.      i2c_idle();
    34.      SSP2CON2bits.PEN=1;
    35.      while(SSP2CON2bits.PEN);
    36. }
    37.  
    38. //....................................................................
    39. // Writes a byte to the I2C bus
    40. //....................................................................
    41. unsigned char i2c_write(unsigned char data)
    42. {
    43.     i2c_idle();
    44.     SSP2BUF = data;                     // Loads the buffer with provided data
    45.     return(!SSP2CON2bits.ACKSTAT);      // Returns 1 if slave acknowledged
    46. }
    I'm sure it's something to do with the configuration of the PIC, but I have made changes to all the relevent register, I think.
     
  4. Papabravo

    Expert

    Feb 24, 2006
    10,140
    1,790
    Do you have pullup resistors on SDA and SCL as required by the I2C specification.
     
  5. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    Yes, I have 4.7K on each line, like when I was bitbanging.

    I know tried this just to see if the port is working:
    Code ( (Unknown Language)):
    1.  
    2. while(1){
    3.             SSP2BUF = 0xFF;
    4.             SSP2CON2bits.SEN=1;
    5.             __delay_us(20);
    6.             SSP2CON2bits.PEN=1;
    7.             __delay_us(20);
    8. }
    But nothing. Both lines are staying high.
     
  6. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    I think it's definitely a config fault. If I could just get it to clock, I could figure the rest out
     
  7. portreathbeach

    Thread Starter Active Member

    Mar 7, 2010
    143
    5
    OK. I had a slight config error. I had set RB1 and RB4 as inputs instead of RB1 and RB2, I changed this but still seeing high level on both pins.

    EDIT: Finally got something working. I am sending the address of the real time clock module and when I remove the SDAT line, the acknowledge bit changes, so I know it must be communicating. It was a stupid config error, and not quite reading the datasheet properly.

    Thanks again for your help.
     
    Last edited: Jun 30, 2014
Loading...