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.

MCP7940N RTC write operation using PIC18F25K40

Status
Not open for further replies.

nayakajit87

Member level 5
Member level 5
Joined
Aug 13, 2018
Messages
84
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
1,065
Here is simple code written to communicate with I2c device.

I could not able to get any Start bit.weather below code is correct. I have used MCC generated code library ,


Code C# - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "mcc_generated_files/mcc.h"
 
#define PFS             RB0
#define RESET1           RB1
#define SELECT          RB2
#define ADVANCE         RB3
#define RLY_DRV1        RB4
#define DISPCLK         RB5
#define DISPDATA        RB6
#define STROBE          RB7
 
#define LED_MS      RA0
#define LED_HM      RA1
#define LED_SS      RA2
 
#define START_SIGNAL    RA3
#define PRG_EN       RA4
#define HLD_RST      RA5
#define RLY_DRV2     RC0
unsigned int sec;
unsigned int min;
unsigned int hour;
unsigned int date;
unsigned int month;
unsigned int year;
unsigned int day;
void I2C1_SlaveRestart(void) {
 SSP1CON2bits.RSEN = 1;
}
 
void WaitMSSP() {
 while(PIR3bits.SSP1IF == 0); // SSP1IF is set when operation complete
 {
 PIR3bits.SSP1IF = 0; // clear interrupt flag
 }
}
 
void MCP7940_Write(unsigned char addr ,unsigned char data) {
 SSP1CON2bits.SEN=1;
 while(1==SSP1CON2bits.SEN);
 SSP1BUF = 0b11011110;
 WaitMSSP();
 while(SSP1CON2bits.ACKSTAT == 1);
 SSP1BUF = addr;
 WaitMSSP();
 while(SSP1CON2bits.ACKSTAT == 1);
 SSP1BUF = data;
 WaitMSSP();
 SSP1CON2bits.PEN = 1;
 while(1==SSP1CON2bits.PEN);
 PIR3bits.SSP1IF=0;
}
unsigned int MCP7940_Read(char addr) {
 char result;
SSP1CON2bits.RSEN = 1;// send restart
 while(1==SSP1CON2bits.RSEN); // wait for transmission to complete
 PIR3bits.SSP1IF = 0; // clear interrupt flag
 SSP1BUF = 0b11011110; // send control byte to MCP7940 - write
 WaitMSSP();
 while(SSP1CON2bits.ACKSTAT== 1); // wait for RTC to be ready
 SSP1BUF = addr; // send register address to MCP7940
 WaitMSSP();
 while(SSP1CON2bits.ACKSTAT == 1); // wait for RTC to be ready
 SSP1CON2bits.RSEN = 1; // send restart
 WaitMSSP();
 SSP1BUF= 0b11011111; // send control byte to MCP7940 - read
 WaitMSSP();
 while(SSP1CON2bits.ACKSTAT== 1); // wait for RTC to be ready
 SSP1CON2bits.RCEN = 1; // put master in receive mode
 while(1==SSP1CON2bits.RCEN); // wait for transmission to complete
 PIR3bits.SSP1IF = 0; // clear interrupt flag
 SSP1CON2bits.ACKDT = 1;
 SSP1CON2bits.ACKEN = 1;
 while(1==SSP1CON2bits.ACKEN); // wait for NACK send to complete
 SSP1CON2bits.PEN = 1; // send STOP
 while(PEN);
 PIR3bits.SSP1IF = 0; // clear interrupt flag
 result = SSP1BUF; // get byte that was sent by RTC
 return result; // and return it to caller
 
}
 
unsigned int bcdtodecimal(unsigned int bcd) 
{
 unsigned int decimal;
 decimal = (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F);
 return decimal;
}
 
 
void main(void) {
 // Initialize the device
 SYSTEM_Initialize();
// If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
 // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global and Peripheral Interrupts
 // Use the following macros to:
// Enable the Global Interrupts
 INTERRUPT_GlobalInterruptEnable();
// Disable the Global Interrupts
 //INTERRUPT_GlobalInterruptDisable();
// Enable the Peripheral Interrupts
 INTERRUPT_PeripheralInterruptEnable();
// Disable the Peripheral Interrupts
 //INTERRUPT_PeripheralInterruptDisable();
I2C1_Initialize();
 MCP7940_Write(0,0x10);
 MCP7940_Write(1,0x10);
 MCP7940_Write(2,0x10);
 MCP7940_Write(3,0x10);
 MCP7940_Write(4,0x10);
 MCP7940_Write(5,0x10);
 MCP7940_Write(6,0x10);
while (1) {
sec = MCP7940_Read(0);
 sec=bcdtodecimal(sec);
 min = MCP7940_Read(1);
 min = bcdtodecimal(min);
 hour = MCP7940_Read(2);
 hour=bcdtodecimal(hour);
 day= MCP7940_Read(3);
//Process_RUN_MODE();
 
 /*LED_MS=1;
 if (Main_Flag == 0) {
 Main_Flag = 1;
 PRG_RUN_RESET();
 }
 Process_RUN_MODE();
 */
 
 }
}



CKt.jpg

RTC_2.jpg

RTC_COnfig.jpg
 
Last edited by a moderator:

Hi,

I could not able to get any Start bit.
With I2C START and STOP are no "bits" ( like with UART), they are conditions.
START: SCL = HIGH, SDA = falling edge
STOP: SCL = HIGH, SDA = rising edge

Klaus
 

As stated, there's no single start bit but a specific sequence of SDA and SCL lines.

But what are you actually looking at? Observing the I2C line with an oscilloscope? Do you mean, there's no SDA and SCL activity at all? Please clarify.
 

I dont know how to make use of MCC generated file. thats reason i have make use of own function to write and read i2c time. I have gone through some forum where they using above function . but i could not able to get response like DS1307 with arduino board.

Below is .c file created when i use MCC config setting. Setting details attached in first thread.
1) i would like to know how to make use of below function in main.

main.c
void MCP7940_Write(unsigned char addr ,unsigned char data)
{
I2C1_MasterStart();

}
i2c1_master.c
static inline void I2C1_MasterStart(void)
{
SSP1CON2bits.SEN = 1;
}


2) if i am using these function directly SSP1CON2bits.SEN = 1; why cant able to get any pulse ?? i have checked hardware setting made as per datasheet and AN1355/AN1491
MYSCL and SDA in logical analzer shows always high


i2c1_master.c
Code:
#include "i2c1_master.h"
#include <xc.h>

// I2C1 STATES
typedef enum {
    I2C1_IDLE = 0,
    I2C1_SEND_ADR_READ,
    I2C1_SEND_ADR_WRITE,
    I2C1_TX,
    I2C1_RX,
    I2C1_RCEN,
    I2C1_TX_EMPTY,      
    I2C1_SEND_RESTART_READ,
    I2C1_SEND_RESTART_WRITE,
    I2C1_SEND_RESTART,
    I2C1_SEND_STOP,
    I2C1_RX_ACK,
    I2C1_RX_NACK_STOP,
    I2C1_RX_NACK_RESTART,
    I2C1_RESET,
    I2C1_ADDRESS_NACK,

} i2c1_fsm_states_t;

// I2C1 Event callBack List
typedef enum {
    I2C1_DATA_COMPLETE = 0,
    I2C1_WRITE_COLLISION,
    I2C1_ADDR_NACK,
    I2C1_DATA_NACK,
    I2C1_TIMEOUT,
    I2C1_NULL
} i2c1_callbackIndex_t;

// I2C1 Status Structure
typedef struct
{
    i2c1_callback_t callbackTable[6];
    void *callbackPayload[6];           //  each callBack can have a payload
    uint16_t time_out;                  // I2C1 Timeout Counter between I2C1 Events.
    uint16_t time_out_value;            // Reload value for the timeouts
    i2c1_address_t address;             // The I2C1 Address
    uint8_t *data_ptr;                  // pointer to a data buffer
    size_t data_length;                 // Bytes in the data buffer
    i2c1_fsm_states_t state;            // Driver State
    i2c1_error_t error;
    unsigned addressNackCheck:1;
    unsigned busy:1;
    unsigned inUse:1;
    unsigned bufferFree:1;

} i2c1_status_t;

static void I2C1_SetCallback(i2c1_callbackIndex_t idx, i2c1_callback_t cb, void *ptr);
static void I2C1_Poller(void);
static inline void I2C1_MasterFsm(void);

/* I2C1 interfaces */
static inline bool I2C1_MasterOpen(void);
static inline void I2C1_MasterClose(void);    
static inline uint8_t I2C1_MasterGetRxData(void);
static inline void I2C1_MasterSendTxData(uint8_t data);
static inline void I2C1_MasterEnableRestart(void);
static inline void I2C1_MasterDisableRestart(void);
static inline void I2C1_MasterStartRx(void);
static inline void I2C1_MasterStart(void);
static inline void I2C1_MasterStop(void);
static inline bool I2C1_MasterIsNack(void);
static inline void I2C1_MasterSendAck(void);
static inline void I2C1_MasterSendNack(void);
static inline void I2C1_MasterClearBusCollision(void);

/* Interrupt interfaces */
static inline void I2C1_MasterEnableIrq(void);
static inline bool I2C1_MasterIsIrqEnabled(void);
static inline void I2C1_MasterDisableIrq(void);
static inline void I2C1_MasterClearIrq(void);
static inline void I2C1_MasterSetIrq(void);
static inline void I2C1_MasterWaitForEvent(void);

static i2c1_fsm_states_t I2C1_DO_IDLE(void);
static i2c1_fsm_states_t I2C1_DO_SEND_ADR_READ(void);
static i2c1_fsm_states_t I2C1_DO_SEND_ADR_WRITE(void);
static i2c1_fsm_states_t I2C1_DO_TX(void);
static i2c1_fsm_states_t I2C1_DO_RX(void);
static i2c1_fsm_states_t I2C1_DO_RCEN(void);
static i2c1_fsm_states_t I2C1_DO_TX_EMPTY(void);
static i2c1_fsm_states_t I2C1_DO_SEND_RESTART_READ(void);
static i2c1_fsm_states_t I2C1_DO_SEND_RESTART_WRITE(void);
static i2c1_fsm_states_t I2C1_DO_SEND_RESTART(void);
static i2c1_fsm_states_t I2C1_DO_SEND_STOP(void);
static i2c1_fsm_states_t I2C1_DO_RX_ACK(void);
static i2c1_fsm_states_t I2C1_DO_RX_NACK_STOP(void);
static i2c1_fsm_states_t I2C1_DO_RX_NACK_RESTART(void);
static i2c1_fsm_states_t I2C1_DO_RESET(void);
static i2c1_fsm_states_t I2C1_DO_ADDRESS_NACK(void);


typedef i2c1_fsm_states_t (*fsmHandlerFunction)(void);
const fsmHandlerFunction fsmStateTable[] = {
    I2C1_DO_IDLE,
    I2C1_DO_SEND_ADR_READ,
    I2C1_DO_SEND_ADR_WRITE,
    I2C1_DO_TX,
    I2C1_DO_RX,
    I2C1_DO_RCEN,
    I2C1_DO_TX_EMPTY,
    I2C1_DO_SEND_RESTART_READ,
    I2C1_DO_SEND_RESTART_WRITE,
    I2C1_DO_SEND_RESTART,
    I2C1_DO_SEND_STOP,
    I2C1_DO_RX_ACK,
    I2C1_DO_RX_NACK_STOP,
    I2C1_DO_RX_NACK_RESTART,
    I2C1_DO_RESET,
    I2C1_DO_ADDRESS_NACK,
};

i2c1_status_t I2C1_Status = {0};

void I2C1_Initialize()
{
    SSP1STAT = 0x40;
    SSP1CON1 = 0x08;
    SSP1CON2 = 0x00;
    SSP1ADD  = 0x09;
    SSP1CON1bits.SSPEN = 0;
}

i2c1_error_t I2C1_Open(i2c1_address_t address)
{
    i2c1_error_t returnValue = I2C1_BUSY;
    
    if(!I2C1_Status.inUse)
    {
        I2C1_Status.address = address;
        I2C1_Status.busy = 0;
        I2C1_Status.inUse = 1;
        I2C1_Status.addressNackCheck = 0;
        I2C1_Status.state = I2C1_RESET;
        I2C1_Status.time_out_value = 500; // MCC should determine a reasonable starting value here.
        I2C1_Status.bufferFree = 1;

        // set all the call backs to a default of sending stop
        I2C1_Status.callbackTable[I2C1_DATA_COMPLETE]=I2C1_CallbackReturnStop;
        I2C1_Status.callbackPayload[I2C1_DATA_COMPLETE] = NULL;
        I2C1_Status.callbackTable[I2C1_WRITE_COLLISION]=I2C1_CallbackReturnStop;
        I2C1_Status.callbackPayload[I2C1_WRITE_COLLISION] = NULL;
        I2C1_Status.callbackTable[I2C1_ADDR_NACK]=I2C1_CallbackReturnStop;
        I2C1_Status.callbackPayload[I2C1_ADDR_NACK] = NULL;
        I2C1_Status.callbackTable[I2C1_DATA_NACK]=I2C1_CallbackReturnStop;
        I2C1_Status.callbackPayload[I2C1_DATA_NACK] = NULL;
        I2C1_Status.callbackTable[I2C1_TIMEOUT]=I2C1_CallbackReturnReset;
        I2C1_Status.callbackPayload[I2C1_TIMEOUT] = NULL;
        
        I2C1_MasterClearIrq();
        I2C1_MasterOpen();
        returnValue = I2C1_NOERR;
    }
    return returnValue;
}

i2c1_error_t I2C1_Close(void)
{
    i2c1_error_t returnValue = I2C1_BUSY;
    if(!I2C1_Status.busy)
    {
        I2C1_Status.inUse = 0;
        I2C1_Status.address = 0xff;
        I2C1_MasterClearIrq();
        I2C1_MasterDisableIrq();
        I2C1_MasterClose();
        returnValue = I2C1_Status.error;
    }
    return returnValue;
}

i2c1_error_t I2C1_MasterOperation(bool read)
{
    i2c1_error_t returnValue = I2C1_BUSY;
    if(!I2C1_Status.busy)
    {
        I2C1_Status.busy = true;
        returnValue = I2C1_NOERR;

        if(read)
        {
            I2C1_Status.state = I2C1_SEND_ADR_READ;
        }
        else
        {
            I2C1_Status.state = I2C1_SEND_ADR_WRITE;
        }
        I2C1_MasterStart();
        I2C1_Poller();
    }
    return returnValue;
}

i2c1_error_t I2C1_MasterRead(void)
{
    return I2C1_MasterOperation(true);
}

i2c1_error_t I2C1_MasterWrite(void)
{
    return I2C1_MasterOperation(false);
}

void I2C1_SetTimeOut(uint8_t timeOutValue)
{
    I2C1_MasterDisableIrq();
    I2C1_Status.time_out_value = timeOutValue;
    I2C1_MasterEnableIrq();
}

void I2C1_SetBuffer(void *buffer, size_t bufferSize)
{
    if(I2C1_Status.bufferFree)
    {
        I2C1_Status.data_ptr = buffer;
        I2C1_Status.data_length = bufferSize;
        I2C1_Status.bufferFree = false;
    }
}

void I2C1_SetDataCompleteCallback(i2c1_callback_t cb, void *ptr)
{
    I2C1_SetCallback(I2C1_DATA_COMPLETE, cb, ptr);
}

void I2C1_SetWriteCollisionCallback(i2c1_callback_t cb, void *ptr)
{
    I2C1_SetCallback(I2C1_WRITE_COLLISION, cb, ptr);
}

void I2C1_SetAddressNackCallback(i2c1_callback_t cb, void *ptr)
{
    I2C1_SetCallback(I2C1_ADDR_NACK, cb, ptr);
}

void I2C1_SetDataNackCallback(i2c1_callback_t cb, void *ptr)
{
    I2C1_SetCallback(I2C1_DATA_NACK, cb, ptr);
}

void I2C1_SetTimeoutCallback(i2c1_callback_t cb, void *ptr)
{
    I2C1_SetCallback(I2C1_TIMEOUT, cb, ptr);
}

static void I2C1_SetCallback(i2c1_callbackIndex_t idx, i2c1_callback_t cb, void *ptr)
{
    if(cb)
    {
        I2C1_Status.callbackTable[idx] = cb;
        I2C1_Status.callbackPayload[idx] = ptr;
    }
    else
    {
        I2C1_Status.callbackTable[idx] = I2C1_CallbackReturnStop;
        I2C1_Status.callbackPayload[idx] = NULL;
    }
}

static void I2C1_Poller(void)
{
    while(I2C1_Status.busy)
    {
        I2C1_MasterWaitForEvent();
        I2C1_MasterFsm();
    }
}

static inline void I2C1_MasterFsm(void)
{
    I2C1_MasterClearIrq();

    if(I2C1_Status.addressNackCheck && I2C1_MasterIsNack())
    {
        I2C1_Status.state = I2C1_ADDRESS_NACK;
    }
    I2C1_Status.state = fsmStateTable[I2C1_Status.state]();
}


static i2c1_fsm_states_t I2C1_DO_IDLE(void)
{
    I2C1_Status.busy = false;
    I2C1_Status.error = I2C1_NOERR;
    return I2C1_RESET;
}

static i2c1_fsm_states_t I2C1_DO_SEND_ADR_READ(void)
{
    I2C1_Status.addressNackCheck = 1;
    I2C1_MasterSendTxData(I2C1_Status.address << 1 | 1);
    return I2C1_RCEN;
}

static i2c1_fsm_states_t I2C1_DO_SEND_ADR_WRITE(void)
{
    I2C1_Status.addressNackCheck = 1;
    I2C1_MasterSendTxData(I2C1_Status.address << 1);
    return I2C1_TX;
}

static i2c1_fsm_states_t I2C1_DO_TX(void)
{
    if(I2C1_MasterIsNack())
    {
        switch(I2C1_Status.callbackTable[I2C1_DATA_NACK](I2C1_Status.callbackPayload[I2C1_DATA_NACK]))
        {
            case I2C1_RESTART_READ:
                return I2C1_DO_SEND_RESTART_READ();
            case I2C1_RESTART_WRITE:
                  return I2C1_DO_SEND_RESTART_WRITE();
            default:
            case I2C1_CONTINUE:
            case I2C1_STOP:
                return I2C1_DO_SEND_STOP();
        }
    }
    else
    {
        I2C1_Status.addressNackCheck = 0;
        I2C1_MasterSendTxData(*I2C1_Status.data_ptr++);
        return (--I2C1_Status.data_length)?I2C1_TX:I2C1_TX_EMPTY;
    }
}

static i2c1_fsm_states_t I2C1_DO_RX(void)
{
    *I2C1_Status.data_ptr++ = I2C1_MasterGetRxData();
    if(--I2C1_Status.data_length)
    {
        I2C1_MasterSendAck();
        return I2C1_RCEN;
    }
    else
    {
        I2C1_Status.bufferFree = true;
        switch(I2C1_Status.callbackTable[I2C1_DATA_COMPLETE](I2C1_Status.callbackPayload[I2C1_DATA_COMPLETE]))
        {
            case I2C1_RESTART_WRITE:
            case I2C1_RESTART_READ:
                return I2C1_DO_RX_NACK_RESTART();
            default:
            case I2C1_CONTINUE:
            case I2C1_STOP:
                return I2C1_DO_RX_NACK_STOP();
        }
    }
}

static i2c1_fsm_states_t I2C1_DO_RCEN(void)
{
    I2C1_Status.addressNackCheck = 0;
    I2C1_MasterStartRx();
    return I2C1_RX;
}

static i2c1_fsm_states_t I2C1_DO_TX_EMPTY(void)
{
    I2C1_Status.bufferFree = true;
    switch(I2C1_Status.callbackTable[I2C1_DATA_COMPLETE](I2C1_Status.callbackPayload[I2C1_DATA_COMPLETE]))
    {
        case I2C1_RESTART_READ:
        case I2C1_RESTART_WRITE:
            return I2C1_DO_SEND_RESTART();
        case I2C1_CONTINUE:
            I2C1_MasterSetIrq();
            return I2C1_TX;
        default:
        case I2C1_STOP:
            return I2C1_DO_SEND_STOP();
    }
}

static i2c1_fsm_states_t I2C1_DO_RX_EMPTY(void)
{
    I2C1_Status.bufferFree = true;
    switch(I2C1_Status.callbackTable[I2C1_DATA_COMPLETE](I2C1_Status.callbackPayload[I2C1_DATA_COMPLETE]))
    {
        case I2C1_RESTART_WRITE:
            I2C1_MasterEnableRestart();
            return I2C1_SEND_RESTART_WRITE;
        case I2C1_RESTART_READ:
            I2C1_MasterEnableRestart();
            return I2C1_SEND_RESTART_READ;
        case I2C1_CONTINUE:
            // Avoid the counter stop condition , Counter is incremented by 1
            return I2C1_RX;
        default:
        case I2C1_STOP:
            if(I2C1_Status.state != I2C1_SEND_RESTART_READ)
            {
                I2C1_MasterDisableRestart();
            }
            return I2C1_RESET;
    }
}

static i2c1_fsm_states_t I2C1_DO_SEND_RESTART_READ(void)
{
    I2C1_MasterEnableRestart();
    return I2C1_SEND_ADR_READ;
}

static i2c1_fsm_states_t I2C1_DO_SEND_RESTART_WRITE(void)
{
    I2C1_MasterEnableRestart();
    return I2C1_SEND_ADR_WRITE;
}


static i2c1_fsm_states_t I2C1_DO_SEND_RESTART(void)
{
    I2C1_MasterEnableRestart();
    return I2C1_SEND_ADR_READ;
}

static i2c1_fsm_states_t I2C1_DO_SEND_STOP(void)
{
    I2C1_MasterStop();
    return I2C1_IDLE;
}

static i2c1_fsm_states_t I2C1_DO_RX_ACK(void)
{
    I2C1_MasterSendAck();
    return I2C1_RCEN;
}


static i2c1_fsm_states_t I2C1_DO_RX_NACK_STOP(void)
{
    I2C1_MasterSendNack();
    return I2C1_SEND_STOP;
}

static i2c1_fsm_states_t I2C1_DO_RX_NACK_RESTART(void)
{
    I2C1_MasterSendNack();
    return I2C1_SEND_RESTART;
}

static i2c1_fsm_states_t I2C1_DO_RESET(void)
{
    I2C1_Status.busy = false;
    I2C1_Status.error = I2C1_NOERR;
    return I2C1_RESET;
}
static i2c1_fsm_states_t I2C1_DO_ADDRESS_NACK(void)
{
    I2C1_Status.addressNackCheck = 0;
    I2C1_Status.error = I2C1_FAIL;
    switch(I2C1_Status.callbackTable[I2C1_ADDR_NACK](I2C1_Status.callbackPayload[I2C1_ADDR_NACK]))
    {
        case I2C1_RESTART_READ:
        case I2C1_RESTART_WRITE:
            return I2C1_DO_SEND_RESTART();
        default:
            return I2C1_DO_SEND_STOP();
    }
}

