use RTC square wave output to sync on seconds

This commit is contained in:
King Kévin 2017-04-02 10:15:13 +02:00
parent ed8d8f985a
commit bbc66e3c82
1 changed files with 47 additions and 37 deletions

84
main.c
View File

@ -49,9 +49,12 @@
/** @defgroup main_flags flag set in interrupts to be processed in main task
* @{
*/
volatile bool rtc_internal_tick_flag = false; /**< flag set when internal RTC ticked */
volatile bool rtc_tick_flag = false; /**< flag set when RTC ticked */
/** @} */
#define SQUARE_WAVE_PORT B /**< port connected to RTC DS1307 square wave output */
#define SQUARE_WAVE_PIN 0 /**< pin connected to RTC DS1307 square wave output */
/** user input command */
static char command[32] = {0};
/** user input command index */
@ -199,32 +202,42 @@ void main(void)
}
#endif
// setup internal RTC
printf("setup internal RTC: ");
rtc_auto_awake(RCC_LSE, 32768-1); // ensure internal RTC is on, uses the 32.678 kHz LSE, and the prescale is set to our tick speed, else update backup registers accordingly (power off the micro-controller for the change to take effect)
rtc_interrupt_enable(RTC_SEC); // enable RTC interrupt on "seconds"
nvic_enable_irq(NVIC_RTC_IRQ); // allow the RTC to interrupt
// disable internal RTC
printf("disable internal RTC: ");
rcc_periph_clock_enable(RCC_PWR); // enable power domain clock
rcc_periph_clock_enable(RCC_BKP); // enable backup domain clock
pwr_disable_backup_domain_write_protect(); // enable write on backup domain (including RTC)
RCC_BDCR &= ~RCC_BDCR_RTCEN; // disable RTC
printf("OK\n");
// display uptime
uint32_t ticks_time = rtc_get_counter_val(); // get time from internal RTC (since first start/power up)
printf("uptime: %u.%02u:%02u:%02u\n", ticks_time/(60*60*24), (ticks_time/(60*60))%24, (ticks_time%(60*60))/60, (ticks_time%60)); // display uptime
// setup external RTC
printf("setup external RTC: ");
rtc_ds1307_setup(); // setup external RTC module
// enable square wave output and configure input interrupt
rtc_ds1307_write_square_wave(1); // enable 1 Hz square wave output to sync on seconds
rcc_periph_clock_enable(RCC_GPIO(SQUARE_WAVE_PORT)); // enable clock for GPIO
gpio_set_mode(GPIO(SQUARE_WAVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(SQUARE_WAVE_PIN)); // set button pin to input
rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt
exti_select_source(EXTI(SQUARE_WAVE_PIN), GPIO(SQUARE_WAVE_PORT)); // mask external interrupt of this pin only for this port
exti_set_trigger(EXTI(SQUARE_WAVE_PIN), EXTI_TRIGGER_FALLING); // trigger on falling edge of square wave (this is also when the RTC register are updated)
exti_enable_request(EXTI(SQUARE_WAVE_PIN)); // enable external interrupt
nvic_enable_irq(NVIC_EXTI_IRQ(SQUARE_WAVE_PIN)); // enable interrupt
printf("OK\n");
// display date
uint8_t* rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC
uint8_t rtc_seconds = 0; // count the number of seconds passed and sync time on minute
if (rtc_ds1307_time==NULL) {
printf("could not get time from DS1307\n");
} else {
rtc_seconds = rtc_ds1307_time[0]; // remember seconds of minute
printf("current date: 20%02u-%02u-%02u %02u:%02u:%02u\n", rtc_ds1307_time[6], rtc_ds1307_time[5], rtc_ds1307_time[4], rtc_ds1307_time[2], rtc_ds1307_time[1], rtc_ds1307_time[0]);
}
// verify is external RTC is running
if (rtc_ds1307_oscillator_disabled()) {
printf("/!\\ RTC oscillator is disabled: the battery may be empty\n");
rtc_ds1307_oscillator_enable(); // enable oscillator again
}
// display date
uint8_t* rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC
if (rtc_ds1307_time==NULL) {
printf("could not get time from DS1307\n");
} else {
printf("current date: 20%02u-%02u-%02u %02u:%02u:%02u\n", rtc_ds1307_time[6], rtc_ds1307_time[5], rtc_ds1307_time[4], rtc_ds1307_time[2], rtc_ds1307_time[1], rtc_ds1307_time[0]);
}
// setup TM1637 and MAX7219 7-segments displays
printf("setup 7-segment displays: ");
@ -306,26 +319,23 @@ void main(void)
}
button_flag = false; // reset flag
}
while (rtc_internal_tick_flag) { // the internal RTC ticked
rtc_internal_tick_flag = false; // reset flag
led_toggle(); // toggle LED (good to indicate if main function is stuck)
ticks_time = rtc_get_counter_val(); // copy time from internal RTC for processing
while (rtc_tick_flag) { // the external RTC ticked
rtc_tick_flag = false; // reset flag
action = true; // action has been performed
if ((ticks_time%(60))==0) { // one minute passed
printf("uptime: %u.%02u:%02u:%02u\n", ticks_time/(60*60*24), (ticks_time/(60*60))%24, (ticks_time%(60*60))/60, (ticks_time%60)); // display uptime
}
rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC
if (rtc_ds1307_time==NULL) {
printf("could not get time from DS1307: resetting\n");
rtc_ds1307_setup(); // resetting periph
} else {
if (!led_tm1637_time(rtc_ds1307_time[1], rtc_ds1307_time[0])) {
printf("could not set time on TM1637\n");
led_toggle(); // toggle LED (good to indicate if main function is stuck)
rtc_seconds++; // increment number of seconds passed
if (rtc_seconds>=60) { // one minute passed
rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC
if (rtc_ds1307_time==NULL) {
printf("could not get time from DS1307: resetting\n");
rtc_ds1307_setup(); // resetting periph
} else {
rtc_seconds = rtc_ds1307_time[0]; // get actual number of seconds
if (0==rtc_ds1307_time[1] && 0==rtc_ds1307_time[2]) { // new day arrived
led_max7219_number(20000000+rtc_ds1307_time[6]*10000+rtc_ds1307_time[5]*100+rtc_ds1307_time[4], 0x14, 1); // display date on 2nd display
}
}
}
if (!led_tm1637_on()) { // switch on display
printf("could not switch on TM1637\n");
}
}
if (action) { // go to sleep if nothing had to be done, else recheck for activity
action = false;
@ -335,9 +345,9 @@ void main(void)
} // main loop
}
/** @brief interrupt service routine called when tick passed on RTC */
void rtc_isr(void)
void EXTI_ISR(SQUARE_WAVE_PIN)(void)
{
rtc_clear_flag(RTC_SEC); // clear flag
rtc_internal_tick_flag = true; // notify to show new time
exti_reset_request(EXTI(SQUARE_WAVE_PIN)); // reset interrupt
rtc_tick_flag = true; // perform button action
}