打印
[Atmel]

用SAM-BA或JLINK跑ATSAM4E16的程序(17)ASF RTC

[复制链接]
664|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ddllxxrr|  楼主 | 2015-11-24 21:43 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ddllxxrr 于 2015-11-24 21:54 编辑

RTC可选内部或外部32.768kHz晶振驱动。可定时,报警,更新时间/日历,还可以通过RTCOUT0和RTCOUT1输出波形。


以下程序就是同串**互,可以设日期,设时间,设报警时间,设日期报警,清除报警,和产生波形:

程序如下:

#include "asf.h"
#include "stdio_serial.h"
#include "conf_clock.h"
#include "conf_board.h"

/// [url=home.php?mod=space&uid=1302964]@cond[/url] 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond

/* Main menu is being displayed. */
#define STATE_MENU             0
/* Time is being edited. */
#define STATE_SET_TIME         1
/* Date is being edited. */
#define STATE_SET_DATE         2
/* Time alarm is being edited. */
#define STATE_SET_TIME_ALARM   3
/* Date alarm is being edited. */
#define STATE_SET_DATE_ALARM   4
/* Wave generating is being edited. */
#define STATE_WAVEFORM         5

/* Maximum size of edited string. */
#define MAX_EDIT_SIZE          10

/* Macro for converting char to digit. */
#define char_to_digit(c) ((c) - '0')

#define STRING_EOL    "\r"
#define STRING_HEADER "-- RTC Example --\r\n" \
                "-- "BOARD_NAME" --\r\n" \
                "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL

/* Current state of application. */
static uint32_t gs_ul_state = STATE_MENU;

/* Edited hour. */
static uint32_t gs_ul_new_hour;
/* Edited minute. */
static uint32_t gs_ul_new_minute;
/* Edited second. */
static uint32_t gs_ul_new_second;

/* Edited year. */
static uint32_t gs_ul_new_year;
/* Edited month. */
static uint32_t gs_ul_new_month;
/* Edited day. */
static uint32_t gs_ul_new_day;
/* Edited day-of-the-week. */
static uint32_t gs_ul_new_week;

/* Indicate if alarm has been triggered and not yet cleared */
static uint32_t gs_ul_alarm_triggered = 0;

/* Time string */
static uint8_t gs_uc_rtc_time[8 + 1] =
                { '0', '0', ':', '0', '0', ':', '0', '0', '\0' };
/* Date string */
static uint8_t gs_uc_date[10 + 1] =
                { '0', '0', '/', '0', '0', '/', '0', '0', '0', '0', '\0' };
/* Week string */
static uint8_t gs_uc_day_names[7][4] =
                { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };

/* Flag for refreshing menu */
static uint32_t gs_ul_menu_shown = 0;

/**
*  Configure UART console.
*/
static void configure_console(void)
{
        const usart_serial_options_t uart_serial_options = {
                .baudrate = CONF_UART_BAUDRATE,
#ifdef CONF_UART_CHAR_LENGTH
                .charlength = CONF_UART_CHAR_LENGTH,
#endif
                .paritytype = CONF_UART_PARITY,
#ifdef CONF_UART_STOP_BITS
                .stopbits = CONF_UART_STOP_BITS,
#endif
        };

        /* Configure console UART. */
        sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
        stdio_serial_init(CONF_UART, &uart_serial_options);
}