void I2C1_BusCollisionIsr(void)
{
    I2C1_MasterClearBusCollision();
    I2C1_Status.state = I2C1_RESET;
}

i2c1_operations_t I2C1_CallbackReturnStop(void *funPtr)
{
    return I2C1_STOP;
}

i2c1_operations_t I2C1_CallbackReturnReset(void *funPtr)
{
    return I2C1_RESET_LINK;
}

i2c1_operations_t I2C1_CallbackRestartWrite(void *funPtr)
{
    return I2C1_RESTART_WRITE;
}

i2c1_operations_t I2C1_CallbackRestartRead(void *funPtr)
{
    return I2C1_RESTART_READ;
}



/* I2C1 Register Level interfaces */
static inline bool I2C1_MasterOpen(void)
{
    if(!SSP1CON1bits.SSPEN)
    {
        SSP1STAT = 0x40;
        SSP1CON1 = 0x08;
        SSP1CON2 = 0x00;
        SSP1ADD = 0x09;
        SSP1CON1bits.SSPEN = 1;
        return true;
    }
    return false;
}

static inline void I2C1_MasterClose(void)
{
    //Disable I2C1
    SSP1CON1bits.SSPEN = 0;
}

static inline uint8_t I2C1_MasterGetRxData(void)
{
    return SSP1BUF;
}

static inline void I2C1_MasterSendTxData(uint8_t data)
{
    SSP1BUF  = data;
}

static inline void I2C1_MasterEnableRestart(void)
{
    SSP1CON2bits.RSEN = 1;
}

static inline void I2C1_MasterDisableRestart(void)
{
    SSP1CON2bits.RSEN = 0;
}

static inline void I2C1_MasterStartRx(void)
{
    SSP1CON2bits.RCEN = 1;
}

static inline void I2C1_MasterStart(void)
{
    SSP1CON2bits.SEN = 1;
}

static inline void I2C1_MasterStop(void)
{
    SSP1CON2bits.PEN = 1;
}

static inline bool I2C1_MasterIsNack(void)
{
    return SSP1CON2bits.ACKSTAT;
}

static inline void I2C1_MasterSendAck(void)
{
    SSP1CON2bits.ACKDT = 0;
    SSP1CON2bits.ACKEN = 1;
}

static inline void I2C1_MasterSendNack(void)
{
    SSP1CON2bits.ACKDT = 1;
    SSP1CON2bits.ACKEN = 1;
}

static inline void I2C1_MasterClearBusCollision(void)
{
    PIR3bits.BCL1IF = 0;
}

static inline bool I2C1_MasterIsRxBufFull(void)
{
    return SSP1STATbits.BF;
}

static inline void I2C1_MasterEnableIrq(void)
{
    PIE3bits.SSP1IE = 1;
}

static inline bool I2C1_MasterIsIrqEnabled(void)
{
    return PIE3bits.SSP1IE;
}

static inline void I2C1_MasterDisableIrq(void)
{
    PIE3bits.SSP1IE = 0;
}

static inline void I2C1_MasterClearIrq(void)
{
    PIR3bits.SSP1IF = 0;
}

static inline void I2C1_MasterSetIrq(void)
{
    PIR3bits.SSP1IF = 1;
}

static inline void I2C1_MasterWaitForEvent(void)
{
    while(1)
    {
        if(PIR3bits.SSP1IF)
        {    
            break;
        }
    }
}
 

I have tested my hardware with Arduino Uno board its working well. There i could able to get proper response.
i have tested mcc generated library function with ds1307/ds3231/pc8563 module it works well. But when i try with MCP7940N device i wont get any response.

Code:
#include "mcc_generated_files/mcc.h"
#include"mcc_generated_files/examples/i2c1_master_example.h"
unsigned int i=0;
unsigned int k=0;
unsigned int count;
unsigned int x;
#define LED RC7
#define CONTROLREG 0xFF
#define SDA RC4 // Data pin for i2c
#define SCK RC3 // Clock pin for i2c
#define SDA_DIR TRISC4 // Data pin direction
#define SCK_DIR TRISC3 // Clock pin direction

#define I2C_SPEED 150 // kbps

unsigned short int cnt, num,Dgt=0;;
unsigned short int temp1,temp2,temp3;

int sec;
int min;
int hour;
int date;
int month;
int year;
int day;
int temp=0;
int r_data;
#define Seg1 0x01
#define Seg2 0x02
#define Seg3 0x04
#define Seg4 0x08
#define Seg5 0x10
#define Seg6 0x20


unsigned char Flag_Update=0;
void Delay(unsigned int k) {
 unsigned int j;
 for(j=0; j<k; j++);
}


void SetSeg(unsigned short data, unsigned short segno)

