Hello everyone !
I want to make a PIC24FJ128GA110 communicate via I2C on an ADC Maxim MAX11603. I am really new to PIC programming so apologies in advance if I'm not clear. I tried to initialize the I2C2 bus (will join my functions) so I can get an SCL signal on my scope, but despite my initialization, it is not working. I checked the pull-ups resistors and their value is 3.3ohms which is what I want. I reckon my problem would come from the clock configuration as I am really not sure about it. Does someone has any ideas of what I could try to indeed have a SCL signal on my scope please ?
This is my i2c.c file :
#include <stdint.h>
#include <stdbool.h>
//#include "system.h"
#include "i2c.h"
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 8000000UL
#endif
#ifndef FCY
#define FCY _XTAL_FREQ/2
#endif
#include <libpic30.h>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//We give a start condition on SDA and SCL
#define SDA TRISAbits.TRISA3
#define SCL TRISAbits.TRISA2
#define SDA_IN PORTAbits.RA3
#define SCL_IN PORTAbits.RA2
#define I2C_WADDR(x) (x & 0xFE) //clear R/W
#define I2C_RADDR(x) (x | 0x01) //set R/W
////////////////////////////////////////////////////////////////////////////////
//Timer and interrupt for i2c
void myTimer() {
//i2c2_init(100);
T1CONbits.TON = 1;
T1CONbits.TCS = 0;
T1CONbits.TCKPS = 0b10;
PR1 = 10000; // period to read I2C, This could probably be chosen more intelligently
TMR1 = 0;
}
//Configuration of the oscillator
void init_OSC() {
OSCCONbits.COSC = 0b001;
OSCCONbits.NOSC = 0b001;
// Configure PLL prescaler, PLL multiplier, and PLL postscaler
CLKDIVbits.RCDIV = 0; // PLL prescaler: N1 = 2
CLKDIVbits.DOZE = 0; // PLL postscaler: N2 = 2
// Configure oscillator selection bits
__builtin_write_OSCCONH(0x01); // Fast RC oscillator with PLL
__builtin_write_OSCCONL(OSCCON | 0x01); // Enable clock switch
// Wait for PLL to lock
while (OSCCONbits.LOCK != 1) {}
}
//Function initiates I2C2 module to baud rate BRG
void i2c2_init(int BRG) {
//I2C2ADD = 0b1101101;
I2C2ADD = 0b00000001;
I2C2BRG = BRG;
//Enable open-drain mode on SDA2
ODCAbits.ODA2 = 1;
ODCAbits.ODA3 = 1;
//Enable pull up for SCL and SDA
CNPD3bits.CN35PDE = 1; // SCL2 pin
CNPD3bits.CN36PDE = 1; // SDA2 pin
SDA = 0;
SCL = 0;
SCL_IN = SDA_IN = 0 ;
I2C2CONbits.I2CEN = 0; // Disable I2C Mode
// Clear Interrupt
IFS3bits.MI2C2IF = 0;
//Continue module operation in Idle mode
I2C2CONbits.I2CSIDL = 0;
//IPMIEN mode disabled
I2C2CONbits.IPMIEN = 1;
//7 bits slave address
I2C2CONbits.A10M = 0;
//Slew rate enabled
I2C2CONbits.DISSLW = 1;
//General call address disabled
I2C2CONbits.GCEN = 0;
//Disable SMBus input thresholds
I2C2CONbits.SMEN = 1;
//Software or receive call stretching disabled
I2C2CONbits.STREN = 0;
// Enable I2C Mode
I2C2CONbits.I2CEN = 1;
}
//Function initiates a start condition on bus
void i2c2_start(void) {
I2C2CONbits.ACKDT = 0; //Reset any previous Ack
__delay_us(10);
I2C2CONbits.SEN = 1; //Initiate Start condition
SDA = 1;
__delay_us(10);
SCL = 1;
__delay_us(10);
SDA = 0;
}
void i2c2_restart(void) {
I2C2CONbits.RSEN = 1; //Initiate restart condition
__delay_us(10);
}
//Resets the I2C bus to Idle
void reset_i2c2_bus(void) {
I2C2CONbits.PEN = 1; //initiate stop bit
I2C2CONbits.RCEN = 0;
IFS3bits.MI2C2IF = 0; // Clear Interrupt
I2C2STATbits.IWCOL = 0;
I2C2STATbits.BCL = 0;
__delay_us(10);
}
//Basic I2C byte send
char send_i2c2_byte(int data) {
IFS3bits.MI2C2IF = 0; // Clear Interrupt
I2C2TRN = data; // load the outgoing data byte
// Check for NO_ACK from slave, abort if not found
if (I2C2STATbits.ACKSTAT == 1) {
reset_i2c2_bus();
return (1);
}
__delay_us(10);
return (0);
}
//Function that write
void I2C2write(char addr, char value) {
i2c2_start();
send_i2c2_byte(addr);
send_i2c2_byte(value);
reset_i2c2_bus();
}
//Function reads data, returns the read data, no ack
char i2c2_read(void) {
char data = 0;
i2c2_start();
I2C2CONbits.RCEN = 1; //set I2C module to receive
data = I2C2RCV; //get data from I2CRCV register
return data; //return data
}
//function reads data, returns the read data, with ack
char i2c2_read_ack(void) {
char data = 0;
I2C2CONbits.RCEN = 1; //set I2C module to receive
data = I2C2RCV; //get data from I2CRCV register
I2C2CONbits.ACKEN = 1; //set ACK to high
__delay_us(10); //wait before exiting
return data; //return data
}
This is my i2c.h file :
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "xc.h"
#include <p24FJ128GA110.h>
void myTimer();
void init_OSC();
void i2c2_init(int BRG);
void i2c2_start(void);
void i2c2_restart(void);
void reset_i2c2_bus(void);
char send_i2c2_byte(int data);
void I2C2write(char addr, char value);
char i2c2_read(void);
char i2c2_read_ack(void);
This is my main file :
#include <stdio.h>
#include <stdlib.h>
#include "i2c.h"
#define ADC_SLAVE_ADDRESS_WRITE 0b11001010
#define ADC_SLAVE_ADDRESS_READ 0b11001011
#define SETUP_REGISTER_ADDRESS 0b11001101
#define CONFIGURATION_REGISTER_ADDRESS 0b01101010
/*
*
*/
int main() {
//myTimer();
init_OSC();
i2c2_init(0x27);
while (1) {
//i2c2_start();
//send_i2c2_byte(ADC_SLAVE_ADDRESS_WRITE);
//send_i2c2_byte(SETUP_REGISTER_ADDRESS);
//reset_i2c2_bus();
}
return (EXIT_SUCCESS);
}
As I said, I am really new to this :'(. I would take any advice, ideas or comments in consideration to improve my work.
Thank y'all for your time !
Juicycrunchwrap