/**
* \brief Get new time. Successful value is put in gs_ul_new_hour,
* gs_ul_new_minute, gs_ul_new_second.
*/
static uint32_t get_new_time(void)
{
        uint8_t uc_key;
        uint32_t i = 0;

        /* Clear setting variable. */
        gs_ul_new_hour = 0xFFFFFFFF;
        gs_ul_new_minute = 0xFFFFFFFF;
        gs_ul_new_second = 0xFFFFFFFF;

        /* Use gs_uc_rtc_time[] as a format template. */
        while (1) {

                scanf("%c", (char *)&uc_key);

                /* End input */
                if (uc_key == 0x0d || uc_key == 0x0a) {
                        puts("\r");
                        break;
                }

                /* DEL or BACKSPACE */
                if (uc_key == 0x7f || uc_key == 0x08) {
                        if (i > 0) {
                                /* End of gs_uc_rtc_time[], then one more back of index */
                                if (!gs_uc_rtc_time[i]) {
                                        --i;
                                }

                                puts("\b \b");
                                --i;

                                /* Delimiter ':' for time is uneditable */
                                if (!((gs_uc_rtc_time[i]) >= '0' && (gs_uc_rtc_time[i]) <= '9')
                                                && i > 0) {
                                        puts("\b \b");
                                        --i;
                                }
                        }
                }

                /*
                 * End of gs_uc_rtc_time[], no more input except the above DEL/BS,
                 * or enter to end.
                 */
                if (!gs_uc_rtc_time[i]) {
                        continue;
                }

                printf("%c", uc_key);
                gs_uc_rtc_time[i++] = uc_key;

        }

        if (i == 0) {
                return 0;
        }

        if (i != 0 && gs_uc_rtc_time[i] != '\0') {
                /* Failure input */
                return 1;
        }

        gs_ul_new_hour = char_to_digit(gs_uc_rtc_time[0]) * 10 +
                        char_to_digit(gs_uc_rtc_time[1]);
        gs_ul_new_minute = char_to_digit(gs_uc_rtc_time[3]) * 10 +
                        char_to_digit(gs_uc_rtc_time[4]);
        gs_ul_new_second = char_to_digit(gs_uc_rtc_time[6]) * 10 +
                        char_to_digit(gs_uc_rtc_time[7]);

        /* Success input. Verification of data is left to RTC internal Error Checking. */
        return 0;
}

/**
* \brief Calculate week from year, month, day.
*/
static uint32_t calculate_week(uint32_t ul_year, uint32_t ul_month,
                uint32_t ul_day)
{
        uint32_t ul_week;

        if (ul_month == 1 || ul_month == 2) {
                ul_month += 12;
                --ul_year;
        }

        ul_week = (ul_day + 2 * ul_month + 3 * (ul_month + 1) / 5 + ul_year +
                        ul_year / 4 - ul_year / 100 + ul_year / 400) % 7;

        ++ul_week;

        return ul_week;
}

/**
* \brief Get new time. Successful value is put in gs_ul_new_year,
* gs_ul_new_month, gs_ul_new_day, gs_ul_new_week.
*/
static uint32_t get_new_date(void)
{
        uint8_t uc_key;
        uint32_t i = 0;

        /* Clear setting variable */
        gs_ul_new_year = 0xFFFFFFFF;
        gs_ul_new_month = 0xFFFFFFFF;
        gs_ul_new_day = 0xFFFFFFFF;
        gs_ul_new_week = 0xFFFFFFFF;

        /* Use gs_uc_rtc_time[] as a format template */
        while (1) {

                scanf("%c", (char *)&uc_key);

                /* End input */
                if (uc_key == 0x0d || uc_key == 0x0a) {
                        puts("\r");
                        break;
                }

                /* DEL or BACKSPACE */
                if (uc_key == 0x7f || uc_key == 0x08) {
                        if (i > 0) {
                                /* End of date[], then one more back of index */
                                if (!gs_uc_date[i]) {
                                        --i;
                                }

                                puts("\b \b");
                                --i;

                                /* Delimiter '/' for date is uneditable */
                                if (!((gs_uc_date[i]) >= '0' && (gs_uc_date[i]) <='9')
                                                && i > 0) {
                                        puts("\b \b");
                                        --i;
                                }
                        }
                }

                /*
                 * End of gs_uc_rtc_time[], no more input except the above DEL/BS,
                 * or enter to end.
                 */
                if (!gs_uc_date[i]) {
                        continue;
                }

                printf("%c", uc_key);
                gs_uc_date[i++] = uc_key;

        }

        if (i == 0) {
                return 0;
        }

        if (i != 0 && gs_uc_date[i] != '\0' && i != 6) {
                /* Failure input */
                return 1;
        }

        /* MM-DD-YY */
        gs_ul_new_month = char_to_digit(gs_uc_date[0]) * 10
                        + char_to_digit(gs_uc_date[1]);
        gs_ul_new_day = char_to_digit(gs_uc_date[3]) * 10
                        + char_to_digit(gs_uc_date[4]);
        if (i != 6) {
                /* For 'Set Date' option, get the input new year and new week. */
                gs_ul_new_year = char_to_digit(gs_uc_date[6]) * 1000 +
                                char_to_digit(gs_uc_date[7]) * 100 +
                                char_to_digit(gs_uc_date[8]) * 10 +
                                char_to_digit(gs_uc_date[9]);
                gs_ul_new_week = calculate_week(gs_ul_new_year, gs_ul_new_month,
                                gs_ul_new_day);
        }

        /*
         * Success input. Verification of data is left to RTC internal Error
         * Checking.
         */
        return 0;
}


