一、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