Author Topic: Help getting a PIC I2C working  (Read 1631 times)

0 Members and 1 Guest are viewing this topic.

Offline JayboyTopic starter

  • Newbie
  • Posts: 2
  • Country: au
Help getting a PIC I2C working
« on: January 30, 2017, 06:03:14 am »
Hi,

I'm just starting to get into micros again after many years away. I'm trying to interface a PIC 16F1459 to a DS1307 RTC chip.

I'm getting a bit stuck using the PICs MSSP module. For some reason if I step though my program with a pickit3 the i2c signals look fine on the DSO. But when I run it at full speed there is no activity. I not sure if ive mucked up something with the clock speeds etc..

Any ideas?

Code: [Select]
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = ON   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config CPUDIV = CLKDIV6 // CPU System Clock Selection Bit (CPU system clock divided by 6)
#pragma config USBLSCLK = 48MHz // USB Low SPeed Clock Selection bit (System clock expects 48 MHz, FS/LS USB CLKENs divide-by is set to 8.)
#pragma config PLLMULT = 3x     // PLL Multipler Selection Bit (3x Output Frequency Selected)
#pragma config PLLEN = ENABLED  // PLL Enable Bit (3x or 4x PLL Enabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
#define _XTAL_FREQ 8000000
#include <xc.h>

#define d1lat LATCbits.LATC7
#define d2lat LATCbits.LATC6
#define d3lat LATCbits.LATC5
#define d4lat LATCbits.LATC4
#define dataport LATC

void transmit (int data);
void i2cinit(void);
void i2cstart(void);
void i2ctx(int dat);
void i2cstop(void);
unsigned char i2crx(void);
void i2cwait(void);
void i2cnak(void);
void i2cack(void);
void i2crestart(void);




void main(void) {
OSCCON = OSCCON & 0b11000011;   
OSCCON = OSCCON | 0b00111100; //Set Clock to 8mhz
TRISC = 0b00000000;

i2cinit();            //setup i2c

while(1){
transmit(0xD1);  //transmit byte (test)
//__delay_ms(1000);
}


    return;
}

void transmit(int data){
    i2cstart();
    i2ctx(0xD1);
    i2cstop(); 
}

void i2cinit(void)
{
TRISBbits.TRISB6 = 1;      /* SDA and SCL as input pin */
TRISBbits.TRISB4 = 1;
SSPSTAT = 0x80; /* Slew rate disabled */
SSPCON1 = 0x28;   /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
SSPADD = 0x13;    /* 100Khz @ 8Mhz Fosc */
   
}

void i2cstart(void)
{
SSPCON2bits.SEN = 1;        /* Start condition enabled */
while(SSPCON2bits.SEN);      /* automatically cleared by hardware */
}


void i2cstop(void)
{
SSPCON2bits.PEN = 1;       /* Stop condition enabled */
while(SSPCON2bits.PEN);      /* Wait for stop condition to finish */
               
}

void i2crestart(void)
{
SSPCON2bits.RSEN = 1;        /* Repeated start enabled */
while(SSPCON2bits.RSEN);     /* wait for condition to finish */
}

void i2cack(void)
{
SSPCON2bits.ACKDT = 0;       /* Acknowledge data bit, 0 = ACK */
SSPCON2bits.ACKEN = 1;       /* Ack data enabled */
while(SSPCON2bits.ACKEN);    /* wait for ack data to send on bus */
}

void i2cnak(void)
{
SSPCON2bits.ACKDT = 1;       /* Acknowledge data bit, 1 = NAK */
SSPCON2bits.ACKEN = 1;       /* Ack data enabled */
while(SSPCON2bits.ACKEN);    /* wait for ack data to send on bus */
}

void i2cwait(void)
{
while ((SSPCON2 & 0x1F ) | ( SSPSTAT & 0x04 ) );
    /* wait for any pending transfer */
}

void i2ctx(int dat)
{
SSPBUF = dat;    /* Move data to SSPBUF */
while(SSPSTATbits.BF);       /* wait till complete data is sent from buffer */
i2cwait();       /* wait for any pending transfer */
}

unsigned char i2crx(void)
{
unsigned char temp;
SSPCON2bits.RCEN = 1;   
while(!SSPSTATbits.BF);   
temp = SSPBUF;   
i2cwait();     
return temp;
}
 

Offline RogerRowland

  • Regular Contributor
  • *
  • Posts: 193
  • Country: gb
    • Personal web site
Re: Help getting a PIC I2C working
« Reply #1 on: January 30, 2017, 07:35:11 am »
One thing you need to do (maybe not the only thing!) is to disable analog inputs on those pins in PORTB that you use for I2C.

So, in your main() function, just add something like:

Code: [Select]
ANSELB = 0;
That will disable all analog inputs on that port but you clear individual bits as necessary if you do need ADC.

See section 12.5.3 of the datasheet for details.
« Last Edit: January 30, 2017, 07:37:42 am by RogerRowland »
 

Offline JayboyTopic starter

  • Newbie
  • Posts: 2
  • Country: au
Re: Help getting a PIC I2C working
« Reply #2 on: January 30, 2017, 08:57:29 am »
Thanks i disabled the analog pins. I think I found the real issue I was using too lower value pullup resistors, so it was doing funky things when I has the oscilloscope attached.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf