有的PPC控制不是采用线性计数方式,而是采用循环计数,也即下一刻的调节数值跟前一次的调节数值是相关的。以AW9956为例:它是一款脉冲控制的LCD背光驱动芯片,共有16级亮度,采用上升沿计数。
如上,Ton是从LCD背光从关断到使能的电平,之后则是规则的等长脉冲,最后Tshdn则是关断LCD背光。亮度计数分配如下:
脉冲循环计数示例图:
(1)线性计数:虽然AW9656是一款循环计数的芯片,但是也可以采用线性计数方式工作,会有典型的屏闪。只需要在每次设置前关断后再重设即可。实例代码如下:
int Brightness_SetGpio(int gpio_num,int level) { int i; int min_level = 30; //the min value for UI brightness setup int max_level = 255; //the max value for UI brightness setup int min_bri = 1; //the min value for adjust the brightness int max_bri = 16; //the max value for adjust the brightness kal_uint8 count=0, to_count=0; static int s_bBacklightOn = 1; mt_set_gpio_mode(gpio_num, GPIO_MODE_GPIO); mt_set_gpio_dir(gpio_num, GPIO_DIR_OUT); if (level) { if (level < min_level) { to_count = max_bri; } else if (level > 255) { to_count = min_bri; } else { to_count = max_bri-((level-min_level)*(max_bri-min_bri)/(max_level-min_level)); LEDS_DEBUG("[LED] infact count=%d\n", to_count); } mt_set_gpio_out(gpio_num, GPIO_OUT_ZERO); mdelay(5); //turn off EN PIN mt_set_gpio_out(gpio_num, GPIO_OUT_ONE); udelay(20); //resetting EN PIN to_count--; //to_count not include the first EN pluse for (i=1; i<to_count; i++) { mt_set_gpio_out(gpio_num, GPIO_OUT_ZERO); udelay(2); mt_set_gpio_out(gpio_num, GPIO_OUT_ONE); udelay(2); } } else { mt_set_gpio_out(gpio_num, GPIO_OUT_ZERO); mdelay(5); } return 0; }
(2)循环计数程序,已验证,具体做法不同于下述思路。
#define SN3228_BRIGHTNESS_TOTAL_LEVEL (16) #define SN3228_BRIGHTNESS_STEP_LEVEL (16) int SN3228_pre_gpio_dev_level = -1; static int Cust_SN3228_SetBacklight(int level, int div) { int phylevel; int pulse_count; int i; phylevel = level/SN3228_BRIGHTNESS_STEP_LEVEL; If( level>0 && phylevel == 0) { phylevel = 1; } if( SN3228_pre_gpio_dev_level != -1 && SN3228_pre_gpio_dev_level == phylevel ) { return 0; } else if(SN3228_pre_gpio_dev_level == -1) { SN3228_pre_gpio_dev_level = SN3228_BRIGHTNESS_TOTAL_LEVEL-1; } if( phylevel <= SN3228_pre_gpio_dev_level ) { pulse_count = SN3228_pre_gpio_dev_level - phylevel; } else { pulse_count = SN3228_BRIGHTNESS_TOTAL_LEVEL - (phylevel - SN3228_pre_gpio_dev_level); } mt_set_gpio_mode(GPIO_LCD_EN_PIN, GPIO_LCD_EN_PIN_M_GPIO); mt_set_gpio_dir(GPIO_LCD_EN_PIN, GPIO_DIR_OUT); If( level > 0 ) { If( SN3228_pre_gpio_dev_level == 0 ) { mdelay(25); mt_set_gpio_out(GPIO_LCD_EN_PIN, GPIO_OUT_ONE); } mt_set_gpio_out(GPIO_LCD_EN_PIN, GPIO_OUT_ONE); For( i=0; i<pulse_count; i++) { udelay(1); mt_set_gpio_out(GPIO_LCD_EN_PIN, GPIO_OUT_ZERO); udelay(1); mt_set_gpio_out(GPIO_LCD_EN_PIN, GPIO_OUT_ONE); } } Else { mt_set_gpio_out(GPIO_LCD_EN_PIN, GPIO_OUT_ZERO); } udelay(1); SN3228_pre_gpio_dev_level = phylevel; return 0; }