参赛队名:0 ERROR 队伍编号:CICC1957
本篇主要介绍如何利用蜂鸟HbirdV2-SoC自带外设PWM进行毫秒级的延时和计时。
在上一个帖子中,介绍了HbirdV2-SoC自带外设PWM的寄存器配置,并在文末贴上了详细的源码。本次以该源码为基础,完成毫秒级的定时。
首先,利用源码中提供的函数,将TIM0配置为如下所示:
本配置中,先配置TIM0的预分频为0,以原生时钟进行计数。
其次,设置TIM0计数到阈值后,重置计数值为start
value。
选择高速主时钟作为TIM0时钟源,原生e203主时钟为16MHz,若修改过硬件源码,则应注意修改后频率。
设置TIM0在每个时钟都触发事件。并设置初始计数值为0,计数阈值为0xffff,之后使能TIM0,更新TIM0寄存器配置,重置并启动计数。
最后一步中,利用e203自带函数获取当前主时钟频率,赋值给全局变量SOC_CORE_FREQ(注:该全局变量需要自己提前声明)。
void TIM0_Init()
{
TIMNum timer = TIM_0;
TIM_set_prescaler(timer, 0);
TIM_updown_sel(timer, TIM_COUNT_UP_RST);
TIM_clk_sel(timer, TIM_CORE_CLK);
//TIM_InputSource_sel(timer, 0);
TIM_set_mode(timer, TIM_MODE_CYCLE);
TIM_set_StartValue(timer, 0);
TIM_set_EndValue(timer, 0Xffff);
//TIM_set_CHxThreshold(timer, TIM_TH_CHANNEL0, 10000);
//TIM_set_CHxMode(timer, TIM_TH_CHANNEL0, TIM_TH_TOGGLE);
//TIM_interruptSource_sel(TIM_TH_CHANNEL2, 1);
//TIM_interrput_disable(TIM_TH_CHANNEL2);
//TIM_interrput_enable(TIM_TH_CHANNEL2);
TIM_enable(timer);
//TIM_disable(TIM_0);
TIM_cmd(timer, TIM_CMD_UPDATA);
TIM_cmd(timer, TIM_CMD_RST);
TIM_cmd(timer, TIM_CMD_START);
SOC_CORE_FREQ = get_cpu_freq();
}
完成TIM0配置后,就可以设置一个微秒级的延时函数了,本例中模仿e203自带的delay_1ms()函数,实现了delay_50us()函数,该延时函数定义如下:
void delay_50us(uint32_t count)
{
uint16_t start_time, delta_time;
uint16_t delay_ticks = (uint16_t) (SOC_CORE_FREQ / 20000);
for(uint32_t i=0; i<count; i++)
{
TIM_cmd(TIM_0, TIM_CMD_RST);
TIM_cmd(TIM_0, TIM_CMD_START);
start_time = TIM_get_cnt(TIM_0);
do
{
delta_time = TIM_get_cnt(TIM_0) - start_time;
} while (delta_time < delay_ticks);
}
}
值得注意的是,e203主频仅为16MHz,也就是说,计数16次为1us。然而,在获取start_time之后运行do while语句以及获取delta_time,都要经过复数个机器周期,显然,计数16次实现1us延迟是极不精准的。为了达到一定了精度要求,本例中仅实现50us的延时。
其次,TIM0的计数寄存器仅为16位,用在16MHz主时钟对其进行计数时,最大delay仅为4.096ms,因此,改用一个for循环来实现长时间计数。
本节为了验证所设计的延时函数的性能,利用e203自带的RTC时钟来验证设计的delay_50us()函数。相关代码如下
uint32_t start_mtime, delta_mtime;
start_mtime = SysTimer_GetLoadValue();
delay_50us(200);
delta_mtime = SysTimer_GetLoadValue() - start_mtime;
printf("expected delay is 10ms, actual delay is %dns \n", (delta_mtime*30517));
该段代码输出结果如下:
可以看到,进行微秒级延迟时,精度误差比较大,约为15.04%,该微秒级延迟能在一些对时序精度要求不那么高的应用,例如OV5640摄像头配置中SCCB协议信号的延迟。
同时,若要达到更高的精度要求,可以参考e203自带delay_1ms()函数设计,但是延时时间不宜超过4ms。其次,可以增大延迟步长为100us或200us,以减小微秒级延迟函数误差。