1)实验平台:正点原子Linux开发板
2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》
关注官方微信号公众号,获取更多资料:正点原子

第二十九章LCD背光调节实验
不管是使用显示器还是手机,其屏幕背光都是可以调节的,通过调节背光就可以控制屏幕的亮度。在户外阳光强烈的时候可以通过调高背光来看清屏幕,在光线比较暗的地方可以调低背光,防止伤眼睛并且省电。正点原子的三款RGB LCD也支持背光调节,本章我们就来学习如何调节LCD背光。
29.1 LCD背光调节简介
正点原子的三个RGB LCD都有一个背光控制引脚,给这个背光控制引脚输入高电平就会点亮背光,输入低电平就会关闭背光。假如我们不断的打开和关闭背光,当速度足够快的时候就不会感觉到背光关闭这个过程了。这个正好可以使用PWM来完成,PWM全称是Pulse Width Modulation,也就是脉冲宽度调制,PWM信号如图29.1.1所示:

图29.1.1 PWM信号
PWM信号有两个关键的术语:频率和占空比,频率就是开关速度,把一次开关算作一个周期,那么频率就是1秒内进行了多少次开关。占空比就是一个周期内高电平时间和低电平时间的比例,一个周期内高电平时间越长占空比就越大,反之占空比就越小。占空比用百分之表示,如果一个周期内全是低电平那么占空比就是0%,如果一个周期内全是高电平那么占空比就是100%。
我们给LCD的背光引脚输入一个PWM信号,这样就可以通过调整占空比的方式来调整LCD背光亮度了。提高占空比就会提高背光亮度,降低占空比就会降低背光亮度。重点就在于PWM信号的产生和占空比的控制,很幸运的是,I.MX6U提供了PWM外设,因此我们可以配置PWM外设来产生PWM信号。
打开《I.MX6ULL参考手册》的第40章“Chapter40 Pulse Width Modulation(PWM)”,I.MX6U一共有8路PWM信号,每个PWM包含一个16位的计数器和一个4 x 16的数据FIFO,I.MX6U的PWM外设结构如图29.1.2所示:

图29.1.2 I.MX6U PWM结构框图
图29.1.2中的各部分功能如下:
①、此部分是一个选择器,用于选择PWM信号的时钟源,一共有三种时钟源:ipg_clk、ipg_clk_highfreq和ipg_clk_32k。
②、这是一个12位的分频器,可以对①中选择的时钟源进行分频。
③、这是PWM的16位计数器寄存器,保存着PWM的计数值。
④、这是PWM的16位周期寄存器,此寄存器用来控制PWM的频率。
⑤、这是PWM的16位采样寄存器,此寄存器用来控制PWM的占空比。
⑥、此部分是PWM的中断信号,PWM是提供中断功能的,如果使能了相应的中断的话就会产生中断。
⑦、此部分是PWM对应的输出IO,产生的PWM信号就会从对应的IO中输出,I.MX6U-ALPHA开发板的LCD背光控制引脚连接在I.MX6U的GPIO1_IO8上,GPIO1_IO8可以复用为PWM1_OUT。
可以通过配置相应的寄存器来设置PWM信号的频率和占空比,PWM的16位计数器是个向上计数器,此计数器会从0X0000开始计数,直到计数值等于寄存器PWMx_PWMPR(x=1~8) +1,然后计数器就会重新从0X0000开始计数,如此往复。所以寄存器PWMx_PWMPR可以设置PWM的频率。
在一个周期内,PWM从0X0000开始计数的时候,PWM引脚先输出高电平(默认情况下,可以通过配置输出低电平)。采样FIFO中保存的采样值会在每个时钟和计数器值进行比较,当采样值和计数器相等的话PWM引脚就会改为输出低电平(默认情况下,同样可以通过配置输出高电平)。计数器会持续计数,直到和周期寄存器PWMx_PWMPR(x=1~8) +1的值相等,这样一个周期就完成了。所以,采样FIFO控制着占空比,而采样FIFO里面的值来源于采样寄存器PWMx_PWMSAR,因此相当于PWMx_PWMSAR控制着占空比。至此,PWM信号的频率和占空比设置我们就知道该如何去做了。
PWM开启以后会按照默认值运行,并产生PWM波形,而这个默认的PWM一般并不是我们需要的波形。如果这个PWM波形控制着设备的话就会导致设备因为接收到错误的PWM信号而运行错误,严重情况下可能会损坏设备,甚至人身安全。因此,在开启PWM之前最好设置好PWMx_PWMPR和PWMx_PWMSAR这两个寄存器,也就是设置好PWM的频率和占空比。
当我们向PWMx_PWMSAR寄存器写入采样值的时候,如果FIFO没满的话其值会被存储到FIFO中。如果FIFO满的时候写入采样值就会导致寄存器PWMx_PWMSR的位FWE(bit6)置1,表示FIFO写错误,FIFO里面的值也并不会改变。FIFO可以在任何时候写入,但是只有在PWM使能的情况下读取。寄存器PWMx_SR的位FIFOAV(bit2:0)记录着当前FIFO中有多少个数据。从采样寄存器PWMx_PWMSAR读取一次数据,FIFO里面的数据就会减一,每产生一个周期的PWM信号,FIFO里面的数据就会减一,相当于被用掉了。PWM有个FIFO空中断,当FIFO为空的时候就会触发此中断,可以在此中断处理函数中向FIFO写入数据。
关于I.MX6U的PWM的原理知识就讲解到这里,接下来看一下PWM的几个重要的寄存器,本章我们使用的是PWM1,首先看一下寄存器PWM1_PWMCR寄存器,此寄存器结构如图29.1.2所示:

