IMX6ULL裸机-2-PWM定时器

发布者:VelvetWhisper最新更新时间:2024-07-03 来源: elecfans关键字:PWM  定时器 手机看文章 扫描二维码
随时随地手机看文章

1 PWM定时器介绍

一共有 8 路 PWM 信号,每个 PWM 包含一个 16 位的计数器和一个 4 x 16 的数据 FIFO。一路框图如下:

①、此部分是一个选择器,用于选择 PWM 信号的时钟源,一共有三种时钟源:ipg_clk,pg_clk_highfreq 和 ipg_clk_32k。 ②、这是一个 12 位的分频器,可以对①中选择的时钟源进行分频。 ③、这是 PWM 的 16 位计数器寄存器,保存着 PWM 的计数值。 ④、这是 PWM 的 16 位周期寄存器,此寄存器用来控制 PWM 的频率。 ⑤、这是 PWM 的 16 位采样寄存器,此寄存器用来控制 PWM 的占空比。 ⑥、此部分是 PWM 的中断信号,PWM 是提供中断功能的,如果使能了相应的中断的话就会产生中断。 ⑦、此部分是 PWM 对应的输出 IO,产生的 PWM 信号就会从对应的 IO 中输出。


2 PWM控制器配置

2.1 PWMx_PWMPR 周期设置

PWM 的 16 位计数器是个上计数器,此计数器会从 0X0000 开始计数,直到计数值等于寄存器PWMx_PWMPR(x=1~8)+ 1,然后计数器就会重新从0X0000 开始计数,如此往复。PWMx_PWMPR设置频率。PWM周期公式如下:


PWM_FRE = PWM_CLK / (PERIOD + 2)

也就是PWMO(Hz) = PCLK(Hz) / (PERIOD + 2)


比如当前PWM_CLK=1MHz, 要产生1KHz的PWM,那么PERIOD = 1000000/1K - 2 = 998。,如下设置1000,即可得到PERIOD=998,也就是1khz.


void pwm1_setperiod_value(unsigned int value)

{

    unsigned int regvalue = 0;


    if(value < 2)

        regvalue = 2;

    else 

        regvalue = value - 2;

    PWM1->PWMPR = (regvalue & 0XFFFF);

}

2.2 PWMx_PWMSAR 占空比

设置Sample采样寄存器,Sample数据会写入到FIFO中。当计数器的值小于 SAMPLE 的时候输出高电平(或低电平)。当计数器值大于等于 SAMPLE,小于寄存器PWM1_PWMPR 的 PERIO 的时候输出低电平(或高电平)。 假如我们要设置 PWM 信号的占空比为 50%,那么就可以将 SAMPLE 设置为(PERIOD + 2) / 2 = 1000 / 2=500。


如下设置50,即可得到sample=500,也就是占空比50%.


struct backlight_dev_struc

{   

    unsigned char pwm_duty;     /* 占空比  */

};

struct backlight_dev_struc backlight_dev;


void pwm1_setsample_value(unsigned int value)

{

    PWM1->PWMSAR = (value & 0XFFFF);    

}

void pwm1_setduty(unsigned char duty)

{

    unsigned short preiod;

    unsigned short sample;

    backlight_dev.pwm_duty = duty;

    preiod = PWM1->PWMPR + 2;

    sample = preiod * backlight_dev.pwm_duty / 100;

    pwm1_setsample_value(sample);

}

2.3 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 的时候使能 PWM,为 0 的时候关闭 PWM。


void pwm1_enable(void)

{

    PWM1->PWMCR |= 1 << 0;   

}

void pwm1_init(void) {

    PWM1->PWMCR = 0;    /* 寄存器先清零 */

    PWM1->PWMCR |= (1 << 26) | (1 << 16) | (65 << 4);


    /* 设置PWM周期为1000,那么PWM频率就是1M/1000 = 1KHz。 */

    pwm1_setperiod_value(1000);


    /* 设置占空比,默认50%占空比   ,写四次是因为有4个FIFO */

    backlight_dev.pwm_duty = 50;

    for(i = 0; i < 4; i++)

    {

        pwm1_setduty(backlight_dev.pwm_duty);   

    }


    /* 使能FIFO空中断,设置寄存器PWMIR寄存器的bit0为1 */

    PWM1->PWMIR |= 1 << 0;

    system_register_irqhandler(PWM1_IRQn, (system_irq_handler_t)pwm1_irqhandler, NULL); /* 注册中断服务函数 */

    GIC_EnableIRQ(PWM1_IRQn);   /* 使能GIC中对应的中断 */

    PWM1->PWMSR = 0;            /* PWM中断状态寄存器清零 */


    pwm1_enable();              /* 使能PWM1 */

}

