xiyue521 发表于 2021-5-1 15:17

【中科蓝讯AB32VG1 RISC-V板“碰上”RTT测评】软件定时器+硬件定时器

本帖最后由 xiyue521 于 2021-5-7 14:06 编辑

<p><span style="font-size:24px;">概述:</span></p>

<p><span style="font-size:24px;">1)硬件定时器是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。</span></p>

<p><span style="font-size:24px;">2)软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。</span></p>

<p><span style="font-size:24px;">RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时数值必须是 OS Tick 的整数倍,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。</span></p>

<p><span style="font-size:24px;">1.先来看看软件定时器的使用:</span></p>

<p><span style="font-size:24px;">软件定时器其实可以看做是一个特殊的任务,对比一下线程和定时器的创建就知道了,很相似,就是软件定时器功能只有定时。</span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">rt_timer_create 与rt_thread_create</span></p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">rt_timer_start 与rt_thread_startup</span></p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">定时器创建:</span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"><span style="font-size:24px;"></span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">线程创建:</span></p>

<p class="imagemiddle" style="text-align: center;"><span style="font-size:24px;"></span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">rt_timer_t rt_timer_create(const char *name,</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void (*timeout)(void *parameter),</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*parameter,</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rt_tick_t &nbsp;&nbsp;time,</span></p>

<p><span style="font-size:24px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rt_uint8_t &nbsp;flag)</span></p>

<p><span style="font-size:24px;">主要就是void (*timeout)(void *parameter),和time这两个参数,一个是定时器回调函数指针,一个是定时的时间,单位和时间片有关,就是他的整数倍了。</span></p>

<p><span style="font-size:24px;">软件定时器使用比较简单类比下线程创建即可。</span></p>

<p><span style="font-size:24px;">代码:</span></p>

<div aria-label="代码段 小部件" contenteditable="false" role="region" tabindex="-1">
<pre data-widget="codesnippet">
<code class="hljs">
static void Led_TimerCallback(void *parameter){
    RGB_Blue(~flag);
    flag = ~flag;
}

int Timer_Start(void){
    RGB_Init();
   rt_timer_t timer= rt_timer_create(&quot;soft_timer&quot;,
                                          Led_TimerCallback,
                                          RT_NULL,
                                          1000,
                                          RT_TIMER_FLAG_PERIODIC
                                        );//创建一个1s周期定时器

    rt_timer_start(timer);
    return 0;
}
INIT_APP_EXPORT(Timer_Start);
</code></pre>
<img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" /><span style="background: url(&quot;https://bbs.eeworld.com.cn/static/editor/plugins/widget/images/handle.png&quot;) rgba(220, 220, 220, 0.5); top: -15px; left: 0px; display: block;"><img height="15" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" /></span></div>

<p><span style="font-size:24px;">2.再来看看硬件定时器,这个就比较麻烦了,要先在RTThread setings使能timer1,然后保存下,</span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"><span style="font-size:24px;"></span></p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p><span style="font-size:24px;">&nbsp; &nbsp; 先查找设备:&nbsp;<br />
&nbsp; &nbsp; hw_timer = rt_device_find(&quot;timer1&quot;);</span></p>

<p><span style="font-size:24px;">&nbsp; &nbsp; &nbsp;以读写的方式打开设备 :<br />
&nbsp; &nbsp; rt_device_open(hw_timer, RT_DEVICE_OFLAG_RDWR);</span></p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">&nbsp; &nbsp; &nbsp;设置定时器工作模式为周期定时 :<br />
&nbsp; &nbsp; timer_mode = HWTIMER_MODE_PERIOD;<br />
&nbsp; &nbsp; rt_device_control(hw_timer, HWTIMER_CTRL_MODE_SET, &amp;timer_mode);</span></p>

<p><span style="font-size:24px;">有以下几个参数:用HWTIMER_CTRL_MODE_SET</span></p>

<p><span style="font-size:24px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">&nbsp; &nbsp; /超值回调函数 :<br />
&nbsp; &nbsp; rt_device_set_rx_indicate(hw_timer, timeout_cb);</span></p>

<p>&nbsp;</p>

<p><span style="font-size:24px;">&nbsp; &nbsp; /配置超时值 :<br />
&nbsp; &nbsp; timeout_t.sec = 5;<br />
&nbsp; &nbsp; timeout_t.usec = 0;<br />
&nbsp; &nbsp; rt_device_write(hw_timer, 0, &amp;timeout_t, sizeof(timeout_t));</span></p>

<p><span style="font-size:24px;"></span></p>

<p><span style="font-size:24px;">其中可以设置秒和ms</span></p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle"><span style="font-size:24px;">现象:</span></p>

<p class="imagemiddle" style="text-align: center;"><span style="font-size:24px;"></span></p>

<p class="imagemiddle"><span style="font-size: 24px;">代码:</span></p>

<pre>
<code>
/* 定时器超时回调函数 */
rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
    rt_kprintf("hwtimer timeout callback fucntion!\n");
    return 0;
}

int hw_sample(void)
{
    rt_err_t ret = RT_EOK;
    /* 查找设备 */
    hw_timer = rt_device_find("timer1");
    if(hw_timer == RT_NULL)
    {
      rt_kprintf("find %s failed\t\n", "time1");
      return RT_ERROR;
    }
    /* 查找设备成功 */
    rt_kprintf("find %s success \t\n","");

    /* 以读写的方式打开设备 */
    rt_device_open(hw_timer, RT_DEVICE_OFLAG_RDWR);

    /* 设置定时器工作模式为周期定时 */
    timer_mode = HWTIMER_MODE_PERIOD;
    rt_device_control(hw_timer, HWTIMER_CTRL_MODE_SET, &amp;timer_mode);

    /* 超值回调函数 */
    rt_device_set_rx_indicate(hw_timer, timeout_cb);

    /* 配置超时值 */
    timeout_t.sec = 5;
    timeout_t.usec = 0;
    rt_device_write(hw_timer, 0, &amp;timeout_t, sizeof(timeout_t));

    return RT_EOK;
}
INIT_APP_EXPORT(hw_sample);
</code></pre>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>


补充内容 (2021-5-9 00:20):
2.先来看看本芯片AB322VG1的硬件定时器外设资源:一种是基本定时器,仅支持32位定时器功能,分别为定时器0/1/2;另一种是带有高级功能的定时器,其支持定时器模式、计数器模式、捕获模式以及PWM模式,为定时器3/4/...

xiyue521 发表于 2021-5-9 00:21

<p style="text-align:justify">本芯片AB322VG1的硬件定时器外设资源:一种是基本定时器,仅支持32位定时器功能,分别为定时器0/1/2;另一种是带有高级功能的定时器,其支持定时器模式、计数器模式、捕获模式以及PWM模式,为定时器3/4/5。</p>

<p style="text-align:justify"></p>

<p style="text-align:justify">本次主要使用了TIMER1,设计到的寄存器有:</p>

<p style="text-align:justify">TIMER1CON: 定时器1控制寄存器;</p>

<p style="text-align:justify">TIMER1CPND:定时器1清除挂起寄存器;</p>

<p style="text-align:justify">TIMER1CNT: 定时器1计数器寄存器;</p>

<p style="text-align:justify">TIMER1PR:定时器1周期寄存器</p>

火辣西米秀 发表于 2021-5-23 09:26

<p>硬件定时器是先查找设备,在RTThread setings使能timer1,再保存,步骤有点多</p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【中科蓝讯AB32VG1 RISC-V板“碰上”RTT测评】软件定时器+硬件定时器