图29.1.2寄存器PWM1_PWMCR寄存器结构
寄存器PWM1_PWMCR用到的重要位如下:
FWM(bit27:26):FIFO水位线,用来设置FIFO空余位置为多少的时候表示FIFO为空。设置为0的时候表示FIFO空余位置大于等于1的时候FIFO为空;设置为1的时候表示FIFO空余位置大于等于2的时候FIFO为空;设置为2的时候表示FIFO空余位置大于等于3的时候FIFO为空;设置为3的时候表示FIFO口语位置大于等于4的时候FIFO为空。
STOPEN(bit25):此位用来设置停止模式下PWM是否工作,为0的话表示在停止模式下PWM继续工作,为1的话表示停止模式下关闭PWM。
DOZEN(bit24):此位用来设置休眠模式下PWM是否工作,为0的话表示在休眠模式下PWM继续工作,为1的话表示休眠模式下关闭PWM。
WAITEN(bit23):此位用来设置等待模式下PWM是否工作,为0的话表示在等待模式下PWM继续工作,为1的话表示等待模式下关闭PWM。
DEGEN(bit22):此位用来设置调试模式下PWM是否工作,为0的话表示在调试模式下PWM继续工作,为1的话表示调试模式下关闭PWM。
BCTR(bit21):字节交换控制位,用来控制16位的数据进入FIFO的字节顺序。为0的时候不进行字节交换,为1的时候进行字节交换。
HCRT(bit20):半字交换控制位,用来决定从32位IP总线接口传输来的哪个半字数据写入采样寄第器的第16位中。
POUTC(bit19:18):PWM输出控制控制位,用来设置PWM输出模式,为0的时候表示PWM先输出高电平,当计数器值和采样值相等的话就输出低电平。为1的时候相反,当为2或者3的时候PWM信号不输出。本章我们设置为0,也就是一开始输出高电平,当计数器值和采样值相等的话就改为低电平,这样采样值越大高电平时间就越长,占空比就越大。
CLKSRC(bit17:16):PWM时钟源选择,为0的话关闭;为1的话选择ipg_clk为时钟源;为2的话选择ipg_clk_highfreq为时钟源;为3的话选择ipg_clk_32k为时钟源。本章我们设置为1,也就是选择ipg_clk为PWM的时钟源,因此PWM时钟源频率为66MHz。
PRESCALER(bit15:4):分频值,可设置为0~4095,对应着1~4096分频。
SWR(bit3):软件复位,向此位写1就复位PWM,此位是自清零的,当复位完成以后此位会自动清零。
REPEAT(bit2:1):重复采样设置,此位用来设置FIFO中的每个数据能用几次。可设置0~3,分别表示FIFO中的每个数据能用1~4次。本章我们设置为0,即FIFO只的每个数据只能用一次。
EN(bit0):PWM使能位,为1