一、PWM
不管是使用显示器还是手机,其屏幕背光都是可以调节的,通过调节背光就可以控制屏幕的亮度。在户外阳光强烈的时候可以通过调高背光来看清屏幕,在光线比较暗的地方可以调低背光,防止伤眼睛并且省电。 我们使用的开发吧LCD 有一个背光控制引脚,给这个背光控制引脚输入高电平就会点亮背光,输入低电平就会关闭背光。假如我们不断的打开和关闭背光,当速度足够快的时候就不会感觉到背光关闭这个过程了。这个正好可以使用PWM 来完成,PWM 全称是 Pulse Width Modulation,也就是脉冲宽度调制,本质上来说PWM的目的就是产生一个方波。
PWM 信号有两个关键的术语:频率和占空比 ,频率 就是开关速度,把一次开关算作一个周期,那么频率就是 1 秒内进行了多少次开关。占空比 就是一个周期内高电平时间和低电平时间的比例,一个周期内高电平 时间越长占空比就越大,反之占空比就越小。占空比用百分之表示,如果一个周期内全是低电平那么占空比就是 0%,如果一个周期内全是高电平那么占空比就是100%。
我们给 LCD 的背光引脚输入一个 PWM 信号,这样就可以通过调整占空比的方式来调整LCD 背光亮度了。提高占空比就会提高背光亮度,降低占空比就会降低背光亮度。重点就在于PWM 信号的产生和占空比的控制,很幸运的是,I.MX6U 提供了 PWM 外设,因此我们可以配置 PWM 外设来可以方便地产生 PWM 信号。
二、寄存器
1.引脚设置




2.控制寄存器(PWMCR)



3.状态寄存器(PWMSR)


4.中断寄存器(PWMIR)

5.采样寄存器(PWMSAR)

6.周期寄存器(PWMPR)

三、代码
1.pwm.h
            
            
              cs
              
              
            
          
          #ifndef _PWM_H_
#define _PWM_H_
extern void init_pwm1(void);
extern void set_ratio(void);
extern float global_ratio;
#endif
        2.pwm.c
            
            
              cs
              
              
            
          
          #include "pwm.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "led.h"
#include "interrupt.h"
#include "core_ca7.h"
float global_ratio = 1.0;
void set_ratio(void)
{
    int i;
    for(i = 0;i < 4;++i)
    {
        PWM1->PWMSAR = PWM1->PWMPR * global_ratio;
    }
}
void pwm1_interrupt_handler(void)
{
    if((PWM1->PWMSR & (1 << 3)) != 0)
    {
        set_ratio();
        PWM1->PWMSR |= (1 << 3);
    }
}
void init_pwm1(void)
{
    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_PWM1_OUT, 0);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_PWM1_OUT, 0xB090);
    PWM1->PWMCR = 0;
    PWM1->PWMCR |= (1 << 26) | (1 << 16) | (65 << 4) | (3 << 1);
    PWM1->PWMIR |= (1 << 0);
    PWM1->PWMPR = 998;
    set_ratio();
    system_interrupt_register(PWM1_IRQn, pwm1_interrupt_handler);
    GIC_EnableIRQ(PWM1_IRQn );
    PWM1->PWMCR |= (1 << 0);
}
        3.main.c
            
            
              cs
              
              
            
          
          #include "string.h"
#include "led.h"
#include "beep.h"
#include "MCIMX6Y2.h"
#include "key.h"
#include "interrupt.h"
#include "clock.h"
#include "epit.h"
#include "gpt.h"
#include "delay.h"
#include "uart.h"
#include "stdio.h"
#include "i2c.h"
#include "lm75.h"
#include "adc.h"
#include "spi.h"
#include "adxl345.h"
#include "lcd.h"
#include "framebuffer.h"
#include "pwm.h"
#include "ts.h"
int main(void)
{
    
    init_clock();
    system_interrupt_init();
    init_led();
    init_beep();
    // init_key();
//    init_epit1();
    init_gpt1();
    init_uart1(); 
    init_i2c1();
    init_i2c2();
    init_adc1_channle1();
    init_spi3();
//    init_adxl345();
    init_lcd();
    lcd_clear(0x00FFFFFF);
    init_pwm1();
    while(1)
    {     
        char buffer[32];
        float f;
        f = lm75_get_temperature();
        int k = f * 10;
        int m = k / 10;
        int n = k % 10;
        sprintf(buffer, "%d.%d", m, n);
        lcd_show_string(100, 100, 16 * strlen(buffer), 32, 32, buffer);
 
        delays(100);
        global_ratio += 0.05;
        if(global_ratio > 1)
        {
            global_ratio = 0;
        }
        set_ratio();
    }
    return 0;
}
        4.start.S
修改bug,stmfd sp!, {r0-r12, lr}往前放
            
            
              cs
              
              
            
          
          .global _start
_start:
	ldr pc, =_reset_handler
	ldr pc, =_undefine_handler
	ldr pc, =_svc_handler
	ldr pc, =_prefetch_abort_handler
	ldr pc, =_data_abort_handler
	ldr pc, =_reserved_handler
	ldr pc, =_irq_handler
	ldr pc, =_fiq_handler
_undefine_handler:
	ldr pc, =_undefine_handler
_svc_handler:
	ldr pc, =_svc_handler
_prefetch_abort_handler:
	ldr pc, =_prefetch_abort_handler
_data_abort_handler:
	ldr pc, =_data_abort_handler
_reserved_handler:
	ldr pc, =_reserved_handler
_irq_handler:
    subs lr, lr, #4
    stmfd sp!, {r0-r12, lr}
    mrc p15, 4, r1, c15, c0, 0
    add r1, r1, #0x2000
    ldr r0, [r1, #0x0C]
    stmfd sp!, {r0, r1}
    cps #0x1F
    stmfd sp!, {lr}
    bl system_interrupt_handler
    ldmfd sp!, {lr}
    cps #0x12
    ldmfd sp!, {r0, r1}
    str r0, [r1, #0x10]
    ldmfd sp!, {r0-r12, pc}^
_fiq_handler:
	ldr pc, =_fiq_handler
_reset_handler:
    cps #0x12
    ldr sp, =0x86000000
    cps #0x1F  
    cpsie i
    ldr sp, =0x84000000
    bl _enable_icahce
    bl _set_vbar
    bl _bss_clear
    bl _enable_fpu
    b main
_enable_fpu:
    // 1. 设置CPACR寄存器使能FPU访问
    mrc     p15, 0, r0, c1, c0, 2   // 读取CPACR
    orr     r0, r0, #(0xF << 20)    // 设置CP10和CP11为完全访问
    mcr     p15, 0, r0, c1, c0, 2   // 写回CPACR
    
    // 2. 使能FPU
    mov     r0, #0x40000000         // 设置FPEXC的EN位
    vmsr    fpexc, r0               // 写入FPEXC
    
    // 3. 配置FPSCR
    mov     r0, #0x00000000         // 清除所有标志位
    vmsr    fpscr, r0               // 写入FPSCR
    
    bx      lr                      // 返回
_enable_icahce:
    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #(1 << 13)
    orr r0, r0, #(1 << 12)
    mcr p15, 0, r0, c1, c0, 0
    bx lr
_set_vbar:
    ldr r0, =0x87800000
    mcr p15, 0, r0, c12, c0, 0
    bx lr
_bss_clear:
    ldr r0, =__bss_start
    ldr r2, =__bss_end
loop:
    mov r1, #0
    str r1, [r0]
    add r0, r0, #4
    cmp r0, r2
    blt loop
    bx lr
finished:
    b finished