7脚屏PWM控制亮度
测试SDK版本:《AC695N_soundbox_sdk_release_3.1.0》
文章目录
前言
此篇分享7脚屏的一些相关知识,主要介绍用PWM控制7脚屏亮度的方法。
一、7脚屏亮度控制的方法
1.1 利用IO口的驱动能力
杰理的IC,一般驱动能力就两级:
注意:7脚屏的7个IO口选择,一定要选相同驱动能力的IO口,不然会出现亮度不均匀的问题
具体的设置方法就是:
在扫屏时,7个IO有输出高电平的,有输出低电平的,在输出高电平时,改变IO口的HD0和HD这两个寄存器。
强输出:
gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[cnt], 1);
gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[cnt], 1);
弱输出:
gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[cnt], 0);
gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[cnt], 0);
此方法只适用于亮度只有两级变化的情况。某些案子有自定义休眠的需求,但是休眠又不能关屏的,需要降低亮度来降低功耗的这种情况。比如时钟音箱等。
1.2 加驱动IC
如果客户对成本不太敏感,可以建议客户增加驱动IC。但是,也是要重新搞一份驱动代码的。
还有一种方案,7脚屏中集成了一颗OTP单片机驱动的,价格应该和单个7脚屏差不多,这个东西也是为了省口省成本搞出来的:
可以看到,这个屏的控制方式为单线通讯:
这就得用定时器中断去模拟它的时序,且中断函数要放到RAM中跑,不然会被其它任务打断,照成时序不准,屏出现乱闪的问题。
此方法能解决问题,但是也增加了开发成本。
1.3 利用PWM和IO remapping,实现PWM调节亮度
我们知道,杰理IC的IO是支持 remapping 功能的,PWM也是支持IO remapping 的:
具体实现就是,初始化PWM后,用Outout_Channel将PWM输出映射到IO上就可以了。在扫屏时,7个IO有输出高电平的,有输出低电平的,在输出高电平时,只要用Outout_Channel把一个timer的PWM输出指向本来要输出高电平的脚。导致这些脚输出PWM波形,就可以通过条件PWM占空比来调节屏的亮度。
在 mcpwm.c 中,写一个自己的 PWM占空比 设置函数,主要是可以修改PWM的频率,SDK默认配了10k,但是实际调案子发现,如果PCB没处理好,PWM频率设置在20k以下,会产生噪声,这个噪声会随着PWM的频率而变化,所以改一个可以修改PWM频率的接口出来,这个频率一般设置在20k以上,一般人耳听不到20k以上的声音。
关于初始化,timer1被系统用到,sdk默认扫屏用的timer2,所以一般不选这两个timer。
void user_set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty)
{
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / fre;
}
void user_timer_pwm_init(void)
{
timer_pwm_init(JL_TIMER3, 0xff*100, 100, IO_PORTA_15, CH2_T3_PWM_OUT);
//timer_pwm_init(JL_TIMER3, 10000, 5000, IO_PORTB_05, 0);
//timer_pwm_init(JL_TIMER5, 10000, 8000, IO_PORTB_07, 0);
}
然后就是改下屏的驱动:
IO输出高时,用函数 u32 gpio_output_channle(u32 gpio, u32 clk) 将通道 CH2_T3_PWM_OUT 的PWM输出指向 对应IO。
IO输出低时,要注意将IO的映射解除,主要就是控制IO的 dir 和 die 寄存器。
if (__this->user_data->pin_type == LED7_PIN7) {
//pin cnt output H
gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[cnt], 1);
gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[cnt], 1);
//gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[cnt], 1);
gpio_output_channle(__this->user_data->pin_cfg.pin7.pin[cnt], CH2_T3_PWM_OUT);
for (i = 0; i < 7; i++) {
if (seg & BIT(i)) {
//pin i output L
gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[i], 0);
gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[i], 0);
gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[i], 0);
gpio_set_die(__this->user_data->pin_cfg.pin7.pin[i],0);
}
}
cnt = (cnt >= 6) ? 0 : cnt + 1;
再然后,就可以通过之前的 PWM占空比 设置函数去改变屏的亮度了
u8 user_duty_level = 100;
#define USER_PWM_DETY_SET(timer_hdl,duty) user_set_timer_pwm_duty(timer_hdl,100*0xff,duty*0xff)
... ...
case LED7_DUTY_SW:
user_duty_level += 10;
if(user_duty_level > 100){
user_duty_level = 0;
}
USER_PWM_DETY_SET(JL_TIMER3,user_duty_level);
break;
实际效果:
二、7脚屏的其它问题记录
2.1 不看屏的原理图,用代码点屏
更改显示更新函数:
static void __ui_led7_update_bShowbuf1(void)
{
#if 0
__this->led7_var.bShowBuff1[0] = 0; //if pin0 output 1, other output 0/1
__this->led7_var.bShowBuff1[1] = 0;
__this->led7_var.bShowBuff1[2] = 0;
__this->led7_var.bShowBuff1[3] = 0;
__this->led7_var.bShowBuff1[4] = 0;
__this->led7_var.bShowBuff1[5] = 0;
__this->led7_var.bShowBuff1[6] = 0;
__this->led7_var.bShowBuff1[xxx] = BIT(yyy);
#else
... ...
#endif
}
利用两个按键改变IO的高低,在将X、Y值依据点亮的位置填入真值表:
case MSG_BT_NEXT_FILE:
xxx++;
xxx%=7;
printf("x: %d y: %d\n",xxx,yyy);
break;
case MSG_BT_PREV_FILE:
yyy++;
yyy%=7;
printf("x: %d y: %d\n",xxx,yyy);
break;
2.2 首次上电,蓝牙初始化时,显示会乱闪一下的问题
默认sdk,每次烧写程序到板子后,第一次上电,蓝牙初始化时,显示内容都会乱闪一下,这个问题,估计是蓝牙初始化时,哪里写VM,关了总中断导致的。
解决办法SDK已经给出了,将LED7跑RAM使能:
#define TCFG_LED7_RUN_RAM 1 //led7跑ram 不屏蔽中断(需要占据2k附近ram)
然后优先级设置这里,有个小BUG,宏没生效,可以加头文件也可以手动打开:
总结
此篇内容适用于多数杰理系列,比如AC695X、AC696X、AC692X等等,都是通用的方法