/**
* \brief Display the user interface on the terminal.
*/
static void refresh_display(void)
{
        uint32_t ul_hour, ul_minute, ul_second;
        uint32_t ul_year, ul_month, ul_day, ul_week;

        if (gs_ul_state != STATE_MENU) {
                /* Not in menu display mode, in set mode. */
        } else {
                /* Retrieve date and time */
                rtc_get_time(RTC, &ul_hour, &ul_minute, &ul_second);
                rtc_get_date(RTC, &ul_year, &ul_month, &ul_day, &ul_week);

                /* Display */
                if (!gs_ul_menu_shown) {
                        puts("\n\rMenu:\n\r"
                                        "  t - Set time\n\r"
                                        "  d - Set date\n\r"
                                        "  i - Set time alarm\n\r"
                                        "  m - Set date alarm\r");
#if ((SAM3S8) || (SAM3SD8) || (SAM4S) || (SAM4C) || (SAM4CP) || (SAM4CM) || (SAMV71)|| (SAMV70) || (SAME70) || (SAMS70))
                        puts("  w - Generate Waveform\r");
#endif
                        if (gs_ul_alarm_triggered) {
                                puts("  c - Clear alarm notification\r");
                        }

                        printf("\n\r");

                        gs_ul_menu_shown = 1;
                }

                /* Update current date and time */
                puts("\r");
                printf(" [Time/Date: %02u:%02u:%02u, %02u/%02u/%04u %s ][Alarm status:%s]",
                        (unsigned int)ul_hour, (unsigned int)ul_minute, (unsigned int)ul_second,
                        (unsigned int)ul_month, (unsigned int)ul_day, (unsigned int)ul_year,
                        gs_uc_day_names[ul_week-1], gs_ul_alarm_triggered?"Triggered!":"");
        }
}

/**
* \brief Interrupt handler for the RTC. Refresh the display.
*/
void RTC_Handler(void)
{
        uint32_t ul_status = rtc_get_status(RTC);

        /* Second increment interrupt */
        if ((ul_status & RTC_SR_SEC) == RTC_SR_SEC) {
                /* Disable RTC interrupt */
                rtc_disable_interrupt(RTC, RTC_IDR_SECDIS);

                refresh_display();

                rtc_clear_status(RTC, RTC_SCCR_SECCLR);

                rtc_enable_interrupt(RTC, RTC_IER_SECEN);
        } else {
                /* Time or date alarm */
                if ((ul_status & RTC_SR_ALARM) == RTC_SR_ALARM) {
                        /* Disable RTC interrupt */
                        rtc_disable_interrupt(RTC, RTC_IDR_ALRDIS);

                        gs_ul_alarm_triggered = 1;
                        refresh_display();
                        /* Show additional menu item for clear notification */
                        gs_ul_menu_shown = 0;
                        rtc_clear_status(RTC, RTC_SCCR_ALRCLR);
                        rtc_enable_interrupt(RTC, RTC_IER_ALREN);
                }
        }
}


