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,//< 1..12, 1 is January.day = 04,//< 1..28,29,30,31 depending on month.dotw = 3, // 0 is Sunday, so 5 is Friday.hour = 23,//< 0..23.min = 30,//< 0..59.sec = 00};//< 0..59
- 🌿
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_RTCpico_stdlibhardware_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:00datetime_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 RTCrtc_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 timewhile (true) {rtc_get_datetime(&t);datetime_to_str(datetime_str, sizeof(datetime_buf), &t);printf("\r%s ", datetime_str);sleep_ms(100);}
}
- 📗RTC报警中断使用例程:
每分钟的固定秒数,产生一次报警中断,一次配置重复触发。
- 🥕参考:
https://github.com/khoih-prog/RP2040_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"#define GPIO 25#define BUILTIN_LED PICO_DEFAULT_LED_PIN#define ALARM_AT_SECONDS 5
#define ALARM_REPEAT_FOREVER truevolatile bool alarmTriggered = false;
bool setAlarmDone = false;
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};datetime_t alarmT;//// 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 minutealarmT.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_FOREVERsetAlarmRepeat(ALARM_AT_SECONDS);
#elsesetAlarmOnce(ALARM_AT_SECONDS);
#endifsetAlarmDone = 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); // 324usuint 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 RTCrtc_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 defaultgpio_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 LEDif (alarmTriggered){alarmTriggered = false;printf("clk_sys = %dkHz,clk_rtc = %dkHz,rtc_status:%d\n", f_clk_sys, rtc_running());//57/30printf("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 truevolatile 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 minutealarmT.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_FOREVERsetAlarmRepeat(ALARM_AT_SECONDS);
#elsesetAlarmOnce(ALARM_AT_SECONDS);
#endifsetAlarmDone = 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); // 324usuint 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 RTCrtc_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 defaultgpio_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);
- 🌿如果只配置触发一次:
datetime_t alarm = {.year = 2024,.month = 0x09,.day = 04,.dotw = 3, // 0 is Sunday, so 5 is Friday.hour = 23,.min = 30,.sec = 00};rtc_set_alarm(&alarm, &alarm_callback);