The MCP7940M is a Real-Time Clock/Calendar (RTCC) with an I2C interface. This library is developed for AVR devices (tested on ATmega328PB) but it can easily be ported to other microcontroller types. The necessary I2C library is also included.
Here is some description from the datasheet:
The MCP7940M tracks time using internal counters for hours, minutes, seconds, days, months, years, and day of week. Alarms can be configured on all counters up to and including months. For usage and configuration, the MCP7940M supports I2C communications up to 400 kHz.
The open-drain, multi-functional output can be configured to assert on an alarm match, to output a selectable frequency square wave, or as a general purpose output. The MCP7940M is designed to operate using a 32.768 kHz tuning fork crystal with external crystal load capacitors. On-chip digital trimming can be used to adjust for frequency variance caused by crystal tolerance and temperature.
Contents
- Connecting MCP7940M
- API
- Configuration
- Functions
- Initialization
- Set seconds
- Set minutes
- Set hours
- Set day of the week
- Set day of the month
- Set month
- Set year
- Read seconds
- Read minutes
- Read hours
- Read day of week
- Read day of month
- Read month
- Read year
- Check if leap year
- Read oscillator status
- Alarm
- Turn alarm on/off
- Set alarm polarity
- Set seconds alarm
- Set minutes alarm
- Set hours alarm
- Set day of week alarm
- Set day of month alarm
- Set alarm
- Check if alarm is on
- Set EXTOSC
- Set CRSTRIM
- Digital trimming
- Configure MFP
- Set MFP
- Set MFP frequency
- Write SRAM
- Read SRAM
- Code example & tutorial
- Links
Connecting MCP7940M
MCP7940M pinout
1 - X1: Quartz Crystal Input or External Oscillator Input
2 - X2: Quartz Crystal Output
3 - NC: Not Connected
4 - Vss: Ground
5 - SDA: Bidirectional Serial Data (I2C). Connect a pull-up resistor. Usually 10k.
6 - SCL: Serial Clock (I2C). Connect a pull-up resistor. Usually 10k.
7 - MFP: Open-drain multifunction pin. Connect a pull-up resistor. Usually 10k-100k. Can be configured as a GPIO controlled via I2C, or to change state whenever the alarm triggers or to output a pre-selected frequency.
8 - VCC: Power supply (1.8V to 5.5V).
API
Configuration
The library uses the TWI0 module by default and can be changed in the header file. The MCP7940M serial address is 0xDE as defined in the datasheet. TWI speed is 100kHz by default and can be changed to 400kHz if needed.
Functions
Initialization
void MCP_Init(void)
Used to initialize the TWI (I2C) interface and to enable the oscillator bit in the RTCSEC register.
Set seconds
void MCP_SetSeconds(uint8_t seconds)
Set seconds.
seconds
Decimal value from 0 to 59.
Set minutes
void MCP_SetMinutes(uint8_t minutes)
Set minutes.
minutes
Decimal value from 0 to 59.
Set hours
void MCP_SetHours(uint8_t hours, uint8_t hr_format, uint8_t am_pm)
Set hours in a 12 or 24 format.
hours
Decimal value from 0 to 23 or 1 to 12.
hr_format
Hour format. Can be one of the available constants MCP_12H_FORMAT or MCP_24H_FORMAT.
am_pm
With 24 hour format, this can be 0. When 12 hour format is used, this indicates the AM/PM bit. Can be one of the available constants MCP_PM or MCP_AM.
Set day of the week
void MCP_SetWeekday(Day weekday)
Week day.
weekday
A value from 1 to 7. The representation is user-defined. The following enumeration is also available to be able to use name of the day instead of numbers.
typedef enum DAY { Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday, INCORRECTDATEFORMAT } Day;
Set day of the month
void MCP_SetMonthDay(uint8_t day)
Day of the month.
day
Decimal value from 1 to 31.
Set month
void MCP_SetMonth(Month month)
Month of the year.
month
Value from 1 to 12. The following enumeration is also available to be able to use name of the month instead of numbers.
typedef enum MONTH { January = 1, February, March, April, May, June, July, August, September, October, November, December } Month;
Set year
void MCP_SetYear(uint8_t year)
The year in a two digit format.
year
A value from 0 to 99 in a two digit format. For example year 2025 would be 25.
Read seconds
uint8_t MCP_ReadSeconds(void)
Returns seconds.
Read minutes
uint8_t MCP_ReadMinutes(void)
Returns minutes.
Read hours
uint8_t MCP_ReadHours(uint8_t hr_format)
Returns hours in a 12 or 24 hour format.
hr_format
Hour format. Can be one of the available constants MCP_12H_FORMAT or MCP_24H_FORMAT
Read day of week
Day MCP_ReadWeekday(void)
Returns day of week from 1 to 7.
Read day of month
uint8_t MCP_ReadMonthDay(void)
Returns day of the month from 1 to 31.
Read month
Month MCP_ReadMonth(void)
Returns a number form 1 to 12 representing the month.
Read year
uint8_t MCP_ReadYear(void)
Returns the year in a two digit format. For example year 2025 will read as 25.
Check if leap year
bool MCP_IsLeapYear(void)
Returns 1 if year is a leap year.
Read oscillator status
uint8_t MCP_ReadOSCRUN(void)
Returns 1 if oscillator is enabled and running or 0 if oscillator has stopped or has been disabled. Could be used as a wrapper for every other function.
Usage:
if(MCP_ReadOSCRUN()){ // Read time }
Alarm
The MCP7940M has two alarm modules that can be configured individually. Most alarm functions require a pointer to one of the two available structure objects named alarm0 and alarm1.
Only one mask is possible for an alarm module so only one function type should be used. For example doing:
MCP_setAlarmSecond();
MCP_setAlarmMinute();
The alarm will trigger only on set minute since that function was used last and configured the alarm mask. Use setAlarm() to set alarm mask for second, minute, hour, day of week, day of month and month all at the same time.
Turn alarm on/off
void MCP_alarmOnOff(ALARM_t* alarm, uint8_t state)
Turn alarm on/off using the enable bit and clear the interrupt flag. When both alarm modules are disabled, the MFP pin will be in GPIO mode, and the pin state is defined by the OUT bit.
alarm
Pointer to an alarm object. Example: &alarm0 or &alarm1.
state
ALARM_ON or ALARM_OFF.
Set alarm polarity
void MCP_setALMPOL(uint8_t bit)
Set Alarm Interrupt Output Polarity bit. MFP mode must be set to an interrupt type.
bit
1 = Asserted output state of MFP is a logic high level (normal low, high when alarm on) 0 = Asserted output state of MFP is a logic low level
Set seconds alarm
void MCP_setAlarmSecond(ALARM_t* alarm, uint8_t second)
Set alarm to trigger at a given second. Triggers every minute.
Set minutes alarm
void MCP_setAlarmMinute(ALARM_t* alarm, uint8_t minute)
Set alarm to trigger at a given minute. Triggers every hour.
Set hours alarm
void MCP_setAlarmHour(ALARM_t* alarm, uint8_t hour, uint8_t hr_format, uint8_t am_pm)
Set alarm to trigger at a given hour. Triggers every day at the specified hour.
Set day of week alarm
void MCP_setAlarmWeekDay(ALARM_t* alarm, Day day)
Set alarm to trigger at a day of week. Triggers every week.
Set day of month alarm
void MCP_setAlarmMonthDay(ALARM_t* alarm, uint8_t day)
Set alarm to trigger at a day of month. Triggers every month.
Set alarm
void MCP_setAlarm(ALARM_t* alarm, uint8_t second, uint8_t minute, uint8_t hour, uint8_t hr_format, uint8_t am_pm, Day weekday, uint8_t monthday, Month month)
Set alarm to match second, minute, hour, day of week, day of month and month.
Check if alarm is on
bool MCP_isAlarmOn(ALARM_t* alarm)
Check if alarm is on by checking the interrupt flag. Returns 1 if alarm is on.
Set EXTOSC
void MCP_setEXTOSC(uint8_t bit)
Set or clear the External Oscillator Input bit (EXTOSC) in CONTROL register.
bit
1 = Enable X1 pin to be driven by external 32.768 kHz source
0 = Disable external 32.768 kHz input
Set CRSTRIM
void MCP_setCRSTRIM(uint8_t bit)
Set or clear the Coarse Trim Mode Enable bit (CRSTRIM) in CONTROL register. Coarse Trim mode results in the MCP7940M applying digital trimming every 64 Hz clock cycle.
From what I understand, this mode is for calibration only.
"With Coarse Trim mode enabled, the TRIMVAL<6:0> value has a drastic effect on timing. Leaving the mode enabled during normal operation will likely result in inaccurate time.
By monitoring the MFP output frequency while in this mode, the user can easily observe the TRIMVAL<6:0> value affecting the clock timing."
bit
1 = Enable Coarse Trim mode. If SQWEN = 1, MFP will output trimmed 64 Hz nominal clock signal. When SQWEN = 1, the only output frequency will be 64Hz.
0 = Disable Coarse Trim mode
Digital trimming
void MCP_setOSCTRIM(uint8_t sign, uint8_t trimval)
Apply digital trimming.
sign
Trim sign bit. Can be one of following constants: ADD_CLOCKS, SUBTRACT_CLOCKS.
ADD_CLOCKS: 1 = Add clocks to correct for slow time
SUBTRACT_CLOCKS: 0 = Subtract clocks to correct for fast time
trimval
Oscillator Trim Value bits. Number obtained from datasheet formula. It will be shifted right by 1 to convert it to power of 2. When CRSTRIM = 1, divide the number by 128.
When CRSTRIM = 0:
1111111 = Add or subtract 254 clock cycles every minute
1111110 = Add or subtract 252 clock cycles every minute
0000010 = Add or subtract 4 clock cycles every minute
0000001 = Add or subtract 2 clock cycles every minute
0000000 = Disable digital trimming
When CRSTRIM = 1:
1111111 = Add or subtract 254 clock cycles 128 times per second
1111110 = Add or subtract 252 clock cycles 128 times per second
0000010 = Add or subtract 4 clock cycles 128 times per second
0000001 = Add or subtract 2 clock cycles 128 times per second
0000000 = Disable digital trimming
Configure MFP
void MCP_configMFP(uint8_t mode)
Configure the MFP (Multi Function Pin) output. Alarm interrupt modes are activated using the functions for setting the alarm.
mode
Available constants:
MFP_MODE_GPIO: 0 - General Purpose Output (GPIO)
MFP_MODE_SQRWAVE: 4 - Square Wave Clock Output
Set MFP
void MCP_setMFPin(uint8_t pin_state)
Set the MFP (Multi Function Pin) output as high or low. Available only when in GPIO mode. Switching frequency is limited by the I2C speed.
Set MFP frequency
void MCP_setMFPfreq(uint8_t freq)
Set the MFP (Multi Function Pin) output frequency. Available only when in MFP_MODE_SQRWAVE mode set using MCP_configMFP().
freq
Available constants:
MFP_SQWFS_1HZ: 1 Hz
MFP_SQWFS_4096HZ: 4096 Hz
MFP_SQWFS_8192HZ: 8192 Hz
MFP_SQWFS_32768HZ: 32768 Hz
Write SRAM
uint8_t MCP_writeSRAM(uint8_t addr, uint8_t data)
Write 1 byte to RTC SRAM. Memory is volatile.
addr
RAM address from 0 to 63 (64 bytes total). It will be mapped to RTC SRAM memory starting from 0x20 and ending at 0x5F.
data
One byte of data.
return
Number of bytes written. 0 means address out of range.
Read SRAM
uint8_t MCP_readSRAM(uint8_t addr)
Read 1 byte from RTC SRAM.
addr
RAM address from 0 to 63 (64 bytes total). It will be mapped to RTC SRAM memory starting from 0x20 and ending at 0x5F.
return
The byte read from RTC memory. 0 could mean address out of range or data is 0.
Code example & tutorial
#include "MCP7940M.h" int main(void){ uint8_t seconds = 0; uint8_t minutes = 0; uint8_t hours = 0; uint8_t weekday = 0; uint8_t monthday = 0; uint8_t month = 0; uint8_t year = 0; bool sysinit = false; // Initialize the TWI (I2C) interface and enable the RTC oscillator. MCP_Init(); // Set time. Values could be taken from a user input interface. MCP_SetSeconds(45); MCP_SetMinutes(10); MCP_SetHours(13, MCP_24H_FORMAT, 0); MCP_SetWeekday(Monday); MCP_SetMonthDay(26); MCP_SetMonth(June); MCP_SetYear(25); // SENARIO 1: Configure alarm: set MFP to change state when the alarm trigger. // Could drive an active type buzzer or trigger a pin interrupt // to wake a microcontroller from sleep mode. MCP_setALMPOL(1); // MFP normal low, hight when alarm is on // Set alarm to trigger at 7:10:30 (HH:MM:SS) 24 hour format // every Monday day 8 of the month in June. // To trigger an alarm, all values must match but most of the time // we want the alarm every day, so the application should update these every day // to trigger for the next day. MCP_setAlarm(&alarm0, 30, 10, 7, MCP_24H_FORMAT, 0, Monday, 8, June); // If minutes are irrelevant, an alarm can be set to trigger each day // at a certain hour using another register mask. MCP_setAlarmHour(&alarm0, 7, MCP_24H_FORMAT, 0); // every day at 7 in 24 hour format // SCENARIO 2: MFP pin is set to output a certain frequency // MFP mode set to square wave MCP_configMFP(MFP_MODE_SQRWAVE); // Frequency set to 4096 Hz. Can be used to measure and trim the crystal or // to control a passive buzzer for an alarm while a microcontroller pin // would modulate the transistor base to create beeps. MCP_setMFPfreq(MFP_SQWFS_4096HZ); // SCENARIO 3: use the MFP pin as a GPIO MCP_configMFP(MFP_MODE_GPIO); MCP_setMFPin(0); // set MFP low MCP_setMFPin(1); // set MFP high while(1){ // Here we can ask the RTC for time values but // it should be done with a time delay considering the while loop // is very fast and the smaller time value is 1 second. // Another interrupt could be used to compound a variable and form // a time interval of roughly 1 second and then put the MCU to sleep. // Minutes, hours... could be updated every 60 seconds. // Example: //if(1 second elapsed){ // Check if RTC oscillator is working if(MCP_ReadOSCRUN()){ // Read time seconds = MCP_ReadSeconds(); // Update every minute when seconds reach 0 which is the next value // after 59 indicating the minute will change. If the minute will change // the hour could change and also the rest of time values. // sysinit variable is used to update the time in the first minute. if((sysinit == false) || (seconds == 0)){ sysinit = true; minutes = MCP_ReadMinutes(); hours = MCP_ReadHours(MCP_24H_FORMAT); weekday = MCP_ReadWeekday(); monthday = MCP_ReadMonthDay(); month = MCP_ReadMonth(); year = MCP_ReadYear(); } // Check if alarm is on by checking the interrupt flag in the RTC register if(MCP_isAlarmOn(&alarm0)){ // Alarm is on. If seconds are greater than 5 the alarm will be turned off. if(seconds > 5) MCP_alarmOnOff(&alarm0, ALARM_OFF); } } //} } return 1; }
Links
v1.0 | MCP7940M library |
Folder includes: MCP7940M, twi |
Changelog | ||
v1.0 (2025-06-25) |
Public release under GNU GPL v3 license. |
No comments:
Post a Comment