RP2040 C SDK RTC功能使用
- 📍《RP2040 C SDK串口功能使用》
- 🥕RP2040 RTC API官方文档说明:
https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_rtc
- 🥕官方例程参考:
https://github.com/raspberrypi/pico-examples
📑RTC 相关API接口函数介绍
- 🌿
void rtc_init (void)
:初始化rtc。 - 🌿
bool rtc_set_datetime (const datetime_t *t)
:设置rtc
- 形参1:
datetime_t t = {
.year = 2024,
.month = 9,//注意这里不能写09,编译会报错,可以用16进制:0x09
.day = 04,
.dotw = 3, // 0 is Sunday, so 5 is Friday
.hour = 23,
.min = 30,
.sec = 00};
- 🌿
bool rtc_get_datetime (datetime_t *t)
:获取时间。
- 形参1:参考上面的。
- 🌿
bool rtc_running (void)
:查询rtc运行状态。 - 🌿
void rtc_set_alarm (const datetime_t *t, rtc_callback_t user_callback)
:设置报警中断
- 形参1:时间句柄。
- 形参2:回调函数。
- 🌿
void rtc_enable_alarm (void)
:使能rtc报警。 - 🌿
void rtc_disable_alarm (void)
:失能rtc报警
✨使用rtc功能外设,需要在CMakeLists.txt
文件中,添加hardware_rtc
配置
# Add the standard library to the build
target_link_libraries(RP2040_RTC
pico_stdlib
hardware_rtc)
📙例程
- 📘hello_rtc官方给出的使用例程:
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "hardware/rtc.h"
#include "pico/stdlib.h"
#include "pico/util/datetime.h"
/// \tag::hello_rtc_main[]
int main() {
stdio_init_all();
printf("Hello RTC!\n");
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
// Start on Friday 5th of June 2020 15:45:00
datetime_t t = {
.year = 2020,
.month = 06,
.day = 05,
.dotw = 5, // 0 is Sunday, so 5 is Friday
.hour = 15,
.min = 45,
.sec = 00
};
// Start the RTC
rtc_init();
rtc_set_datetime(&t);
// clk_sys is >2000x faster than clk_rtc, so datetime is not updated immediately when rtc_get_datetime() is called.
// tbe delay is up to 3 RTC clock cycles (which is 64us with the default clock settings)
sleep_us(64);
// Print the time
while (true) {
rtc_get_datetime(&t);
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("\r%s ", datetime_str);
sleep_ms(100);
}
}
- 📗RTC报警中断使用例程:
每分钟的固定秒数,产生一次报警中断,一次配置重复触发。
/*
CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"-c "program debugprobe.elf verify reset exit"
jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg -c "adapter speed 2000" -c "program RP2040_RTC.elf verify reset exit"
*/
#include <stdio.h>
#include "pico/stdlib.h"
// #include "hardware/uart.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"
#include "hardware/clocks.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
// GPIO defines
// Example uses GPIO 2
#define GPIO 25
#define BUILTIN_LED PICO_DEFAULT_LED_PIN
#define ALARM_AT_SECONDS 5
#define ALARM_REPEAT_FOREVER true
volatile bool alarmTriggered = false;
bool setAlarmDone = false;
datetime_t t = {
.year = 2024,
.month = 9,
.day = 04,
.dotw = 3, // 0 is Sunday, so 5 is Friday
.hour = 23,
.min = 30,
.sec = 00};
datetime_t alarmT;
static volatile bool fired = false;
//
// This is ISR. Be careful. No Serial.print here.
void rtcCallback(void)
{
alarmTriggered = true;
}
void set_RTC_Alarm(datetime_t *alarmTime)
{
rtc_set_alarm(alarmTime, rtcCallback);
}
void setAlarmOnce(uint8_t alarmSeconds)
{
rtc_get_datetime(&alarmT);
if (alarmSeconds > alarmT.sec)
alarmT.sec = alarmSeconds;
else
{
// Alarm in next minute
alarmT.sec = alarmSeconds;
alarmT.min += 1;
}
set_RTC_Alarm(&alarmT);
printf("Set One-time Alarm @ alarmSeconds = %d\n", alarmSeconds);
}
void setAlarmRepeat(uint8_t alarmSeconds)
{
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;
set_RTC_Alarm(&alarmT);
// irq_set_enabled(RTC_IRQ, true);
printf("Set Repeatitive Alarm @ alarmSeconds = %d\n", alarmT.sec);
}
void setAlarm()
{
#if ALARM_REPEAT_FOREVER
setAlarmRepeat(ALARM_AT_SECONDS);
#else
setAlarmOnce(ALARM_AT_SECONDS);
#endif
setAlarmDone = true;
}
static void alarm_callback(void)
{
alarmTriggered = true;
// datetime_t t = {0};
rtc_get_datetime(&t);
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("Alarm Fired At %s\n", datetime_str);
stdio_flush();
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;
}
int main()
{
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
stdio_init_all();
set_sys_clock_khz(133000, true); // 324us
uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);
uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
printf("clk_rtc = %dkHz\n", f_clk_rtc);
printf("clk_sys = %dkHz\n", f_clk_sys);
// Set up our UART
// uart_init(UART_ID, BAUD_RATE);
// Set the TX and RX pins by using the function select on the GPIO
// Set datasheet for more information on function select
// gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
// gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
printf("Hello RTC!\n");
// Start the RTC
rtc_init();
rtc_set_datetime(&t);
bool rtc_status = rtc_running(); //
printf("RTC is running = %d\n", rtc_status);
// rtc_set_alarm (&alarm, &alarm_callback); // Set an alarm for 5 second from now
// irq_set_enabled(RTC_IRQ, true);
// irq_set_priority (RTC_IRQ, 1); //设置中断优先级
sleep_us(64);
// GPIO initialisation.
// We will make this GPIO an input, and pull it up by default
gpio_init(BUILTIN_LED);
gpio_set_dir(BUILTIN_LED, 1);
gpio_pull_up(BUILTIN_LED);
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
// if (!setAlarmDone)
// {
// setAlarm();
// printf("Set Repeatitive Alarm @ alarmSeconds = %d\n",alarmT.sec );
// }
alarmT.sec = 6;//每1分钟的第6秒报警一次,相对于1分报警一次。
set_RTC_Alarm(&alarmT);
while (true)
{
rtc_get_datetime(&t);
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("\r%s \n", datetime_str);
stdio_flush();
sleep_ms(1000);
gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED
if (alarmTriggered)
{
alarmTriggered = false;
printf("clk_sys = %dkHz,clk_rtc = %dkHz,rtc_status:%d\n", f_clk_sys, rtc_running());//57/30
printf("Set Repeatitive Alarm @ alarmSeconds = %d\n", alarmT.sec);
}
}
return 0;
}
- 📗RTC报警中断间隔秒数重复例程:
运行到固定的秒数,产生一次报警中断,如下重复固定秒数,还需要在报警中断后,再次配置一次,下一个间隔时间触发一次。中断后如果不进行配置,则变成每分钟固定秒数触发。
/*
CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"-c "program debugprobe.elf verify reset exit"
jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg -c "adapter speed 2000" -c "program RP2040_RTC.elf verify reset exit"
*/
#include <stdio.h>
#include "pico/stdlib.h"
// #include "hardware/uart.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"
#include "hardware/clocks.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
// GPIO defines
// Example uses GPIO 2
#define GPIO 25
#define BUILTIN_LED PICO_DEFAULT_LED_PIN
#define ALARM_AT_SECONDS 5
#define ALARM_REPEAT_FOREVER true
volatile bool alarmTriggered = false;
bool setAlarmDone = false;
datetime_t t = {
.year = 2024,
.month = 9,
.day = 04,
.dotw = 3, // 0 is Sunday, so 5 is Friday
.hour = 23,
.min = 30,
.sec = 00};
datetime_t alarmT;
static volatile bool fired = false;
//
// This is ISR. Be careful. No Serial.print here.
void rtcCallback(void)
{
alarmTriggered = true;
}
void set_RTC_Alarm(datetime_t *alarmTime)
{
rtc_set_alarm(alarmTime, rtcCallback);
}
void setAlarmOnce(uint8_t alarmSeconds)
{
rtc_get_datetime(&alarmT);
if (alarmSeconds > alarmT.sec)
alarmT.sec = alarmSeconds;
else
{
// Alarm in next minute
alarmT.sec = alarmSeconds;
alarmT.min += 1;
}
set_RTC_Alarm(&alarmT);
printf("Set One-time Alarm @ alarmSeconds = %d\n", alarmSeconds);
}
void setAlarmRepeat(uint8_t alarmSeconds)
{
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;
set_RTC_Alarm(&alarmT);
// irq_set_enabled(RTC_IRQ, true);
printf("Set Repeatitive Alarm @ alarmSeconds = %d\n", alarmT.sec);
}
void setAlarm()
{
#if ALARM_REPEAT_FOREVER
setAlarmRepeat(ALARM_AT_SECONDS);
#else
setAlarmOnce(ALARM_AT_SECONDS);
#endif
setAlarmDone = true;
}
static void alarm_callback(void)
{
alarmTriggered = true;
// datetime_t t = {0};
rtc_get_datetime(&t);
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("Alarm Fired At %s\n", datetime_str);
stdio_flush();
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;
}
int main()
{
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];
stdio_init_all();
set_sys_clock_khz(133000, true); // 324us
uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);
uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
printf("clk_rtc = %dkHz\n", f_clk_rtc);
printf("clk_sys = %dkHz\n", f_clk_sys);
// Set up our UART
// uart_init(UART_ID, BAUD_RATE);
// Set the TX and RX pins by using the function select on the GPIO
// Set datasheet for more information on function select
// gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
// gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
printf("Hello RTC!\n");
// char datetime_buf[256];
// char *datetime_str = &datetime_buf[0];
// Start on Friday 5th of June 2020 15:45:00
// Start the RTC
rtc_init();
rtc_set_datetime(&t);
bool rtc_status = rtc_running(); //
printf("RTC is running = %d\n", rtc_status);
// rtc_set_alarm (&alarm, &alarm_callback); // Set an alarm for 5 second from now
// irq_set_enabled(RTC_IRQ, true);
// irq_set_priority (RTC_IRQ, 1); //设置中断优先级
// clk_sys is >2000x faster than clk_rtc, so datetime is not updated immediately when rtc_get_datetime() is called.
// tbe delay is up to 3 RTC clock cycles (which is 64us with the default clock settings)
sleep_us(64);
// GPIO initialisation.
// We will make this GPIO an input, and pull it up by default
gpio_init(BUILTIN_LED);
gpio_set_dir(BUILTIN_LED, 1);
gpio_pull_up(BUILTIN_LED);
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;//每间隔5秒钟报警一次
//alarmT.sec = 6;//每1分钟第6秒报警一次
set_RTC_Alarm(&alarmT);
//setAlarm();
//rtc_set_alarm(&alarmT, &alarm_callback);
while (true)
{
rtc_get_datetime(&t);
datetime_to_str(datetime_str, sizeof(datetime_buf), &t);
printf("\r%s \n", datetime_str);
stdio_flush();
sleep_ms(1000);
gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED
// if (!setAlarmDone)
// {
// setAlarm();
// printf("Set Repeatitive Alarm @ alarmSeconds = %d\n",alarmT.sec );
// }
if (alarmTriggered)
{
alarmTriggered = false;
printf("clk_sys = %dkHz,clk_rtc = %dkHz,rtc_status:%d\n", f_clk_sys, rtc_running());
// rtc_set_alarm(&alarmT, &alarm_callback);
setAlarm();//配置下一次报警时间
// printf("Set Repeatitive Alarm @ alarmSeconds = %d\n", alarmT.sec);
}
}
return 0;
}
🔰两者代码配置区别:
- 🌿每分钟重复触发:
rtc_get_datetime(&alarmT);
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = alarmSeconds;
set_RTC_Alarm(&alarmT);
- 🌿间隔秒数重复触发:
alarmT.min = alarmT.hour = alarmT.day = alarmT.dotw = alarmT.month = alarmT.year = -1;
alarmT.sec = (t.sec + ALARM_AT_SECONDS)%60;//每间隔5秒钟报警一次
set_RTC_Alarm(&alarmT);