bit[27:26] : 01 当FIFO中空余位置大于等于2的时候FIFO空标志值位

bit[25] :0 停止模式下PWM不工作

bit[24] : 0 休眠模式下PWM不工作

bit[23] : 0 等待模式下PWM不工作

bit[22] : 0 调试模式下PWM不工作

bit[21] : 0 关闭字节交换

bit[20] : 0 关闭半字数据交换

bit[19:18] : 00 PWM输出引脚在计数器重新计数的时候输出高电平,在计数器计数值达到比较值以后输出低电平

bit[17:16] : 01 PWM时钟源选择IPG CLK = 66MHz

bit[15:4] : 65 分频系数为65+1=66,PWM时钟源 = 66MHZ/66=1MHz

bit[3] : 0 PWM不复位

bit[2:1] : 00 FIFO中的sample数据每个只能使用一次。

bit[0] : 0 先关闭PWM,后面再使能

2.4 PWM1_PWMIR中断控制寄存器

CIE(bit2):比较中断使能位,为 1 的时候使能比较中断,为 0 的时候关闭比较中断。 RIE(bit1):翻转中断使能位,当计数器值等于采样值并回滚到 0X0000 的时候就会产生此中断,为 1 的时候使能翻转中断,为 0 的时候关闭翻转中断。 FIE(bit0):FIFO 空中断,为 1 的时候使能,为 0 的时候关闭。前面代码写的是使能FIFO空中断.


/* 使能FIFO空中断,设置寄存器PWMIR寄存器的bit0为1 */

    PWM1->PWMIR |= 1 << 0;

2.5 PWM1_PWMSR 状态寄存器

FWE(bit6):FIFO 写错误事件,为 1 的时候表示发生了 FIFO 写错误。 CMP(bit5):FIFO 比较事件发标志位,为 1 的时候表示发生 FIFO 比较事件。 ROV(bit4):翻转事件标志位,为 1 的话表示翻转事件发生。 FE(bit3):FIFO 空标志位,为 1 的时候表示 FIFO 位空。 FIFOAV(bit2:0):此位记录 FIFO 中的有效数据个数,有效值为 0~4,分别表示 FIFO 中有0~4 个有效数据


初始化先清0,中断服务程序读取状态,并且清中断。FIFO 中的采样值每个周期都会少一个,所以需要不断的向 FIFO 中写入采样值,防止其为空。我们可以使能 FIFO 空中断,这样当 FIFO 为空的时候就会触发相应的中断,然后在中断处理函数中向 FIFO 写入采样值。


void pwm1_irqhandler(void) {

    if(PWM1->PWMSR & (1 << 3))  /* FIFO为空中断 */

    {

        /* 将占空比信息写入到FIFO中,其实就是设置占空比 */

        pwm1_setduty(backlight_dev.pwm_duty);

        PWM1->PWMSR |= (1 << 3); /* 写1清除中断标志位 */

    }

}


system_register_irqhandler(PWM1_IRQn, (system_irq_handler_t)pwm1_irqhandler, NULL); /* 注册中断服务函数 */

GIC_EnableIRQ(PWM1_IRQn);   /* 使能GIC中对应的中断 */

PWM1->PWMSR = 0;            /* PWM中断状态寄存器清零 */

pwm1_enable();              /* 使能PWM1 */

3 测试

初始化时设置占空比为50%,测试代码读取按键,每次该按键按下就对占空比加10%,如果占空比超过100%,重新从10%开始。


while(1) {

    keyvalue = key_getvalue();

    if(keyvalue == KEY0_VALUE)

    {

        duty += 10;             /* 占空比加10% */

        if(duty > 100)          /* 如果占空比超过100%,重新从10%开始 */

            duty = 10;

        lcd_shownum(50 + 72, 90, duty, 3, 16);

        pwm1_setduty(duty);     /* 设置占空比 */

    }


    delayms(10);

}

