From: Robin Krens Date: Wed, 14 Aug 2019 14:21:21 +0000 (+0800) Subject: rtc example with tm1637 driver X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=811b81ae2d0cc24f6c8203e81d2e9a00a98d936b;p=cortex-from-scratch rtc example with tm1637 driver --- diff --git a/drivers/tm1637.c b/drivers/tm1637.c index b6453ae..1d78f7a 100644 --- a/drivers/tm1637.c +++ b/drivers/tm1637.c @@ -84,7 +84,6 @@ void tm1637_reset() { * grid. Grid 1 an 2 have an additional dot that can be set */ int set_grid(uint8_t offset, char value, bool dot) { - //int (*ack)() = ack_recv; /* Scary function pointer :D */ if (offset > 3) { printf("Offset incorrect"); @@ -118,13 +117,21 @@ int set_grid(uint8_t offset, char value, bool dot) { tm1637_reset(); + + int (*ack)() = &ack_recv; + if ((((value >> 4) & 0xF) == 0xF ) && !(value & 0x08)) { + ack = &ack10_recv; + } + /* Write value to segments */ start_condition(); rwrite(I2C_DR, value); - if(!ack_recv()) - return -1; - stop_condition(); + if(!ack()) { + // return -1; + } + stop_condition(); + delay(); // wait for the chip to finish writing tm1637_reset(); return 0; @@ -145,27 +152,20 @@ int set_display(bool on, uint8_t degree) { return -1; } stop_condition(); - tm1637_reset(); return 0; - } - void tm1637_example() { -unsigned char display_number[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6}; - - + unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6}; char love[4] = { 0x1C, 0xFC, 0x7C, 0x9E }; - + for (int i = 0; i < 4; i++) { set_grid(i, love[i], NODOT); } - set_display(true, 0); - } /* HELPER ROUTINES */ @@ -207,6 +207,14 @@ int ack10_recv() { } +/* Write delay chip */ +static void delay() { + int a = 0; + for (int i = 0; i < 500; i++) + a++; +} + + /* Check if lines are idle (i.e. stop condition finished)*/ int idle() { int cnt = 0; diff --git a/include/drivers/tm1637.h b/include/drivers/tm1637.h index e537cdf..64e1f78 100644 --- a/include/drivers/tm1637.h +++ b/include/drivers/tm1637.h @@ -7,10 +7,12 @@ static void stop_condition(); static int ack_recv(); static int ack10_recv(); static int idle(); +static void delay(); extern void tm1637_init(); extern int set_grid(uint8_t offset, char value, bool dot); extern int set_display(bool on, uint8_t degree); + extern void tm1637_example(); #endif diff --git a/main.c b/main.c index 68eaa03..da28711 100644 --- a/main.c +++ b/main.c @@ -69,10 +69,10 @@ void main() led_init(); // eeprom_at24c_init(); // eeprom_test(); + tm1637_init(); + rtc_init(); - tm1637_init(); - tm1637_example(); //uint32_t test = hextoreg("12345678"); diff --git a/rtc.c b/rtc.c index 4877d92..1f1136a 100644 --- a/rtc.c +++ b/rtc.c @@ -1,10 +1,17 @@ /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL * * $LOG$ - * 2019/7/30 - ROBIN KRENS + * 2019/8/14 - ROBIN KRENS * Initial version * * $DESCRIPTION$ + * Real Time Clock configuration. A Real Time Clock is configured to use + * the more accurate external chrystal (LSE) and ticks at exactly + * one second. (Can be further calibrated using a tamper pin) + * Each clock tick triggers an interrupt and invokes the real time clock + * service routine. + * + * Note: this is not the Cortex M3/M4 SysTick! * * */ @@ -16,52 +23,70 @@ #include #include -#include +#include #include +#include -static void periodic_intr() { +/* This handler is invoked each clock tick. I've included two examples + * one is writing the clock count to a 4 grid led display. Another is a simple LED blink */ +void * rtc_handler() { - while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated - rsetbit(RTC_CRL, 4); // start configure - - rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt - - while(!rchkbit(RTC_CRL, 5)); + // Real time clock output on a LED display + int cntvalue = *RTC_CNTL; + if (cntvalue < 9999) { - rwrite(RTC_PRLL, 0x7FFF); // 1 second - rclrbit(RTC_CRL, 4); // stop configure - while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated - rsetbit(NVIC_ISER0, 3); // enable in register vector -} + unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6}; + + int grid0, grid1, grid2, grid3; -static void calibrate_rtc() { + grid0 = cntvalue % 10; + grid1 = ((cntvalue % 100) - grid0) / 10; + grid2 = ((cntvalue % 1000) - grid0 - grid1) / 100; + grid3 = ((cntvalue % 10000) - grid0 - grid1 - grid2) / 1000; + printf("%d, %d, %d, %d\n", grid0, grid1, grid2, grid3); + + + char current[4] = { dn[grid3], dn[grid2], dn[grid1], dn[grid0] }; -// rsetbit(BKP_RTCCR, 7); // enable CC0, -// while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated -// rsetbit(RTC_CRL, 4); + //char current[4] = { dn[1], dn[1], dn[1], dn[1] }; + for (int i = 0; i < 4; i++) { + set_grid(i, current[i], false); + } - // Set up and check tamper pin + set_display(true, 0); -// rclrbit(RTC_CRL, 4); -// while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated -} - -void * rtc_handler() { + } - //cputs("TICKING IN REAL TIME\n"); + // Simple LED blink //uint32_t curr = *RTC_CNTL; - int even = *RTC_CNTL % 2; - (!even) ? led_off() : led_on(); + //int even = *RTC_CNTL % 2; + //(!even) ? led_off() : led_on(); - rclrbit(RTC_CRL, 0); + rclrbit(RTC_CRL, 0); /* clear interrupt flag */ } +/* Enable a periodic interrupt. At each clock count a interrupt is triggered + * and consequently the handler is invoked. */ +static void periodic_intr() { + + while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated + rsetbit(RTC_CRL, 4); // start configure + rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt + + while(!rchkbit(RTC_CRL, 5)); + rwrite(RTC_PRLL, 0x7FFF); // 0x7FFF equals 1 second clock configuration + rclrbit(RTC_CRL, 4); // stop configure + while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated + rsetbit(NVIC_ISER0, 3); // enable in register vector +} + +/* Setup the Real time clock to work with the Low speed external + * chrystal (32.768 kHz) */ static void setup_rtc() { -// TODO: long time to get stable? /* Enable PWREN and BKPEN */ rsetbit(RCC_APB1ENR, 28); rsetbit(RCC_APB1ENR, 27); @@ -77,12 +102,23 @@ static void setup_rtc() { ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */ -// calibrate_rtc(); TODO: TAMPER PIN? + //calibrate_rtc(); // uncomment if need, needs TAMPER PIN periodic_intr();// setup periodic interrupt } +/* Function to calibrate the RTC even more accurate. + * Output to a so-called tamper pin. Uncomment if needed */ +static void calibrate_rtc() { + /* rsetbit(BKP_RTCCR, 7); // enable CC0, + while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated + rsetbit(RTC_CRL, 4); + // Set up and check tamper pin + rclrbit(RTC_CRL, 4); + while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated */ +} + void rtc_init() { #ifdef ENABLE_RTC