{
 switch(data) {
  case 0:
   PORTB = 0x3F;
   break;
  case 1:
   PORTB = 0x06;
   break;
  case 2:
   PORTB = 0x5B;
   break;
  case 3:
   PORTB = 0x4F;
   break;
  case 4:
   PORTB = 0x66;
   break;
  case 5:
   PORTB = 0x6D;
   break;
  case 6:
   PORTB = 0x7D;
   break;
  case 7:
   PORTB = 0x07;
   break;
  case 8:
   PORTB = 0x7F;
   break;
  case 9:
   PORTB = 0x6F;
   break;
  default :
   PORTB = 0X00;
   break;
 }

 if(segno==1) {
  PORTA = Seg4;
 }
 if(segno==2) {
  PORTA = Seg3;
 }
 if(segno==3) {
  PORTA = Seg2;
 }
 if(segno==4) {
  PORTA = Seg1;
 }

 if(segno==5) {
  PORTC=0X00;
  PORTC = 0x40;//DP2 fourth Segment

  // PORTCbits.RC5=1;
 }

 if(segno==6) {
  PORTC=0X00;
  PORTC= 0x20;//DP2 third Segment

  //PORTCbits.RC6=1;
 }


 if(segno==7) {
  PORTA=0X00;
  PORTA = Seg5; //DP2 Second Segment
  // PORTAbits.RA4=1;
 }

 if(segno==8) {
  PORTA=0X00;
  PORTA = Seg6; //DP2 First Segment
  // PORTAbits.RA5=1;
 }

}



unsigned int bcdtodecimal(unsigned int bcd) {
 unsigned int decimal;
 decimal = (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F);
 return decimal;
}





void ISR_Routine(void) {
 if(PIR0bits.TMR0IF==1) {
  PIR0bits.TMR0IF = 0;
  count= count+1;
  if(count>=10) {

   Flag_Update=1;
   count=0;
   LED=!LED;

  }
 }



}







void main(void) {
 // Initialize the device
 SYSTEM_Initialize();
 INTCONbits.GIE=1;
 INTCONbits.PEIE=1;

 I2C1_Initialize();
 I2C1_Write1ByteRegister(0x6F,0x00,0x10);//sec
 I2C1_Write1ByteRegister(0x6F,0x01,0x20);//min
 I2C1_Write1ByteRegister(0x6F,0x02,0x01);//Hour
 I2C1_Write1ByteRegister(0x6F,0x03,0x01);
 I2C1_Write1ByteRegister(0x6F,0x04,0x02);
 I2C1_Write1ByteRegister(0x6F,0x05,0x03);
 I2C1_Write1ByteRegister(0x6F,0x06,0x10);
 I2C1_Write1ByteRegister(0x6F,0x07,0x48);

 while (1)


 {
  sec=I2C1_Read1ByteRegister(0x6F,0x00);

  min=I2C1_Read1ByteRegister(0x6F,0x01);

  if(Flag_Update==1) {
   SetSeg(min >> 4,4);
   __delay_ms(5);
   SetSeg(min & 0x0f,3);
   __delay_ms(5);
   SetSeg(sec >> 4,2);
   __delay_ms(5);
   SetSeg(sec & 0x0f,1);
   __delay_ms(5);
   Flag_Update = 0; //ready for next update
  }


 }
}
 

Hi,

Try with device address 0xDE.

Klaus
 

I have tested code by changing to 0XDE but didn't worked, with pic18 controller i am getting nack from slave .
i have tested my hardware with arduino unop board and its working well. here sample code.

I am sure there is no issue with hardware.

Code:
#include "I2C.h"

const int MCP7940_I2C = 0x6F; // I2C Address for the RTC

const int REG_RTCSEC = 0x00; // Register Address: Time Second
const int REG_RTCMIN = 0x01; // Register Address: Time Minute
const int REG_RTCHOUR = 0x02; // Register Address: Time Hour
const int REG_RTCWKDAY = 0x03; // Register Address: Date Day of Week
const int REG_RTCDATE = 0x04; // Register Address: Date Day
const int REG_RTCMTH = 0x05; // Register Address: Date Month
const int REG_RTCYEAR = 0x06; // Register Address: Date Year

byte timeStamp[7]; // Byte array holding a full time stamp.

// Array position is the same as the register address.

