manhuami2007 发表于 2022-4-26 16:57

第四篇 定时器和PWM的使用

<div class="parsedown-markdown">
<p>前面提到RVB2601使用的YOC平台,对外设功能进行了封装。这样用起来会更简单,不用去关心底层的知识。但是缺点也很明显,那就是函数的注释写的不好的话,有些函数就不会使用了。</p>

<p>这次使用了其TIMER 和 PWM两个模块。使用模块时,需要添加对应的头文件,<code>#include &lt;drv/xxx.h&gt;</code> 。然后使用不同的外设要建立不同外设的句柄。</p>

<h3>一、定时器的使用</h3>

<ol>
        <li>建立TIMER的句柄,其格式为<code>csi_timer_t</code>。句柄是一个全局变量,用于保存外设的信息。</li>
        <li>调用初始化函数<code>csi_error_t csi_timer_init(csi_timer_t *timer, uint32_t idx)</code>,第二个参数idx为设备ID,在使用的时候发现需要从1开始,idx=0应该是被占用了。</li>
        <li>创建回调函数,回调函数的格式为<code>void (*callback)(csi_timer_t *timer, void *arg)</code>;</li>
        <li>注册回调函数<code>csi_error_t csi_timer_attach_callback(csi_timer_t *timer, void *callback, void *arg)</code>;</li>
        <li>启动定时器<code>csi_error_t csi_timer_start(csi_timer_t *timer, uint32_t timeout_us)</code>,第二个参数为周期值,单位为us。而且是周期性的启动。</li>
</ol>

<p>比如使用定时器实现LED闪烁的例程如下:</p>

<pre>
<code class="language-cpp">//创建用到的句柄
csi_gpio_pin_t led_red;
csi_timer_t l_timer;

//定时器的回调函数
void toggle_red_led(csi_timer_t *timer_handle, void *arg)
{
        csi_gpio_pin_toggle(&amp;led_red);
}

int main(void)
{
    board_yoc_init();
    LOGD(TAG, "%s\n", aos_get_app_version());
    oled_init();
    //设置LED使用的引脚
        csi_pin_set_mux(PA7,PIN_FUNC_GPIO);
        csi_gpio_pin_init(&amp;led_red,PA7);
        csi_gpio_pin_dir(&amp;led_red, GPIO_DIRECTION_OUTPUT);
        //设置定时器
        csi_timer_init(&amp;l_timer,1);
        csi_timer_attach_callback(&amp;l_timer,toggle_red_led,NULL);
        csi_timer_start(&amp;l_timer,500000);
    while (1) {
      LOGD(TAG, "Hello world! YoC");
      aos_msleep(1000);
    }

    return 0;
}</code></pre>

<h3>二、PWM的使用</h3>

<p>PWM模式实现了PWM的输出与捕获功能。支持主要使用的输出功能。PWM的输出是没有回调函数的,而输入捕获有回调函数。</p>

<p>使用PWM输出功能的步骤:</p>

<ol>
        <li>设置引脚为PWM模式</li>
        <li>初始化PWM</li>
        <li>配置PWM的输出功能</li>
        <li>启动PWM的输出</li>
</ol>

<p>这次实现一个呼吸灯的效果,因为输出功能没有回调函数,所以使用上面的TIMER去更新PWM的比较值。</p>

<pre>
<code class="language-cpp">csi_timer_t l_timer;
csi_pwm_t blue_led_pwm;
//回调函数
void toggle_led(csi_timer_t *timer_handle, void *arg)
{
        static uint32_t i;
        if(i%2 == 0){
                width++;
                if(width &gt;= 30){
                        i++;
                }
        }else{
                width--;
                if(width == 0){
                        i++;
                }
        }
    //改变PWM的比较值       
        csi_pwm_out_config(&amp;blue_led_pwm, 2, 30, width, PWM_POLARITY_HIGH);
}


int main(void)
{
    board_yoc_init();
    LOGD(TAG, "%s\n", aos_get_app_version());
    oled_init();
       
    //设置IO为PWM功能
        csi_pin_set_mux(PA4,PA4_PWM_CH4);

        csi_pwm_init(&amp;blue_led_pwm, 0);
        csi_pwm_out_config(&amp;blue_led_pwm, 4/2, 30, width, PWM_POLARITY_LOW);
        csi_pwm_out_start(&amp;blue_led_pwm, 4/2);
       
    //启动一个定时器,定时的更新pwm的比较值,实现呼吸灯的效果
        csi_timer_init(&amp;l_timer,1);
        csi_timer_attach_callback(&amp;l_timer,toggle_led,NULL);
        csi_timer_start(&amp;l_timer,80000);
    while (1) {
      LOGD(TAG, "Hello world! YoC");
      aos_msleep(1000);
    }

    return 0;
}</code></pre>

<p><img alt="" src="1650962467124%20(1).gif" target="_blank" /></p>

<p><strong>注意</strong> :在函数<code>csi_pwm_out_config()</code>和<code>csi_pwm_out_start()</code>中,第二个参数为通道号,但是通道号的使用要注意,为引脚通道号整除2。为什么这样呢?参考其数据手册和源代码(见下图),CH2601的PWM共有6组,每组有2个通道,这两个通道共用1个计数器。可能是因为这个原因,官方在写驱动函数的时候使用了简单处理方法,让两个通道使用相同的设置值,因此在设置的时候,通道号需要整除2。</p>

<p><img alt="" src="2022-04-26-16-48-15.png" target="_blank" /></p>

<p></p>

<p><img alt="" src="2022-04-26-16-50-34.png" target="_blank" /></p>
</div>

<p>&nbsp;</p>

lugl4313820 发表于 2022-4-26 23:19

拍这图片,很有创意哦!

manhuami2007 发表于 2022-4-27 08:33

lugl4313820 发表于 2022-4-26 23:19
拍这图片,很有创意哦!

<p><img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/grinning-face-with-smiling-eyes_1f601.png" width="28" />&nbsp;旁边有个绿灯太亮了,就遮了一下</p>

freebsder 发表于 2022-4-27 22:39

<p>呼吸灯,我也会做!</p>

manhuami2007 发表于 2022-4-28 16:06

freebsder 发表于 2022-4-27 22:39
呼吸灯,我也会做!

<p><img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/grinning-face-with-smiling-eyes_1f601.png" width="28" /></p>
页: [1]
查看完整版本: 第四篇 定时器和PWM的使用