本文将讲解如何利用 hbird e203的 RTC 实现毫秒级和秒级延时,感兴趣的话继续看下去吧!
(原创教学文章,转载请注明出处!)
更多教学资源分享,可加入此群获取!
十二、RTC的使用
RTC的功能列出如下。
- HBirdv2 SoC在常开域中包含一个RTC模块。
- 可编程计数器的比较阈值,一旦RTC计数器的比较值达到比较阈值则可以产生中断
- RTC本质上是一个48位的计数器
下表列出了RTC模块5个寄存器。
注:所有的RTC寄存器都是32位的
12.1 RTC寄存器
12.1.1. RTCCFG
RTCCFG寄存器用于对 RTC 进行配置,具体各比特域的作用如下:
12.1.2. RTCHI和RTCLO
RTCHI和RTCLO 都是反映RC计数器(共48位)的值,其中RTCHI反映高16位,RTCLO反映低32位
12.1.3 RTCS
RTCS寄存器中的值是来自RTC计数器计数值(RTCHI/RTCLO寄存器)中取出的32位,而RTCCFG寄存器 rtcscale 域的值指定了RTC计数器计数值中取出32位的低位起始位置,即计数值的缩放比例。
这样说可能不好理解,举个例子:
- rtcscale = 0,则直接取出RTC计数器计数值低32位作为RTCS的值;若rtcscale = 5,则直接取出RTC计数器计数值除以2^5(32)作为RTCS的值
12.1.4 RTCCMP
该寄存器的值将作为比较阈值与RTC计数器比较值(RTCS寄存器的值)进行比较。一旦RTCS寄存器的值大于或者等于RTCCMP寄存器的值,便会产生中断。
12.2 延时函数编写
我的需求是通过RTC实现毫秒级和秒级延时(常开域为低速时钟,无法实现微妙级延时)
(1)思路: 使能RTC,使计数器从0开始计数,然后计算 1ms 和 1s 对应的计数值,当到达此计数值时才退出空循环.(具体可看代码,注释很详细)
(2)文件结构:
我的扩展包是放在SoC/hbirdv2/Common下,需要添加下头文件路径
添加头文件路径方法:
-
先在Project Explorer 栏下选中 hello_world 项目,点击鼠标右键,选择"Properties"
-
在弹出的窗口中,展开 C/C++ Build 菜单 --> Setting --> Tool Settings菜单 --> GNU RISC-v Cross Assembler
–> Includes
-
将 Include path 拉到最右边,添加新路径,我添加路径为:
${workspace_loc:/${ProjName}/hbird_sdk/SoC/hbirdv2/Common/Include_user}
注:添加头文件包含路径时发现似乎要填头文件所在的文件夹的路径,而不能填父级文件夹路径
同理添加此路径到下图所示的两个 Includes路径设置中
然后点Apply and Close 即可
(3)main中的循环:
每隔 0.5s 打印 Hello World From RISC-V Processor! ,隔 2s 打印 NucleiStudio yyds!
(4)下载测试:
详情请看测试视频(放在群文件中,可自行加群下载查看)
(5)代码文件:
- rtc.h
#include "type_user.h"
#ifndef RTC_H_
#define RTC_H_
// 寄存器偏移地址
#define AON_RTCCFG 0x040
#define AON_RTCLO 0x048
#define AON_RTCHI 0x04C
#define AON_RTCS 0x050
#define AON_RTCCMP 0x060
void rtc_init();
void rtc_off();
void rtc_delay_s(uint s); // 秒级延时
void rtc_delay_ms(uint ms); // 毫秒级延时
void rtc_timer_irq_handler();
#endif /* RTC_H_ */
- rtc.c
#include "platform.h"
#include "rtc.h"
// 延时函数需先使能 rtc 后才能使用
// 低速时钟实际频率为:32765 Hz,即周期为30.52037 us
uint rtc_freq = 32765;
rtc_init(){
AON_REG(AON_RTCCFG) = 0x1000; // 使能 rtc
}
rtc_off(){
AON_REG(AON_RTCCFG) = 0x0000; // 关闭 rtc
}
//1s,即32765.0025个周期;按32765计算,即为0.9999999235 s,误差可忽略不计
rtc_delay_s(uint s){
AON_REG(AON_RTCLO) = 0x0; // 计数值清零
rtc_init();
while(AON_REG(AON_RTCLO) <= (32765*s)){} // 延时 32765*s 周期
rtc_off();
}
// 1ms,即32.765个周期;按33个周期计算,即为1007.17us,即此函数的实际延时时间
rtc_delay_ms(uint ms){
AON_REG(AON_RTCLO) = 0x0; // 计数值清零
rtc_init();
while(AON_REG(AON_RTCLO) <= (33*ms)){} // 延时 33*ms 周期
rtc_off();
}
rtc_timer_irq_handler(){
}
- type_user.h
#ifndef TYPE_USER_H_
#define TYPE_USER_H_
typedef unsigned int uint;
#endif /* TYPE_USER_H_ */
- platform.h
#ifndef _HBIRD_PLATFORM_H
#define _HBIRD_PLATFORM_H
#include
/****************************************************************************
* Platform definitions
*****************************************************************************/
#define _AC(X,Y) (X##Y)
#define AON_CTRL_ADDR _AC(0x10000000,UL)
// Helper functions
#define _REG8(p, i) (*(volatile uint8_t *) ((p) + (i)))
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
#endif /* _HBIRD_PLATFORM_H */