SDK版本:ac696n_soundbox_sdk_v1.2.3
杰理的PWM,定时器会绑定默认的硬件IO,而且支持任意IO映射,硬件io对应用户手册上的io,有硬件io的尽量使用硬件io。
注意:因为系统已经使用了timer1,所以不用这个定时器
PWM初始化函数:
/**
* @param JL_TIMERx : JL_TIMER0/1/2/3/4/5
* @param fre : 频率,单位Hz,不小于95
* @param duty : 初始占空比,0~10000对应0~100%
* @param port : pwm脚,可选硬件脚,也可选非硬件脚。(建议选择硬件引脚)
* @param output_ch : 映射通道,当pwm脚选择非硬件脚时有效,这时我们给他分配output_channel 0/1/2
*/
int timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty, u32 port, int output_ch)
{
u32 hw_port;
switch ((u32)JL_TIMERx) {
case (u32)JL_TIMER0 :
hw_port = IO_PORTA_05;
break;
case (u32)JL_TIMER1 :
hw_port = IO_PORTC_04;
break;
case (u32)JL_TIMER2 :
hw_port = IO_PORTB_03;
break;
case (u32)JL_TIMER3 :
bit_clr_ie(IRQ_TIME3_IDX);
hw_port = IO_PORTB_05;
break;
case (u32)JL_TIMER4 :
hw_port = IO_PORTA_01;
break;
case (u32)JL_TIMER5 :
hw_port = IO_PORTB_07;
break;
default:
return (-1);
}
if ((output_ch == (-1)) && (hw_port != port)) {
//not support output_ch
return (-1);
}
//初始化timer
JL_TIMERx->CON = 0;
JL_TIMERx->CON |= (0b10 << 2); //选择晶振时钟源:24MHz
JL_TIMERx->CON |= (0b0001 << 4); //时钟源4分频
JL_TIMERx->PRD = OSC_Hz / (4 * fre); //设置周期
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / fre; //0~10000对应0~100g
JL_TIMERx->CNT = 0; //清计数值
JL_TIMERx->CON |= (0b01 << 0); //计数模式
if (hw_port == port) {
gpio_set_die(hw_port, 1);
gpio_set_pull_up(hw_port, 0);
gpio_set_pull_down(hw_port, 0);
gpio_set_direction(hw_port, 0);
JL_TIMERx->CON |= BIT(8); //PWM使能
} else {
gpio_output_channle(port, output_ch);
return 1;
}
return 0;
}
PWM初始化函数的使用:
if (timer_pwm_init(JL_TIMER5, MY_PWM_FRE, 0, RGB_WHITE_IO, PWM_NO_OUTPUT_CH) == (-1)) {
ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n");
}
if (timer_pwm_init(JL_TIMER3, MY_PWM_FRE, 0, RGB_RED_IO, CH1_T3_PWM_OUT) == (-1)) {
ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n");
}
if (timer_pwm_init(JL_TIMER2, MY_PWM_FRE, 0, RGB_GREEN_IO, CH2_T2_PWM_OUT) == (-1)) {
ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n");
}
可以看到PWM初始化函数的参数 output_ch 可以设置是用硬件IO的方式还是映射的方式
如果是硬件IO的方式,output_ch 配置为 PWM_NO_OUTPUT_CH(-1),且传入的IO口要与传入的timer默认绑定的IO一致,这样就可以正常使用硬件IO方式的PWM了。
如果是IO映射的方式,output_ch 配置成你要映射的通道,切通道要与传入的timer对应。
可选通道有两个,CH1和CH2:
CH1_T4_PWM_OUT
CH1_T5_PWM_OUT
CH1_T2_PWM_OUT
CH1_T3_PWM_OUT
CH2_T4_PWM_OUT
CH2_T5_PWM_OUT
CH2_T2_PWM_OUT
CH2_T3_PWM_OUT
IO映射说明:
gpio_output_channle(port, output_ch)这个函数展开后是这样的:
if(output_ch == CH2_T2_PWM_OUT){
JL_IOMAP->CON3 &= ~(0b1111 << 24); ///映射io寄存器的配置清零
JL_IOMAP->CON3 |= (14 << 24); ///映射io寄存器的配置
gpio_set_direction(port,0); ///映射io方向输出
gpio_set_pull_up(port,1); ///映射io上拉开启,手册说明
gpio_set_pull_down(port,1); ///映射io下拉开启,手册说明
gpio_write(port,1); ///映射io输出高,手册说明
gpio_set_die(port,0); ///映射io 数字模拟口设置,手册说明
}else if(output_ch == CH1_T2_PWM_OUT){
JL_IOMAP->CON3 &= ~(0b1111 << 20); ///映射io寄存器的配置清零
JL_IOMAP->CON3 |= (14 << 20); ///映射io寄存器的配置
gpio_set_direction(port,0); ///映射io方向输出
gpio_set_pull_up(port,1); ///映射io上拉开启,手册说明
gpio_set_pull_down(port,1); ///映射io下拉开启,手册说明
gpio_write(port,0); ///映射io输出低,手册说明
gpio_set_die(port,1); ///映射io 数字模拟口设置,手册说明
}
这只是timer2的映射配置,其它timer差不多,这些配置都是和用户手册上对应的
手册上的寄存器说明:
IOMAP_CON3: IO mapping control register2
JL_IOMAP->CON3 &= ~(0b1111 << 24); ///映射io寄存器的配置清零
JL_IOMAP->CON3 |= (14 << 24); ///映射io寄存器的配置
IO 的输出选通如下:
gpio_set_direction(port,0); ///映射io方向输出
gpio_set_pull_up(port,1); ///映射io上拉开启,手册说明
gpio_set_pull_down(port,1); ///映射io下拉开启,手册说明
gpio_write(port,1); ///映射io输出高,手册说明
gpio_set_die(port,0); ///映射io 数字模拟口设置,手册说明
选择通道主要是通过配置IO口的输出寄存器和数字寄存器,方向设为输出,开上下拉
初始化完成后,我们调用占空比设置函数就可以调试各种RGB效果了
SDK提供的接口是这样的:
void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 duty)
{
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000; //0~10000对应0~100%
}
我们把10000改成我们熟悉的0xff:
void user_set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx,u32 duty)
{
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 0xff;
}
实际调试时可能会出现timer不够用的情况,比如说有红外功能占用了一路定时器,可以用一个timer或者两个timer实现rgb变色,具体看需求的灯的效果而定。
用一个timer或者两个timer实现的方法:
红橙黄绿蓝靛紫粉,每两种颜色只是rgb其中的两种基色的分量在变换,比如使用的是timer2和timer3,在红(timer2)蓝(timer3)基色的情况下要变为红绿,红色不用改动,将蓝色(timer3)映射的io取消掉,再将绿色的io映射到timer3就可以了。
io映射的打开和关闭可以通过配置io的状态来控制:
关闭:
gpio_set_direction(RGB_RED_IO,1);
gpio_set_pull_up(RGB_RED_IO,0);
gpio_set_pull_down(RGB_RED_IO,0);
gpio_set_die(RGB_RED_IO,0);
打开:
u32 gpio_output_channle(u32 gpio, u32 clk);
到这里,PWM的使用就差不多完事了。
至于实现什么样的效果,可以参考 【杰理AC692X】6脚RGB 5050灯珠实现全彩呼吸灯的方法 这篇博客,加上RGB转HSV的算法,就可以实现更多灯效了。