This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR6928: PCF8563 interfacing with MSP430FR6928

Part Number: MSP430FR6928

Tool/software:

We are interfacing PCF8563 with msp430fr6928 using I2C Communication ,but I2C interrupt is not generated. Here attaching the code snippets for ref and please correct me to move forward .

void fnInitRTC()
{
// RTCCTL0_H = RTCKEY_H; // Unlock RTC_C module
P3SEL0 |= BIT1 | BIT2;
P3SEL1 &= ~(BIT1 | BIT2);
P3DIR |=BIT0;
P3OUT &=~(BIT0);
PM5CTL0 &= ~LOCKLPM5;

UCB1CTLW0 = UCSWRST; // Enable SW reset
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
UCB1BRW = 160; // fSCL = SMCLK/160 = ~100kHz
UCB1I2CSA = 0xA2; // Slave Address
UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
UCB1IE |= UCNACKIE;
data=0x00;
I2C_Master_WriteReg(RTC_WR_ADDR,CTRL1, &data,1);
//__delay_cycles(5500);
data=0x12;
I2C_Master_WriteReg(RTC_WR_ADDR,CTRL2,&data ,1);
// __delay_cycles(5500);
data=0x01;
I2C_Master_WriteReg(RTC_WR_ADDR,MINA,&data ,1);
//__delay_cycles(5500);
data=0x80;
I2C_Master_WriteReg(RTC_WR_ADDR,HRSA, &data,1);
//__delay_cycles(5500);
data=0x80;
I2C_Master_WriteReg(RTC_WR_ADDR,DAYA, &data,1);
// __delay_cycles(5500);
data=0x80;
I2C_Master_WriteReg(RTC_WR_ADDR,WEKA,&data ,1);
__delay_cycles(5500);
data=0x82;
I2C_Master_WriteReg(RTC_WR_ADDR,CLK,&data,1);
__delay_cycles(5500);
data=0x00;
I2C_Master_WriteReg(RTC_WR_ADDR,TIMER,&data,1);
__delay_cycles(5500);
data=0x01;
I2C_Master_WriteReg(RTC_WR_ADDR,TIMERV,&data,1);
__delay_cycles(5500);

}

void I2C_Master_WriteReg(unsigned char dev_addr,unsigned int reg_addr, unsigned char *reg_data, unsigned char count)
//I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{

UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__enable_interrupt();
__bis_SR_register(LPM0_bits + GIE);
__no_operation();

}

void I2C_Master_ReadReg(unsigned char dev_addr,unsigned char reg_addr,unsigned char count)
{

/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt

UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__enable_interrupt();
__bis_SR_register(LPM0_bits /*+ GIE*/);

}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B1_ISR (void)
#else
#error Compiler not supported!
#endif
//Must read from UCB2RXBUF
{
//putch('B');
unsigned char rx_val = 0;
switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
// UCB1CTLW0 |= UCTXSTT; // resend start if NACK
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0:
// Vector 22: RXIFG0
rx_val = UCB1RXBUF;

if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;

RXByteCtr--;
}

if (RXByteCtr == 1)
{
UCB1CTLW0 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
UCB1IE &= ~UCRXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;

case USCI_I2C_UCTXIFG0:

if (TXByteCtr) // Check TX byte counter
{
UCB1TXBUF = TransmitBuffer[TransmitIndex++]; //TXData[SlaveFlag]; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB1CTLW0 |= UCTXSTP; // I2C stop condition
UCB1IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}

break;

default: break;
}
}

  • UCB1I2CSA = 0xA2; // Slave Address

    An I2C slave address is only 7 bits, so this can't be correct (even if the data sheet tells you that repeatedly, alas). The actual address is shown in data sheet (rev 11) Fig 17: 0x51.

    More generally: The address doesn't include the R/W bit. If a datasheet refers to a "Read Address" and a "Write Address", the actual address can be found by shifting (either one) right by 1 bit.

  • still its not working though i change the slave address as 0x51.

    Regards

    Namita

  • Hello namita,

    If you download an example code from SDK and then run it, can you transmit the data correctly ? 

    For I2C transmission, on hardware, you should remember to add pull-up resistance on SCL and SDA. On software, the device address Bruce mentioned is one important point. And I think the best way to resolve this issue maybe to use the oscilloscope to catch any voltage information on SCL and SDA, and enter the debug mode to do debug step by step. 

    Best Regards,

    Janz Bai

  • How do you tell that it isn't working? Breakpoint in the ISR? Readback of he RTC registers? Scope trace?

    For TXIFG0, the bytes are written from TransmitBuffer[], but I don't see any code to put anything there.

  • hi 

    as per hardware requirement we are changing the external RTC chip to PCF8583,hence i write the code for same as below ,but I2C interrupt is not generated ,kindly correct me in code.

    #define  SlaveAddress   0x51

    void InitI2C(unsigned char eeprom_i2c_address)
    {

    // I2C pins

    UCB1CTLW0 = UCSWRST; // Enable SW reset
    UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
    UCB1BRW = 10;//160; // fSCL = SMCLK/160 = ~100kHz
    UCB1I2CSA = SLAVE_ADDR; // Slave Address
    UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB1IE |= UCNACKIE;

    }

    unsigned char I2C_Master_WriteReg(unsigned char dev_addr,unsigned int reg_addr, unsigned char *reg_data, unsigned char count)
    //I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
    {

    while (UCB1STAT & UCBUSY); // Wait until the bus is not busy
    UCB1CTLW0 |= UCSWRST; // Put I2C into reset
    UCB1I2CSA = dev_addr; // Set I2C slave address
    UCB1CTL1 |= UCTXACK; // Send start condition
    UCB1CTL1 |= UCTR; // Set to transmitter mode
    UCB1CTL0 |= UCMODE_3 | UCSYNC; // I2C mode, sync
    UCB1CTL1 &= ~UCSWRST; // Release I2C from reset
    UCB1TXBUF = reg_addr& 0xFF; // Send register address
    UCB1IE &= ~UCRXIE; // Disable RX interrupt
    UCB1IE |= UCTXIE; // Enable TX interrupt
    while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
    UCB1TXBUF = *reg_data; // Send data
    while (!(UCB1IFG & UCTXIFG)); // Wait for TX buffer to be ready
    UCB1CTL1 |= UCTXSTP; // Send stop condition
    while (UCB1CTL1 & UCTXSTP); // Wait for stop condition to complete
    return 1;
    }

    void fnInitRTC()
    {
    I2C_Master_WriteReg(0x51,CTRL1, &data,1);
    __delay_cycles(80000);
    }

    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // Stop WDT
    PJSEL0 |= BIT4 | BIT5;

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // XT1 Setup
    CSCTL0_H = CSKEY >> 8; // Unlock CS registers
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers
    CSCTL4 &= ~LFXTOFF;
    do
    {
    CSCTL5 &= ~LFXTOFFG; // Clear XT1 fault flag
    SFRIFG1 &= ~OFIFG;
    }while (SFRIFG1&OFIFG); // Test oscillator fault flag
    CSCTL0_H = 0;
    PM5CTL0 &= ~LOCKLPM5;
    P3SEL0 |= BIT1 | BIT2;
    P3SEL1 &= ~(BIT1 | BIT2);

    PM5CTL0 &= ~LOCKLPM5;
    InitI2C(SlaveAddress);
    #if RTC_PCF8583
    fnInitRTC();
    gostDate.ucDate = 5;
    gostDate.ucMonth = 11;
    gostDate.ucYear = 12;
    gostTime.ucHour = 19;
    gostTime.ucMin = 16;
    gostTime.ucSec = 26;
    ucSetDate(&gostDate);
    #endif //RTC_PCF8583
    }

  • What happens when you run this?

    ------------------

    1) > I2C_Master_WriteReg(0x51,CTRL1, &data,1);

    How is the A0 pin connected? If it's connected to GND (e.g. MikroE breakout board) the address is 0x50 [Ref PCF8583 datasheet (r 06) Table 5]. 

    2) > UCB1CTL1 |= UCTXACK; // Send start condition

    This doesn't send a Start (I think it doesn't do anything on a Master). You need instead something like:

    > UCB1CTL1 |= UCTXSTT; // Send start condition

    That said, (a) I don't know what happens if you set this when UCSWRST=1 (b) you need to set UCTR first.

    3) I don't see where you enable interrupts (GIE). Add somewhere:

    > __enable_interrupt();   // GIE=1

    [Edit: I missed this before:

    4) > UCB1IE |= UCTXIE; // Enable TX interrupt

    This enables the TXIFG, but I don't see an ISR (and based on the other code you don't need one). Just remove this line.

    ]

  • hi ,i modified but not  generating I2C interrupt ,is there any sample code related to PF8583 without I2C interrupt.?

  • Since you've removed all the UCB1IE settings, I don't expect you'd see any I2C interrupts (ISR calls). You don't need them since you're polling.

    I don't know of any sample code for the PCF8583 and MSP430. A Forum search turns up 20 hits, but I didn't investigate them.

  • i tried with polling also but it  gets stuck at I2C_Write function,while loop ,please refer below code

    // Start I2C communication
    void I2C_Start(void) {
    //UCB1CTLW0 |= USIIFG; // Set start condition
    UCB1CTLW0 |= UCTR + UCTXSTT;
    }

    // Stop I2C communication
    void I2C_Stop(void) {
    UCB0CTLW0 |= UCTXSTP;; // Set stop condition
    }

    // Write data to I2C
    void I2C_Write(unsigned char data) {
    UCB1TXBUF = data; // Load data
    UCB1CTLW0 |= UCTR + UCTXSTT; // Start transmission
    while (!(UCB1IFG & UCTXIFG)); // Wait until transmission complete
    }

    // Read data from I2C
    unsigned char I2C_Read(void)
    {
    unsigned char retVal;
    UCB1CTLW0 |= UCTR + UCTXSTT; // Start reception
    while (!(UCB0IFG & UCRXIFG0)); // Wait until reception complete
    retVal = UCB0RXBUF;
    return retVal; // Return received data
    }
    void fnInitRTC()
    {
    I2C_Start();
    I2C_Write(0xA0); // PCF8583 address (adjust based on address pins)
    I2C_Write(RTC_ADDR_YEAR_DATE); // Register to start writing (time register)
    I2C_Write(0);
    }
    unsigned char ucSetDate(tdstDate *stRTC_Date)
    {
    I2C_Start();
    I2C_Write(0xA0); // PCF8583 address (adjust based on address pins)
    I2C_Write(RTC_ADDR_YEAR_DATE); // Register to start writing (time register)
    I2C_Write(stRTC_Date->ucDate); // Set hours
    // I2C_Write(stRTC_Date->ucMin); // Set minutes
    //I2C_Write(stRTC_Date->ucSec); // Set seconds

    I2C_Stop();
    }
    unsigned char ucGetDate(tdstDate *stRTC_Date)
    {
    I2C_Start();
    I2C_Write(0xA0); // PCF8583 address (adjust based on address pins)
    I2C_Write(0x00); // Register to read from (time register)

    I2C_Start(); // Repeated start
    I2C_Write(0xA1); // PCF8583 address with read bit
    stRTC_Date->ucDate = I2C_Read(); // Read hours
    //stRTC_Dat->ucMin = I2C_Read(); // Read minutes
    //stRTC_Date->ucSec = I2C_Read(); // Read seconds

    I2C_Stop(); }

**Attention** This is a public forum