0
\$\begingroup\$

I am trying to configure an I2C protocol between a PIC18F25k80 and a barometric pressure sensor (the link for the datasheet is provided below). I can't figure out what the problem is. Initially it was giving a write collision error, which I think I managed to handle (correct me if I am wrong). However, the output signals from the clock and data lines do not look anything like the expected sequence for an I2C communication (No sign of start or stop sequences on the clock output).

Thank you


Link for sensor datasheet: http://www.farnell.com/datasheets/1756127.pdf



MAIN METHOD


/* 
 * File: main.c
 * Author: b2049814
 *
 * Created on 19 March 2015, 11:27
 */
// PIC18F25K80 Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
#include <p18cxxx.h>
#include <stdio.h>
#include <plib/pconfig.h>
#include <stdlib.h>
#include <plib/adc.h> //include file for ADC library functions
#include "i2cFunctions.h"
#include <delays.h>
#define I2C_SLAVEW 0b11101110
#define I2C_SLAVER 0b11101111
#define RESET_CMD 0b00011110
#define PROM_READ_CMD 0b10100110
#define PRESS_CONV_CMD 0b01001000
#define READ_ADC_CMD 0b00000000
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1L
#pragma config RETEN = ON // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = HIGH // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = INTIO1 // Oscillator (Internal RC oscillator, CLKOUT function on OSC2)
#pragma config PLLCFG = OFF // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power Up Timer (Disabled)
#pragma config BOREN = OFF // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 3 // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576 // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTB // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7 // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF // Code Protect 06000-07FFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF // Code Protect Boot (Disabled)
#pragma config CPD = OFF // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF // Table Write Protect 00800-03FFF (Disabled)
#pragma config WRT1 = OFF // Table Write Protect 04000-07FFF (Disabled)
#pragma config WRT2 = OFF // Table Write Protect 08000-0BFFF (Disabled)
#pragma config WRT3 = OFF // Table Write Protect 0C000-0FFFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF // Config. Write Protect (Disabled)
#pragma config WRTB = OFF // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protect 00800-03FFF (Disabled)
#pragma config EBTR1 = OFF // Table Read Protect 04000-07FFF (Disabled)
#pragma config EBTR2 = OFF // Table Read Protect 08000-0BFFF (Disabled)
#pragma config EBTR3 = OFF // Table Read Protect 0C000-0FFFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF // Table Read Protect Boot (Disabled)
void initIO( void );
//**************************************************
// main function
//**************************************************
int main() 
{
 initIO();
 initI2C();
 while(1)
 {
 writeI2C( I2C_SLAVEW, PRESS_CONV_CMD );
 }
 return (0);
}
//**************************************************
// InitIO function (initialises ports and oscillator)
//**************************************************
void initIO()
{
 OSCCON = 0x75;
 TRISAbits.TRISA1 = 1;
 TRISAbits.TRISA6 = 0;
 TRISAbits.TRISA5 = 0;
 TRISBbits.TRISB0 = 0;
 TRISCbits.TRISC3 = 1; // set SCL and SDA pins as inputs
 TRISCbits.TRISC4 = 1;
}

HEADER FILE (contains the functions used to configure the I2C protocol)


