《嵌入式硬件(二十一):基于IMX6ULL的脉冲宽度调制(PWM)操作》

一、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
相关推荐
小莞尔7 小时前
【51单片机】【protues仿真】基于51单片机简易电子琴系统(8键)
c语言·单片机·嵌入式硬件·物联网·51单片机
盈创力和20078 小时前
技术解析:CO与NO₂双气体监测如何构筑协同化安全防线
嵌入式硬件·安全·以太网温湿度传感器·多参量传感器·温湿度+气体智能传感器
平凡灵感码头9 小时前
STM32 串口中断接收原理与实战详解:从配置到中断服务函数全流程解析
单片机·嵌入式硬件
切糕师学AI9 小时前
MCU中的RC电路(Resistor-Capacitor Circuit)
单片机·嵌入式硬件
朱嘉鼎10 小时前
KeilIDE背后的命令
c语言·嵌入式硬件·keilmdk
GilgameshJSS16 小时前
STM32H743-ARM例程33-TOUCH
c语言·arm开发·stm32·单片机·嵌入式硬件
hazy1k1 天前
51单片机基础-继电器实验
stm32·单片机·嵌入式硬件·51单片机·1024程序员节
美好的事情总会发生1 天前
FPGA的LVDS接口电压
嵌入式硬件·fpga开发·硬件工程·智能硬件
kaka❷❷1 天前
STM32中 ESP8266 MQTT ModBus RS482 介绍
stm32·嵌入式硬件·智能路由器