占空比10%时亮度波形如下,亮度很暗。


占空比90%时亮度如下:

关键字:PWM  定时器 引用地址:IMX6ULL裸机-2-PWM定时器

上一篇:IMX6ULL裸机-3-SPI控制器
下一篇:IMX6ULL裸机-1-RTC定时器

推荐阅读最新更新时间:2024-11-11 01:14

更改STM32定时器周期后的输出疑问分析
他先将STM32某定时器计数周期设为0xff,单向递增计数模式,OC比较值设为0x7F。 在某时刻将新的计数周期0x7F与比较值0x3F加载到影子寄存器。 当正在进行的一个周期结束后,经示波器测量确实可以看到其下一个周期发生变化,但其周期明显与预设值对应不上! 再次经过一个周期,定时器才会按照预设值稳定输出。 以上是咨询者不算很清晰的描述【其实咨询TIMER问题最好配上时序图】,但可以了解到他要做的事情就是在ARR=0xff,ccr=0x7F的PWM输出状态下,于某时刻赋予ARR和CCR新值以改变输出波形。 事情不算复杂,疑点就是为什么需要2个周期延时后才能有基于新配置的稳定输出。 【他这里说的2个周期显然不清楚到底指的前
[单片机]
更改STM32<font color='red'>定时器</font>周期后的输出疑问分析
TIMER之pwm应用
TIMER之pwm应用 //TIM3 PWM部分初始化 //PWM输出初始化 //arr:自动重装值 //psc:时钟预分频数 //PB5,TIMER3_CH2 void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; //GPIO 结构体初始化 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //基本定时器结构体初始化 TIM_OCInitTypeDef TIM_OCInitStructure; //output compare 结构体初始化
[单片机]
STM32通用定时器的基本定时器功能实现灯闪烁
/*MAIN.C*/ /* Includes ------------------------------------------------------------------*/ #include stm32f10x.h #include misc.h /* Private function prototypes -----------------------------------------------*/ void RCC_Configuration(void); void NVIC_Configuration(void); void GPIO_Configuration(void); void TIM3_Conf
[单片机]
基于msp430单片机定时器的使用方法解析
通过计算设置周期。 #include void main( void ) { // Stop watchdog timer to prevent TIme out reset WDTCTL = WDTPW + WDTHOLD; //WDTCTL = 0X5A80;关狗 CCTL0 = CCIE; //使能CCR0中断 CCR0 = 4095; //设置周期为0.5s TACTL = TASSEL_2 + ID_2 + MC_1; //时钟源的选择,分频,模式 P2DIR = 0XFF; // P2OUT = 0XFF; _EINT(); LPM0; } #pragma vector = TIMERA0_VECTOR __inter
[单片机]
基于msp430单片机<font color='red'>定时器</font>的使用方法解析
proteus与keil Cx51的单片机仿真(定时器方式2应用)
用定时器1方式二计数,每计满100次,将P1.0取反。 电路图: c源程序: #include reg51.h sbit P1_0=P1^0; void main() { TMOD=0X61; TL1=0X9C; TH1=0X9C; TR1=1; for( ; ; ) { do {}while(!TF1); P1_0=!P1_0;TF1=0; } }
[单片机]
快速学Arm(38)--定时器和计数器(2)
我们再来看看定时器/计数器的结构 我们再对照上图看一下下面的例子: 这个例子实现了这样匹配的功能:定时0.1s,定时到,定时器复位并产生中断,外部匹配输出0上的电平翻转. 下面一个例子实现了捕获功能: 这个例子实现了这样的功能:捕获通道0上的下降沿信号触发捕获事件并产生捕获中断. 下面这个例子实现了用定时器测量脉冲宽度的功能
[单片机]
快速学Arm(38)--<font color='red'>定时器</font>和计数器(2)
用AVR(ATMEGA128的PWM相频可调)对360度舵机控制
/******************************舵机控制头文件***********************/ #ifndef __tuoji_H__ #define __tuoji_H__ extern uchar front; extern void motor_init(void);//初使化 extern void stop(void); //停车 extern void go(uchar speed); //小车前或者后,具体看标志位 extern void l_r_front(uchar p); //小车向前走时的转弯函数 extern void l_r_back(uchar p); //小车向后走
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved