平头哥RVB2601测评:点亮你的LED——GPIO与PWM、及PWM的疑问
[复制链接]
本帖最后由 xiyue521 于 2021-7-21 02:38 编辑
一、点亮你的RGB灯:
从原理图看出LED低电平亮:我们可以用通用IO口点亮还可以将GPIO复用为PWM来实现呼吸灯的效果。
①GPIO方式: (以PA7为例)
//设置引脚模式为通用IO口:
csi_pin_set_mux(PA7, PIN_FUNC_GPIO);
//引脚初始化:
csi_gpio_pin_init(&r, PA7);
//设置引脚输出方向:
csi_gpio_pin_dir(&r, GPIO_DIRECTION_OUTPUT);
//设置引脚电平:
csi_gpio_pin_write(&r, GPIO_PIN_LOW);
了解完主要的API后我们在主函数创建一个led任务,在任务重初始化,接着每1000ms调用led样式刷新函数(也就是一秒切换一个led颜色).
int main(void)
{
board_yoc_init();
aos_task_new("demo", demo_task, NULL, 10 * 1024);
aos_task_new("led_task", led_task, NULL, 1 * 1024);
return 0;
}
static void led_task(void *arg)
{
led_pinmux_init();
while(1)
{
aos_msleep(1000);
led_refresh();
}
}
void led_refresh()
{
g_ctr++;
if(g_ctr == 3)
g_ctr = 0;
if(g_ctr == 0)
{
csi_gpio_pin_write(&r, GPIO_PIN_HIGH);
csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
csi_gpio_pin_write(&b, GPIO_PIN_LOW);
}
else if(g_ctr == 1)
{
csi_gpio_pin_write(&r, GPIO_PIN_LOW);
csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
csi_gpio_pin_write(&b, GPIO_PIN_HIGH);
}
else
{
csi_gpio_pin_write(&r, GPIO_PIN_HIGH);
csi_gpio_pin_write(&g, GPIO_PIN_LOW);
csi_gpio_pin_write(&b, GPIO_PIN_HIGH);
}
}
②PWM方式:
//设置引脚功能复用为PWM模式:
csi_pin_set_mux(PA7, PA7_PWM_CH7);
//初始化PWM:
csi_pwm_init(&r, 0);
//配置PWM周期、有效电平时间和有效电平极性:
csi_pwm_out_config(&r, 7 / 2, 300, 100, PWM_POLARITY_HIGH);
//使能PWM
csi_pwm_out_start(&r, 7 / 2);
用逻辑分析仪测出来占空比差不多为100/300即33.3%
然后我们在main函数依然创建一个led任务,led刷新函数里没5ms对g_ctr++或--,取决于dir值,dir就要用到刚刚的控制台用户自定义命令了,在控制台对dir值修改可以改变呼吸灯的变亮或变暗。
static void led_task(void *arg)
{
led_pinmux_init();
while(1)
{
aos_msleep(5);
led_refresh();
}
}
void led_pinmux_init()
{
// 7
csi_error_t ret;
csi_pin_set_mux(PA7, PA7_PWM_CH7);
csi_pin_set_mux(PA25, PA25_PWM_CH2);
csi_pin_set_mux(PA4, PA4_PWM_CH4);
ret = csi_pwm_init(&r, 0);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
ret = csi_pwm_out_config(&r, 7 / 2, 300, 100, PWM_POLARITY_HIGH);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
ret = csi_pwm_out_start(&r, 7 / 2);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
// 25
ret = csi_pwm_out_config(&r, 2 / 2, 300, 100, PWM_POLARITY_HIGH);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
ret = csi_pwm_out_start(&r, 2 / 2);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
// 4
ret = csi_pwm_out_config(&r, 4 / 2, 300, 100, PWM_POLARITY_HIGH);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
ret = csi_pwm_out_start(&r, 4 / 2);
if(ret != CSI_OK)
{
printf("===%s, %d\n", __FUNCTION__, __LINE__);
return;
}
csi_pwm_out_stop(&r, 2 / 2);
csi_pwm_out_stop(&r, 7 / 2);
}
/***************************/
void led_refresh()
{
switch(dir)
{
case 0:
g_ctr++;
if(g_ctr == 300)
{
g_ctr = 0;
}
csi_pwm_out_config(&r, 1, 300, g_ctr, PWM_POLARITY_HIGH);
break;
case 1:
g_ctr--;
if(g_ctr == 0)
{
g_ctr = 300;
}
csi_pwm_out_config(&r, 1, 300, g_ctr, PWM_POLARITY_HIGH);
break;
default:
g_ctr++;
if(g_ctr == 300)
{
g_ctr = 0;
}
csi_pwm_out_config(&r, 1, 300, g_ctr, PWM_POLARITY_HIGH);
break;
}
}
/*****************/
void mycmd_func(char *wbuf, int wbuf_len, int argc, char **argv)
{
extern uint dir;
dir = atoi(argv[1]);
}
可以看到输入test 0时亮度逐渐变暗,test 1反之。
二、舵机:
就是利用PWM设置周期为20ms=20000us,根据占空比的大小舵机改变角度。
void mycmd_func(char *wbuf, int wbuf_len, int argc, char **argv)
{
csi_pwm_out_config(&r, 4 / 2, 20000, atoi(argv[1]), PWM_POLARITY_HIGH);
}
在命令行改变高电平的时间,在500us-2500us之间对应0-180°,1500us是90°的位置。
三、关于PWM几点疑惑:
在设置PWM的配置时用的是:
其中4/2的4是通道4,但是不知道为什么要/2,这么说的话,4/2和5/2效果应该是一样的(结果都是整形2),也就是说通道5如果配置为PWM输出的话,那这两个引脚就是一模一样的了,查看手册发现有4个引脚为CH4,5:我们全部配置为PWM 模式:
接上逻辑分析仪:
结果真的一模一样,周期占空比都是一样的,哎就很奇怪,不知道哪的问题。。。或是SDK的问题。
|