第四篇 定时器和PWM的使用
<div class="parsedown-markdown"><p>前面提到RVB2601使用的YOC平台,对外设功能进行了封装。这样用起来会更简单,不用去关心底层的知识。但是缺点也很明显,那就是函数的注释写的不好的话,有些函数就不会使用了。</p>
<p>这次使用了其TIMER 和 PWM两个模块。使用模块时,需要添加对应的头文件,<code>#include <drv/xxx.h></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(&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(&led_red,PA7);
csi_gpio_pin_dir(&led_red, GPIO_DIRECTION_OUTPUT);
//设置定时器
csi_timer_init(&l_timer,1);
csi_timer_attach_callback(&l_timer,toggle_red_led,NULL);
csi_timer_start(&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 >= 30){
i++;
}
}else{
width--;
if(width == 0){
i++;
}
}
//改变PWM的比较值
csi_pwm_out_config(&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(&blue_led_pwm, 0);
csi_pwm_out_config(&blue_led_pwm, 4/2, 30, width, PWM_POLARITY_LOW);
csi_pwm_out_start(&blue_led_pwm, 4/2);
//启动一个定时器,定时的更新pwm的比较值,实现呼吸灯的效果
csi_timer_init(&l_timer,1);
csi_timer_attach_callback(&l_timer,toggle_led,NULL);
csi_timer_start(&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> </p>
拍这图片,很有创意哦! 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" /> 旁边有个绿灯太亮了,就遮了一下</p>
<p>呼吸灯,我也会做!</p>
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]