void setup() {

 Serial.begin (9600);

 I2c.begin (); // Initialize the I2C library
 I2c.pullup (0); // Disable the internal pullup resistors
 I2c.setSpeed (0); // Enable 100kHz I2C Bus Speed
 I2c.timeOut (250); // Set a 250ms timeout before the bus resets

 // These are the values that will be written to the MCP7940
 timeStamp[0] = convertToBcd( 0); // SECONDS
 timeStamp[1] = convertToBcd(48); // MINUTES
 timeStamp[2] = convertToBcd(19); // HOURS
 timeStamp[3] = convertToBcd( 6); // DAY OF WEEK (arbitrary value 1 - 7)
 timeStamp[4] = convertToBcd( 26); // DAY
 timeStamp[5] = convertToBcd( 8); // MONTH
 timeStamp[6] = convertToBcd( 20); // YEAR

 // Write our time stamp to the time/date registers
 I2c.write(MCP7940_I2C, REG_RTCSEC, timeStamp, 7);

 // Initialize our chip with any further configuration data
 init_MCP7940();

}

void loop() {

 I2c.read(MCP7940_I2C, REG_RTCSEC, 7, timeStamp);

 Serial.print ("Current Time: ");
 Serial.print (convertFromBcd(timeStamp[2] & 0x3F));
 Serial.print (":");
 if (convertFromBcd(timeStamp[1] & 0x7F) / 10 == 0) Serial.print ("0");
 Serial.print (convertFromBcd(timeStamp[1] & 0x7F));
 Serial.print (":");
 if (convertFromBcd(timeStamp[0] & 0x7F) / 10 == 0) Serial.print ("0");
 Serial.println (convertFromBcd(timeStamp[0] & 0x7F));

 delay(500);

}

void init_MCP7940() {

 byte registerValue = 0x00; // Holds the received register value
 byte twelveHour = 0x00; // 0 = 24 Hour Clock Mode / 1 = 12 Hour Clock Mode
 byte startClock = 0x01; // 0 = Start Oscillator / 1 = Stop Oscillator

 // Turn on/off: 12 hour vs. 24 hour clock
 I2c.read (MCP7940_I2C, REG_RTCHOUR, 1);
 registerValue = I2c.receive();
 if (twelveHour == 0x00) I2c.write (MCP7940_I2C, REG_RTCHOUR, bitClear (registerValue, 6));
 if (twelveHour == 0x01) I2c.write (MCP7940_I2C, REG_RTCHOUR, bitSet (registerValue, 6));

 // Turn on/off: Oscillator (starts the clock)
 I2c.read (MCP7940_I2C, REG_RTCSEC, 1);
 registerValue = I2c.receive();
 if (startClock == 0x00) I2c.write (MCP7940_I2C, REG_RTCSEC, bitClear (registerValue, 7));
 if (startClock == 0x01) I2c.write (MCP7940_I2C, REG_RTCSEC, bitSet (registerValue, 7));

}


byte convertToBcd(byte byteDecimal) {

 return (byteDecimal / 10) << 4 | (byteDecimal % 10);

}
byte convertFromBcd(byte byteBCD) {

 byte byteMSB = 0;
 byte byteLSB = 0;

 byteMSB = (byteBCD & B11110000) >> 4;
 byteLSB = (byteBCD & B00001111);

 return ((byteMSB * 10) + byteLSB);
}
 

Attachments

  • MCP_6F_out.JPG
    MCP_6F_out.JPG
    61 KB · Views: 109

Hi,

Your scope picture shows correct address and correct ACK = LOW.

Klaus
 
Last edited:

This make any sense. For Trial what i have done is i just removed jumper cable from SCL line . it continued working where min:Sec sec parameter increment properly . as soon as i connect it start switching from last value and 00 in sec paramter.

I thought that we can capture signal from Logical analyzer . but as soon as i connect it stop working.

Do u think its problem in hardware or software???
 

Hi,

Are you sure you properly installed the 2k pullup resistors?

the logic anlyzer should have no influence on signals and function. If it has --> throw it away.

Klaus
 

yes i have connected properly . because when i tested with arduino uno. it works well. here i have attached waveform for reference.
When i connect same hardware with pic18F series .if SDA/SCL connect it will hang. but if i remove SCL line it start continue showing time.But i dint understand ,why scl line get affected


if i try to capture signal SCL( since not connected CLK pulse not generated) but SDA response is read , logical analyzer cant able to recognize start and stop condition.
 

Attachments

  • MCp_output.JPG
    MCp_output.JPG
    107 KB · Views: 111
  • MCP_Read_operation.JPG
    MCP_Read_operation.JPG
    65.3 KB · Views: 138

I tried using library function but i am facing issue. I would like to try Convesion method . can some one guide me here. i have I2cmaster.c library function generated

I2cmaster.txt contain header file and function generated from MCC

To create my own Library function i am getting error. for trial i used this function
Code:
void MCP7940_Write(unsigned char time_var,unsigned char RTC_addr)
                  
{

I2C1_MasterStart():

}

Can some one tell me how to use inline code
i have added header function. but still getting error.
 

Attachments

  • error code.jpg
    error code.jpg
    470.2 KB · Views: 118
  • I2c_master.txt
    15.1 KB · Views: 89

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top