• 【杰理AC695X】7脚屏PWM控制亮度


    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);
    
    • 1
    • 2

    弱输出:

    	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

    此方法只适用于亮度只有两级变化的情况。某些案子有自定义休眠的需求,但是休眠又不能关屏的,需要降低亮度来降低功耗的这种情况。比如时钟音箱等。

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    然后就是改下屏的驱动:

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    再然后,就可以通过之前的 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实际效果:
    在这里插入图片描述

    二、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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    利用两个按键改变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;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.2 首次上电,蓝牙初始化时,显示会乱闪一下的问题

    默认sdk,每次烧写程序到板子后,第一次上电,蓝牙初始化时,显示内容都会乱闪一下,这个问题,估计是蓝牙初始化时,哪里写VM,关了总中断导致的。

    解决办法SDK已经给出了,将LED7跑RAM使能:

    #define TCFG_LED7_RUN_RAM 					1 	//led7跑ram 不屏蔽中断(需要占据2k附近ram)
    
    • 1

    然后优先级设置这里,有个小BUG,宏没生效,可以加头文件也可以手动打开:
    在这里插入图片描述


    总结

    此篇内容适用于多数杰理系列,比如AC695X、AC696X、AC692X等等,都是通用的方法

  • 相关阅读:
    java的amazonaws接口出现无法执行http请求:管道中断
    C++ STL & 标准库
    【天梯赛 - L2习题集】啃题(6 / 44)
    Android项目使用gradle配置新旧方式对比
    fiddler抓包
    c++day3
    Oracle数据库安装,在自己的windows电脑上面。
    CentOS7设置添加shell脚本开机自动启动服务
    计算机毕业设计之疫情防疫信息化管理系统
    Java 8实战(四)- Lambda类型推断与方法引用
  • 原文地址:https://blog.csdn.net/xx842678/article/details/126527467