(1)实验平台:
普中 51-Ai8051 开发板
https://item.taobao.com/item.htm?abbucket=17&id=1026052331067(2)资料下载 :普中科技-各型号产品资料下载链接
AI8051U 芯片内部集成了硬件实时时钟(RTC) 模块, 这是一个用于精确计时和日历功能的重要外设。 能提供年、 月、 日、 时、 分、 秒的完整时间信息, 并支持闰年自动调整。 本章使用 RTC 制作一个电子时钟。 本章分为如下几部分内容:
[24.1 实验介绍](#24.1 实验介绍)
[24.1.1 实验简介](#24.1.1 实验简介)
[24.1.2 实验目的](#24.1.2 实验目的)
[24.2 硬件设计](#24.2 硬件设计)
[24.3 软件设计](#24.3 软件设计)
[24.3.1 创建和配置工程](#24.3.1 创建和配置工程)
[24.3.1.1 GPIO 配置](#24.3.1.1 GPIO 配置)
[24.3.1.2 配置 RTC](#24.3.1.2 配置 RTC)
[24.3.1.3 生成工程](#24.3.1.3 生成工程)
[24.3.2 添加用户驱动代码](#24.3.2 添加用户驱动代码)
[24.3.2.1 rtc.c 文件](#24.3.2.1 rtc.c 文件)
[24.3.2.2 main.c 文件](#24.3.2.2 main.c 文件)
[24.4 实验现象](#24.4 实验现象)
24.1 实验介绍
24.1.1 实验简介
Ai8051U 系列部分单片机内部集成一个实时时钟控制电路, 主要有如下特性:
**●**低功耗:RTC 模块工作电流低至 2uA@VCC=3.3V、 3uA@VCC=5.0V(典型值)
**●**长时间跨度:支持 2000 年~2099 年, 并自动判断闰年
**●**闹钟:支持一组闹钟设置
**●**支持多个中断:
**☛**一组闹钟中断(每天中断一次, 中断的时间点为闹钟寄存器所设置的任意时/分/秒)
**☛**日中断(每天中断一次, 中断的时间点为每天的 0 时О 分 0 秒)
**☛**小时中断(每小时中断一次, 中断的时间点为分/秒均为 0, 即整点时)
**☛**分钟中断(每分钟中断一次, 中断的时间点为秒为 0, 即分钟寄存器发生变化时)
**☛**秒中断(每秒中断一次, 中断的时间点为秒寄存器发生变化时>
**☛**1/2 秒中断(每 1/2 秒中断一次>
**☛**1/8 秒中断(每 1/8 秒中断一次) 1/32 秒中断(每 1/32 秒中断一次)
**●**支持掉电唤醒
**●**特别注意:Ai8051U 系列单片机的 RTC 无星期功能
24.1.2 实验目的
数码管显示 RTC 时间, 格式为 XX-XX-XX。
24.2 硬件设计
本实验使用到硬件资源如下:
(1) GPIO
(2) 数码管模块
(3) RTC
相关电路在前面章节已经介绍过, 此处省略。
24.3 软件设计
24.3.1 创建和配置工程
按照前面章节内容创建一份新工程, 并命名为 21-rtc, 如下图所示:

24.3.1.1 GPIO 配置
使能端口和时钟, 数码管端口配置可参考前面章节, 将 P14 管脚配置为 ADC4功能, 且设置为高阻输入、 关闭数字信号输入等。 如下图所示:


24.3.1.2 配置 RTC
在 RTC 配置中, 时钟源选择外部 32.768K 晶振, 初始化 RTC 时间(自行设置),使能闹钟功能和设置闹钟时间及开启中断, 使能秒中断等。 如下图所示:

24.3.1.3 生成工程
配置完成后, 按下代码生成按钮, 自动创建工程, 系统开始生成初始化代码。生成工程文件目录如下图所示:

在工程文件夹内新建一个 APP 文件夹, 用于存储用户编写的外设驱动, 方便后期工程管理和程序移植。 在 APP 文件夹下将数码管驱动复制进来即可。

然后在导出的工程中添加 APP 组, 并将 smg.c 导入到工程组内, 最后添加头文件路径, 否则编译将报错。 如下:


24.3.2 添加用户驱动代码
24.3.2.1 rtc.c 文件
cpp
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
u8 time_buf[6];
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// RTC中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void RTC_ISR(void) interrupt RTC_VECTOR
{
//<<AICUBE_USER_RTC_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (RTC_CheckAlarmFlag()) //判断是否是RTC闹钟中断
{
RTC_ClearAlarmFlag(); //清除中断请求标志位
}
if (RTC_CheckSecondFlag()) //判断是否是RTC秒中断
{
RTC_ClearSecondFlag(); //清除中断请求标志位
time_buf[0]=RTC_ReadYear();
time_buf[1]=RTC_ReadMonth();
time_buf[2]=RTC_ReadDay();
time_buf[3]=RTC_ReadHour();
time_buf[4]=RTC_ReadMinute();
time_buf[5]=RTC_ReadSecond();
}
//<<AICUBE_USER_RTC_ISR_CODE1_END>>
}
在秒中断中将获取到的年月日时分秒数据存储在数组内。
24.3.2.2 main.c 文件
cpp
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
/* 深圳市普中科技有限公司(PRECHIN 普中)
* 在线视频:https://space.bilibili.com/2146492485/video
官网:www.prechin.cn
* 实验名称:RTC实时时钟实验
*
* 接线说明:参考电路图
*
* 实验现象:程序下载成功后,数码管显示时间
*
* 注意事项:
*
*/
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "smg.h"
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
extern u8 time_buf[6];
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
u8 buf[8];
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
buf[0]=gsmg_code[time_buf[3]/10];
buf[1]=gsmg_code[time_buf[3]%10];
buf[2]=0x40;
buf[3]=gsmg_code[time_buf[4]/10];
buf[4]=gsmg_code[time_buf[4]%10];
buf[5]=0x40;
buf[6]=gsmg_code[time_buf[5]/10];
buf[7]=gsmg_code[time_buf[5]%10];
SMG_Display(buf,1);
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
主函数相对比较简单, 初始化相关外设, 在循环体内将获取的时间数据通过数码管显示。
24.4 实验现象
将程序编译下载到目标板运行, 实验现象: 数码管上显示 RTC 时间。