/**
* \brief Application entry point for RTC example.
*
* \return Unused (ANSI-C compatibility).
*/
int main(void)
{
        uint8_t uc_key;

        /* Initialize the SAM system */
        sysclk_init();
        board_init();

        /* Initialize the console uart */
        configure_console();

        /* Output example information */
        puts(STRING_HEADER);

        /* Default RTC configuration, 24-hour mode */
        rtc_set_hour_mode(RTC, 0);

        /* Configure RTC interrupts */
        NVIC_DisableIRQ(RTC_IRQn);
        NVIC_ClearPendingIRQ(RTC_IRQn);
        NVIC_SetPriority(RTC_IRQn, 0);
        NVIC_EnableIRQ(RTC_IRQn);
        rtc_enable_interrupt(RTC, RTC_IER_SECEN | RTC_IER_ALREN);

        /* Refresh display once */
        refresh_display();

        /* Handle keypresses */
        while (1) {

                scanf("%c", (char *)&uc_key);

                /* Set time */
                if (uc_key == 't') {
                        gs_ul_state = STATE_SET_TIME;

                        do {
                                puts("\n\r\n\r Set time(hh:mm:ss): ");
                        } while (get_new_time());

                        /* If valid input, none of the variables for time is 0xff. */
                        if (gs_ul_new_hour != 0xFFFFFFFF && (gs_uc_rtc_time[2] == ':')
                                        && (gs_uc_rtc_time[5] == ':')) {
                                if (rtc_set_time(RTC, gs_ul_new_hour, gs_ul_new_minute,
                                                gs_ul_new_second)) {
                                        puts("\n\r Time not set, invalid input!\r");
                                }
                        } else {
                                gs_uc_rtc_time[2] = ':';
                                gs_uc_rtc_time[5] = ':';
                                puts("\n\r Time not set, invalid input!\r");
                        }

                        gs_ul_state = STATE_MENU;
                        gs_ul_menu_shown = 0;
                        refresh_display();
                }

                /* Set date */
                if (uc_key == 'd') {
                        gs_ul_state = STATE_SET_DATE;

                        do {
                                puts("\n\r\n\r Set date(mm/dd/yyyy): ");
                        } while (get_new_date());

                        /* If valid input, none of the variables for date is 0xff(ff). */
                        if (gs_ul_new_year != 0xFFFFFFFF && (gs_uc_date[2] == '/')
                                        && (gs_uc_date[5] == '/')) {
                                if (rtc_set_date(RTC, gs_ul_new_year, gs_ul_new_month,
                                                gs_ul_new_day, gs_ul_new_week)) {
                                        puts("\n\r Date not set, invalid input!\r");
                                }
                        } else {
                                gs_uc_date[2] = '/';
                                gs_uc_date[5] = '/';
                                puts("\n\r Time not set, invalid input!\r");
                        }

                        /* Only 'mm/dd' is input. */
                        if (gs_ul_new_month != 0xFFFFFFFF &&
                                                gs_ul_new_year == 0xFFFFFFFF) {
                                puts("\n\r Not Set for no year field!\r");
                        }

                        gs_ul_state = STATE_MENU;
                        gs_ul_menu_shown = 0;
                        refresh_display();
                }

                /* Set time alarm */
                if (uc_key == 'i') {
                        gs_ul_state = STATE_SET_TIME_ALARM;

                        rtc_clear_date_alarm(RTC);

                        do {
                                puts("\n\r\n\r Set time alarm(hh:mm:ss): ");
                        } while (get_new_time());

                        if (gs_ul_new_hour != 0xFFFFFFFF && (gs_uc_rtc_time[2] == ':')
                                        && (gs_uc_rtc_time[5] == ':')) {
                                if (rtc_set_time_alarm(RTC, 1, gs_ul_new_hour,
                                                1, gs_ul_new_minute, 1, gs_ul_new_second)) {
                                        puts("\n\r Time alarm not set, invalid input!\r");
                                } else {
                                        printf("\n\r Time alarm is set at %02u:%02u:%02u!",
                                                (unsigned int)gs_ul_new_hour, (unsigned int)gs_ul_new_minute,
                                                (unsigned int)gs_ul_new_second);
                                }
                        } else {
                                gs_uc_rtc_time[2] = ':';
                                gs_uc_rtc_time[5] = ':';
                                puts("\n\r Time not set, invalid input!\r");
                        }
                        gs_ul_state = STATE_MENU;
                        gs_ul_menu_shown = 0;
                        gs_ul_alarm_triggered = 0;
                        refresh_display();
                }

                /* Set date alarm */
                if (uc_key == 'm') {
                        gs_ul_state = STATE_SET_DATE_ALARM;

                        rtc_clear_time_alarm(RTC);

                        do {
                                puts("\n\r\n\r Set date alarm(mm/dd/yyyy): ");
                        } while (get_new_date());

                        if (gs_ul_new_year != 0xFFFFFFFF && (gs_uc_date[2] == '/')
                                        && (gs_uc_date[5] == '/')) {
                                if (rtc_set_date_alarm(RTC, 1, gs_ul_new_month, 1,
                                                gs_ul_new_day)) {
                                        puts("\n\r Date alarm not set, invalid input!\r");
                                } else {
                                        printf("\n\r Date alarm is set on %02u/%02u/%4u!",
                                                        (unsigned int)gs_ul_new_month, (unsigned int)gs_ul_new_day,
                                                        (unsigned int)gs_ul_new_year);
                                }
                        } else {
                                gs_uc_date[2] = '/';
                                gs_uc_date[5] = '/';
                                puts("\n\r Date alarm not set, invalid input!\r");
                        }
                        gs_ul_state = STATE_MENU;
                        gs_ul_menu_shown = 0;
                        gs_ul_alarm_triggered = 0;
                        refresh_display();
                }

#if ((SAM3S8) || (SAM3SD8) || (SAM4S) || (SAM4C) || (SAM4CP) || (SAM4CM) || (SAMV71)|| (SAMV70) || (SAME70) || (SAMS70))
                /* Generate Waveform */
                if (uc_key == 'w') {
                        gs_ul_state = STATE_WAVEFORM;
                        puts("\n\rMenu:\n\r"
                                        "  0 - No Waveform\n\r"
                                        "  1 - 1 Hz square wave\n\r"
                                        "  2 - 32 Hz square wave\n\r"
                                        "  3 - 64 Hz square wave\n\r"
                                        "  4 - 512 Hz square wave\n\r"
                                        "  5 - Toggles when alarm flag rise\n\r"
                                        "  6 - Copy of the alarm flag\n\r"
                                        "  7 - Duty cycle programmable pulse\n\r"
                                        "  8 - Quit\r");

                        while (1) {
                                scanf("%c", (char *)&uc_key);

                                if ((uc_key >= '0') && (uc_key <= '7')) {
                                        rtc_set_waveform(RTC, 0, char_to_digit(uc_key));
                                }

                                if (uc_key == '8') {
                                        gs_ul_state = STATE_MENU;
                                        gs_ul_menu_shown = 0;
                                        refresh_display();
                                        break;
                                }
                        }
                }
#endif
                /* Clear trigger flag */
                if (uc_key == 'c') {
                        gs_ul_alarm_triggered = 0;
                        gs_ul_menu_shown = 0;
                        refresh_display();
                }

        }

}

/// [url=home.php?mod=space&uid=1302964]@cond[/url] 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond


运行结果:



相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2398

主题

6945

帖子

66

粉丝