#ifndef i2cFunctions
#define i2cFunctions
void initI2C()
{
 // Master 100KHz
 SSPCON1 = 0b00101000; // I2C enabled, Master mode
 SSPCON2 = 0x00;
 // I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) 
 SSPADD = 19; // 100Khz @ 8Mhz Fosc
 SSPSTAT = 0b10000000; // Slew rate disabled
}
void startI2C()
{
 SSPCON2bits.SEN = 1; // initiate bus start condition
}
void stopI2C()
{
 SSPCON2bits.PEN = 1; // initiate bus stop condition
}
void restartI2C()
{
 SSPCON2bits.RSEN = 1; // initiate bus restart condition
}
void notAckI2C()
{
 SSPCON2bits.ACKDT = 1; // set acknowledge bit state for ACK
 SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence
}
void ackI2C()
{
 SSPCON2bits.ACKDT = 0; // set acknowledge bit state for ACK
 SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence
}
void idleI2C( void )
{
 while ( ( SSPCON2 & 0x1F ) || ( SSPSTATbits.R_W ) );
}
signed char writeByteI2C( unsigned char byte )
{
 SSPBUF = byte;
 if ( SSPCON1bits.WCOL ) // test if write collision occurred
 {
 return ( -2 ); // if WCOL bit is set return negative #
 }
 else
 {
 if ( ( ( SSPCON1&0x0F ) == 0x08 ) || ( ( SSPCON1&0x0F ) == 0x0B ) ) //master mode only
 { 
 while( SSPSTATbits.BF ); // wait until write cycle is complete 
 idleI2C(); // ensure module is idle
 if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
 {
 return ( -1 ); // return NACK
 }
 else
 {
 return ( 0 ); //return ACK
 } 
 }
 }
 return ( -2 );
}
unsigned char readByteI2C( void )
{
 if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) ) //master mode only
 SSPCON2bits.RCEN = 1; // enable master for 1 byte reception
 while ( !SSPSTATbits.BF ); // wait until byte received 
 return ( SSPBUF ); // return with read byte 
}
void writeI2C( unsigned char slaveAddressW, unsigned char command )
{
 signed char writeResult;
 idleI2C();
 startI2C();
 while(SSPCON2bits.SEN);
 do
 {
 SSPBUF = 0x00;
 writeResult = writeByteI2C( slaveAddressW );
 if ( writeResult == -2 ) //write collision handler
 {
 SSPBUF = 0x00; //Clearing buffer
 SSPCON1bits.WCOL = 0; //Clearing the write collision flag
 }
 }
 while ( writeResult != 0 ); //we're repeating transmission until ACK is received
 idleI2C();
 do
 {
 SSPBUF = 0x00;
 writeResult = writeByteI2C( command );
 if ( writeResult == -2 ) //write collision handler
 {
 SSPBUF = 0x00; //Clearing the junk in buffer
 SSPCON1bits.WCOL = 0; //Clearing the write collision flag
 }
 }
 while ( writeResult != 0 ); //we're repeating transmission until ACK is received
 stopI2C();
}
void readI2C( unsigned char slaveAddressR )
{
 unsigned char readSensor[3];
 idleI2C();
 startI2C();
 writeByteI2C( slaveAddressR );
 readSensor[0] = readByteI2C();
 ackI2C();
 readSensor[1] = readByteI2C();
 ackI2C();
 readSensor[2] = readByteI2C();
 notAckI2C();
 stopI2C();
}
#endif

The output capture seems to repeat.

The part number of the sensor is MS5607-02BA03, but the datasheet was already included.

(Green: Clock, Purple: Data)



Output


enter image description here


Output zoomed in


enter image description here


One way to fix this would be to modify your I2C functions to wait until their associated operation completes before they return. For example:

void startI2C()
{
 SSPCON2bits.SEN = 1; // initiate bus start condition
 while (SSPCON2bits.SEN); // wait for bus start condition to complete
}

and the same for every other I2C function.

Another alternative would be to make an IdleI2C() call in between every single I2C operation, like:

IdleI2C();
startI2C();
IdleI2C();
writeByteI2C( slaveAddressR );
IdleI2C();
etc ... 

I tried both ways but the output doesn't seem to change at all.


I tried debugging it again. It looks like the first time it attempts to write something in the buffer register it fails and it returns with a write collision. And it keeps doing that forever because it gets stuck in the do while loop I am using to handle a write collision.


asked Apr 8, 2015 at 10:47
\$\endgroup\$
1
  • \$\begingroup\$ Do you have a scope capture of the waveform that you can upload? What's the part number of the barometric sensor? \$\endgroup\$ Commented Apr 8, 2015 at 10:54

1 Answer 1

1
\$\begingroup\$

You need to wait for any and all I2C operations to complete in a PIC before you initiate the next one. This is what's causing your bus collisions.
For example in your code you have:

startI2C();
writeByteI2C( slaveAddressR );

and the problem here is that you aren't waiting for the start condition to finish before initiating the byte-write.

One way to fix this would be to modify your I2C functions to wait until their associated operation completes before they return. For example:

void startI2C()
{
 SSPCON2bits.SEN = 1; // initiate bus start condition
 while (SSPCON2bits.SEN); // wait for bus start condition to complete
}

and the same for every other I2C function.

Another alternative would be to make an IdleI2C() call in between every single I2C operation, like:

IdleI2C();
startI2C();
IdleI2C();
writeByteI2C( slaveAddressR );
IdleI2C();

etc ...

answered Apr 8, 2015 at 12:59
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.