之前咱们运用空循环,达到了推迟的意图,可是这姿态的推迟比较不准确。现在就运用实时定时器(RTT)来进行更为准确的计时。RTT尽管不是特别通用,在某些单片机上或许没有,但它较为简略。
RTT内部有一个计数器,而且能够装备这个计数器的时钟。经过装备以及核算,就能够得出经过一段时间后,该计数器的添加值。和之前相同,咱们运用空循环来完结推迟,仅仅推迟退出的条件变为“计数器添加了一个特定的值”。
一、 RTT装备
为完成这个功用,需求装备的首要便是分频数了。RTT的时钟能够挑选对慢时钟(SCLK,32.768 kHz)分频,或直接运用1 Hz的RTC时钟。为使LED能进行较为快速的闪耀,在这里就不能运用1 Hz的时钟了。RTT_MR的低十六位表明分频数,其他位运用复位值就能够了:
#define PRESCALE (1u<<10)
RTT->RTT_MR = RTT_MR_RTPRES(PRESCALE);
二、 读取RTT计数器值
经过直接读取RTT_VR就能够得到这个值了。需求留意的时,这个值或许会被主时钟异步地更新,所以能够接连读取两次该值以添加准确性:
uint32_t ReadRTT_CRTV(void)
{
uint32_t v1;
uint32_t v2;
while(1)
{
v1 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
v2 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
/* 经过接连读取两次RTT_VR的值以添加预备性 */
if (v1 == v2)
{
return v1;
}
}
}
三、 更为准确的延时
推迟开始时,读取一次RTT计数器的值,再核算出推迟结束时计数器的值,接下来的作业就等候计数器更新到这个值了。
现在能够把之前完成Delay函数进行修改了:
void Delay(unsigned int ms)
{
uint32_t begin_rttv = ReadRTT_CRTV();
/* 计数器加一的频率 */
const uint32_t freq = CHIP_FREQ_SLCK_RC / PRESCALE; /* CHIP_FREQ_SLCK_RC 在CMSIS有界说,表明SLCK的频率 */
/* 核算推迟后,计数器需求添加的值
need_inc = ms /1000 / (1/freq) */
uint32_t need_inc = ms * freq / 1000;
uint32_t end_rttv = begin_rttv + need_inc;
/* 等候*/
while(ReadRTT_CRTV() < end_rttv)
;
}