This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

MCP7940 drivers for nrf52840

We are working on external RTC MCP7940(i2c) interfaced with nrf52840. Please check if drivers of the same for nrf52/51 are available or any implementation of CLOCK using MCP7940 with NRF?

Regards

Vishal Aditya

Embedded Software Engineer

Parents Reply Children
  • Yes calling init_MCP7940()


    Below register maps:

    const uint8_t MCP7940_I2C = 0xDE;
    const uint8_t MCP7940_RTCSEC = 0x00; ///< Timekeeping, RTCSEC Register address
    const uint8_t MCP7940_RTCMIN = 0x01; ///< Timekeeping, RTCMIN Register address
    const uint8_t MCP7940_RTCHOUR = 0x02; ///< Timekeeping, RTCHOUR Register address
    const uint8_t MCP7940_RTCWKDAY = 0x03; ///< Timekeeping, RTCWKDAY Register address
    const uint8_t MCP7940_RTCDATE = 0x04; ///< Timekeeping, RTCDATE Register address
    const uint8_t MCP7940_RTCMTH = 0x05; ///< Timekeeping, RTCMTH Register address
    const uint8_t MCP7940_RTCYEAR = 0x06; ///< Timekeeping, RTCYEAR Register address
    const uint8_t MCP7940_CONTROL = 0x07; ///< Timekeeping, RTCCONTROL Register address
    const uint8_t MCP7940_OSCTRIM = 0x08; ///< Timekeeping, RTCOSCTRIM Register address
    const uint8_t MCP7940_ALM0SEC = 0x0A; ///< Alarm 0, ALM0SEC Register address
    const uint8_t MCP7940_ALM0MIN = 0x0B; ///< Alarm 0, ALM0MIN Register address
    const uint8_t MCP7940_ALM0HOUR = 0x0C; ///< Alarm 0, ALM0HOUR Register address
    const uint8_t MCP7940_ALM0WKDAY = 0x0D; ///< Alarm 0, ALM0WKDAY Register address
    const uint8_t MCP7940_ALM0DATE = 0x0E; ///< Alarm 0, ALM0DATE Register address
    const uint8_t MCP7940_ALM0MTH = 0x0F; ///< Alarm 0, ALM0MTH Register address
    const uint8_t MCP7940_ALM1SEC = 0x11; ///< Alarm 1, ALM1SEC Register address
    const uint8_t MCP7940_ALM1MIN = 0x12; ///< Alarm 1, ALM1MIN Register address
    const uint8_t MCP7940_ALM1HOUR = 0x13; ///< Alarm 1, ALM1HOUR Register address
    const uint8_t MCP7940_ALM1WKDAY = 0x14; ///< Alarm 1, ALM1WKDAY Register address
    const uint8_t MCP7940_ALM1DATE = 0x15; ///< Alarm 1, ALM1DATE Register address
    const uint8_t MCP7940_ALM1MTH = 0x16; ///< Alarm 1, ALM1MONTH Register address
    const uint8_t MCP7940_PWRDNMIN = 0x18; ///< Power-Fail, PWRDNMIN Register address
    const uint8_t MCP7940_PWRDNHOUR = 0x19; ///< Power-Fail, PWRDNHOUR Register address
    const uint8_t MCP7940_PWRDNDATE = 0x1A; ///< Power-Fail, PWDNDATE Register address
    const uint8_t MCP7940_PWRDNMTH = 0x1B; ///< Power-Fail, PWRDNMTH Register address
    const uint8_t MCP7940_PWRUPMIN = 0x1C; ///< Power-Fail, PWRUPMIN Register address
    const uint8_t MCP7940_PWRUPHOUR = 0x1D; ///< Power-Fail, PWRUPHOUR Register address
    const uint8_t MCP7940_PWRUPDATE = 0x1E; ///< Power-Fail, PWRUPDATE Register address
    const uint8_t MCP7940_PWRUPMTH = 0x1F; ///< Power-Fail, PWRUPMTH Register address
    const uint8_t MCP7940_RAM_ADDRESS = 0x20; ///< NVRAM - Start address for SRAM
    const uint8_t MCP7940_ST = 7; ///< MCP7940 register bits. RTCSEC reg
    const uint8_t MCP7940_12_24 = 6; ///< RTCHOUR, PWRDNHOUR & PWRUPHOUR
    const uint8_t MCP7940_AM_PM = 5; ///< RTCHOUR, PWRDNHOUR & PWRUPHOUR
    const uint8_t MCP7940_OSCRUN = 5; ///< RTCWKDAY register
    const uint8_t MCP7940_PWRFAIL = 4; ///< RTCWKDAY register
    const uint8_t MCP7940_VBATEN = 3; ///< RTCWKDAY register
    const uint8_t MCP7940_LPYR = 5; ///< RTCMTH register
    const uint8_t MCP7940_OUT = 7; ///< CONTROL register
    const uint8_t MCP7940_SQWEN = 6; ///< CONTROL register
    const uint8_t MCP7940_ALM1EN = 5; ///< CONTROL register
    const uint8_t MCP7940_ALM0EN = 4; ///< CONTROL register
    const uint8_t MCP7940_EXTOSC = 3; ///< CONTROL register
    const uint8_t MCP7940_CRSTRIM = 2; ///< CONTROL register
    const uint8_t MCP7940_SQWFS1 = 1; ///< CONTROL register
    const uint8_t MCP7940_SQWFS0 = 0; ///< CONTROL register
    const uint8_t MCP7940_SIGN = 7; ///< OSCTRIM register
    const uint8_t MCP7940_ALMPOL = 7; ///< ALM0WKDAY register
    const uint8_t MCP7940_ALM0IF = 3; ///< ALM0WKDAY register
    const uint8_t MCP7940_ALM1IF = 3; ///< ALM1WKDAY register
    const uint32_t SECONDS_PER_DAY = 86400; ///< 60 secs * 60 mins * 24 hours
    const uint32_t SECONDS_FROM_1970_TO_2000 = 946684800; ///< Seconds between year 1970 and 2000

    Please let me know if any traces required at any line with break-point? Also, I can send the drivers again with a private link to your INBOX it is required?

  • The trace clearly show that its only the MCP7940_I2C address that is transmitted. The nrf_drv_twi_tx documentation states that the data passed to it should be a uint8_t pointer, so try passing it like this

    uint8_t tx_data = REG_RTCHOUR;

    err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C,&tx_data , sizeof(tx_data));

    APP_ERROR_CHECK(err_code)

    Furthermore what does the bitClear (registerValue, 6) and bitSet (registerValue, 6) functions do? You are passing they're return value as the length parameter to nrf_drv_twi_tx and nrf_drv_twi_rx.

    void init_MCP7940() {
    
        char registerValue = 0x00; // Holds the received register value
        char twelveHour = 0x00; // 0 = 24 Hour Clock Mode / 1 = 12 Hour Clock Mode
        char startClock = 0x01; // 0 = Start Oscillator / 1 = Stop Oscillator
        
        // Turn on/off: 12 hour vs. 24 hour clock
        err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C, REG_RTCHOUR, 1);
        err_code = nrf_drv_twi_rx(&m_twi, MCP7940_I2C, registerValue, sizeof(MCP7940_I2C));
        
        if (twelveHour == 0x00) err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C, REG_RTCHOUR, bitClear (registerValue, 6));
        if (twelveHour == 0x01) err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C, REG_RTCHOUR, bitSet (registerValue, 6));
        
        // Turn on/off: Oscillator (starts the clock)
        err_code = nrf_drv_twi_rx(&m_twi, MCP7940_I2C, registerValue, 1);
        
        if (startClock == 0x00) err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C, REG_RTCSEC, bitClear (registerValue, 7));
        if (startClock == 0x01) err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C, REG_RTCSEC, bitSet (registerValue, 7));
    
    }

  • Custom defined which works as below:

    https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitclear/

    https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitset/

    Will update the traces & API call as per this soon!

    uint8_t tx_data = REG_RTCHOUR;

    err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C,&tx_data , sizeof(tx_data));

    APP_ERROR_CHECK(err_code)

  • Pls check the trace of REG_RTCHOUR, 

    const uint8_t MCP7940_RTCHOUR = 0x02; ///< Timekeeping, RTCHOUR Register address

  • Yes, now you are writing to register with address 0x02 of the device with address 0xDE, but you are not providing the value you want to write to register 0x02. 

    uint8_t tx_data[] = {REG_RTCHOUR, <value to write to REG_RTCHOUR register> };
    
    err_code = nrf_drv_twi_tx(&m_twi,MCP7940_I2C,tx_data , sizeof(tx_data));
    
    APP_ERROR_CHECK(err_code)

Related