前面提到RVB2601使用的YOC平台,对外设功能进行了封装。这样用起来会更简单,不用去关心底层的知识。但是缺点也很明显,那就是函数的注释写的不好的话,有些函数就不会使用了。
这次使用了其TIMER 和 PWM两个模块。使用模块时,需要添加对应的头文件,#include <drv/xxx.h>
。然后使用不同的外设要建立不同外设的句柄。
一、定时器的使用
- 建立TIMER的句柄,其格式为
csi_timer_t
。句柄是一个全局变量,用于保存外设的信息。
- 调用初始化函数
csi_error_t csi_timer_init(csi_timer_t *timer, uint32_t idx)
,第二个参数idx为设备ID,在使用的时候发现需要从1开始,idx=0应该是被占用了。
- 创建回调函数,回调函数的格式为
void (*callback)(csi_timer_t *timer, void *arg)
;
- 注册回调函数
csi_error_t csi_timer_attach_callback(csi_timer_t *timer, void *callback, void *arg)
;
- 启动定时器
csi_error_t csi_timer_start(csi_timer_t *timer, uint32_t timeout_us)
,第二个参数为周期值,单位为us。而且是周期性的启动。
比如使用定时器实现LED闪烁的例程如下:
//创建用到的句柄
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;
}
二、PWM的使用
PWM模式实现了PWM的输出与捕获功能。支持主要使用的输出功能。PWM的输出是没有回调函数的,而输入捕获有回调函数。
使用PWM输出功能的步骤:
- 设置引脚为PWM模式
- 初始化PWM
- 配置PWM的输出功能
- 启动PWM的输出
这次实现一个呼吸灯的效果,因为输出功能没有回调函数,所以使用上面的TIMER去更新PWM的比较值。
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;
}
注意 :在函数csi_pwm_out_config()
和csi_pwm_out_start()
中,第二个参数为通道号,但是通道号的使用要注意,为引脚通道号整除2。为什么这样呢?参考其数据手册和源代码(见下图),CH2601的PWM共有6组,每组有2个通道,这两个通道共用1个计数器。可能是因为这个原因,官方在写驱动函数的时候使用了简单处理方法,让两个通道使用相同的设置值,因此在设置的时候,通道号需要整除2。