打印
[PIC®/AVR®/dsPIC®产品]

输出比较-PWM脉宽调制模式

[复制链接]
9757|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kxsi|  楼主 | 2021-8-9 13:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
脉宽调制模式介绍
当控制位 OCM<2:0> (OCxCON<2:0>)被设置为 110 或 111 时,选定的输出比较通道被配置为 PWM (脉宽调制)工作模式。有以下两种 PWM 模式可供使用:

• 不带故障保护输入的 PWM

• 带故障保护输入的 PWM

第二种 PWM 模式需使用 OCFA 或 OCFB 故障输入引脚。在该模式下,OCFx 引脚上的异步逻辑电平 0 会使选定的 PWM 通道关闭。

在 PWM 模式下, OCxR 寄存器是只读从占空比寄存器, OCxRS 是缓冲寄存器,由用户写入数据来更新 PWM 占空比。在每次发生定时器与周期寄存器的匹配事件时 (PWM 周期结束),占空比寄存器 OCxR 会装入 OCxRS 的内容。 TyIF 中断标志在每个 PWM 周期边界处置为有效。


使用特权

评论回复
沙发
kxsi|  楼主 | 2021-8-9 13:30 | 只看该作者
输出比较模块配置为 PWM 操作步骤
1. 通过写选定的定时器周期寄存器 (PRy),设置 PWM 周期。

2. 通过写 OCxRS 寄存器设置 PWM 占空比。

3. 向 OCxR 寄存器中写入初始占空比。

4. 如果需要,允许定时器和输出比较模块的中断。如果要使用 PWM 故障引脚,则必须设置输出比较中断。

5. 通过写输出比较模式位 OCM<2:0>(OCxCON<2:0>),将输出比较模块配置为两种 PWM工作模式中的一种。

6. 设置 TMRy 预分频值,并通过设置 TON (TxCON<15>) = 1 使能时基。

特别注意:在第一次使能输出比较模块之前,必须先初始化 OCxR 寄存器。当模块工作于 PWM模式时,OCxR 寄存器变为只读占空比寄存器。OCxR 中保存的值成为第一个 PWM周期的 PWM 占空比。占空比缓冲寄存器 OCxRS 的内容在发生时基周期匹配之后才会被传送到 OCxR。


使用特权

评论回复
板凳
kxsi|  楼主 | 2021-8-9 13:32 | 只看该作者
PWM 输出波形


带故障保护输入引脚的 PWM

输出比较模式位 OCM<2:0>(OCxCON<2:0>)被设置为 111 。

故障保护通过 OCFA 和 OCFB 引脚提供。OCFA 引脚与输出比较通道 1 至 4 关联,而 OCFB 引脚与输出比较通道 5 关联。

如果在 OCFA/OCFB 引脚检测到逻辑 0,则选定的 PWM 输出引脚被置为高阻抗状态。PWM 输出立即关闭,不连接到器件时钟源。该状态将保持直到满足以下条件:

• 外部故障条件已经消除

• 通过写相应的模式位 OCM<2:0> (OCxCON<2:0>)重新使能 PWM 模式

PWM 周期 = [(PR + 1) • T PB • (TMR 预分频值 )]

PWM 周期一定不能超出所选定模式的周期寄存器宽度

PWM占空比

通过写入 OCxRS 寄存器来指定 PWM 占空比。可以在任何时候写 OCxRS 寄存器,但是在 PRy和 TMRy 发生匹配 (即周期结束)前占空比值不会被锁存到 OCxR 中。这可以为 PWM 占空比提供双重缓冲,对于 PWM 的无毛刺操作是极其重要的。在 PWM 模式下,OCxR 是只读寄存器。

PWM 占空比有一些重要的边界参数,包括:

• 如果占空比寄存器 OCxR 中装入 0x0000,则 OCx 引脚将保持低电平 (占空比为 0%)。

• 如果 OCxR 大于 PRy (定时器周期寄存器),则引脚将保持高电平 (占空比为 100%)。

• 如果 OCxR 等于 PRy,则 OCx 引脚在一个时基计数值内为低电平,而在所有其他计数值内均为高电平。

PWM输出时序图



I/O 引脚控制

当输出比较模块被使能时,I/O 引脚方向由比较模块控制。当比较模块被禁止时,它会将 I/O 引脚控制权归还给相应的引脚 LAT 和 TRIS 控制位。

当使能了具有故障保护输入模式的 PWM 时,必须通过将相应的 TRIS SFR 位置 1 以将 OCFx 故障引脚配置为输入。选择 PWM 故障模式时, OCFx 故障输入引脚不会自动配置为输入。



节能和调试模式下的操作

SLEEP (休眠)模式下

当器件进入 SLEEP(休眠)模式时,系统时钟被禁止。在 SLEEP(休眠)模式期间,输出比较模块会将引脚驱动为与在进入 SLEEP (休眠)模式之前相同的有效状态。然后模块将暂停在该状态。

例如,如果引脚原先为高电平,则在 CPU 进入 SLEEP(休眠)状态后,引脚将保持高电平。类似地,如果引脚原先为低电平,则在 CPU 进入 SLEEP(休眠)状态后,引脚将保持低电平。在这两种情况下,当器件唤醒时,输出比较模块将继续工作。

当模块在 PWM 故障模式下工作时,故障电路的异步部分将保持工作状态。如果检测到故障,比较输出使能信号会置为无效,OCFLT(OCxCON<4>)被置 1。如果允许了相应中断,还将产生中断,并且器件将从 SLEEP (休眠)模式唤醒。

IDLE (空闲)模式下

当器件进入 IDLE (空闲)模式时,系统时钟源保持工作,但 CPU 停止执行代码。 SIDL 位(OCxCON<13>)用于选择比较模块在器件进入 IDLE (空闲)模式时是停止工作还是在 IDLE

(空闲)模式下继续正常工作。

• 如果 SIDL = 1,则在 IDLE (空闲)模式下模块将停止工作。模块在 IDLE (空闲)模式下停止工作时将执行与在 SLEEP (休眠)模式下相同的程序。

• 如果 SIDL = 0,则只有选定时基设置为在 IDLE (空闲)模式下工作时,模块才能在 IDLE

(空闲)模式下继续工作。如果 SIDL 位为逻辑 0,则输出比较通道将在 CPU IDLE(空闲)模式期间工作。此外,还必须将相应的 SIDL 位设为逻辑 0 以使能时基。

• 当模块在PWM故障模式下工作时,故障电路的异步部分将保持工作状态。如果检测到故障,比较输出使能信号会置为无效,OCFLT(OCxCON<4>)被置 1。如果允许了相应中断,还将产生中断,并且器件将从 IDLE (空闲)模式唤醒。

DEBUG (调试)模式下

各种复位的影响

MCLR 复位

在发生 MCLR 事件之后,每个输出比较模块的 OCxCON、 OCxR 和 OCxRS 寄存器会复位为值0x00000000。

上电复位

在发生上电(Power-on,POR)事件之后,每个输出比较模块的 OCxCON、OCxR 和 OCxRS寄存器会复位为值 0x00000000。

看门狗定时器复位

在发生看门狗定时器 (Watchdog Timer, WDT)事件之后, OCMP 控制寄存器的状态取决于WDT 事件之前 CPU 的工作模式。

如果器件不处于 SLEEP (休眠)模式,则 WDT 事件会将 OCxCON、 OCxR 和 OCxRS 寄存器强制为复位值 0x00000000。

如果在发生 WDT 事件时器件处于 SLEEP (休眠)模式,则 OCxCON、 OCxR 和 OCxRS 寄存器值不受影响。


使用特权

评论回复
地板
kxsi|  楼主 | 2021-8-9 13:32 | 只看该作者
PWM脉宽调整模式Harmony配置
1、在Project Graph界面中添加定时器TMR2以及输出比较OCMP1,并配置定时器(可参考前面**配置,不赘述);

2、配置输出比较参数,其中Select Output Compare Mode选择为PWM mode on OCx: Fault pin disabled 即简单脉宽调制模式,不带故障保护输入;并配置Compare value(OCxR)值,初始只读占空比寄存器;



3、组件配置完成后点击左侧的Generate Code按钮生成代码;

4、生成的代码与原始代码存在差异,需进行确认;

5、代码生成后需要的操作;

1、初始化完成后添加TMR2以及OCMP1的启动;

2、写修改占空比函数;

8、编译运行将代码烧录到开发板中;


使用特权

评论回复
5
kxsi|  楼主 | 2021-8-9 13:33 | 只看该作者
具体代码分析
文件plib_ocmp1.c

void OCMP1_Initialize (void)
{
    /*Setup OC1CON */
    /*OCM = 6 */ // OCM<2:0> 为 110 简单脉宽调制模式,不带故障保护输入
    /*OCTSEL = 0 */ // 输出比较定时器选择位,0:TMR2,1:TMR3
    /*OC32 = 0 */ //32 位比较模式位
    /*SIDL = false */ //空闲模式停止位
    OC1CON = 0x6; //输出比较控制寄存器

    OC1R = 10; //初始只读占空比寄存器
    OC1RS = 10; //缓冲寄存器

    IEC0SET = _IEC0_OC1IE_MASK; //中断允许控制
}

//使能输出比较外设
void OCMP1_Enable (void)
{
    OC1CONSET = _OC1CON_ON_MASK; //输出比较外设使能位
}

//禁止输出比较外设
void OCMP1_Disable (void)
{
    OC1CONCLR = _OC1CON_ON_MASK; //输出比较外设使能位
}

//获取只读占空比寄存器值
uint16_t OCMP1_CompareValueGet (void)
{
    return (uint16_t)OC1R; //只读占空比寄存器值
}

//设置缓冲寄存器值(占空比)
void OCMP1_CompareSecondaryValueSet (uint16_t value)
{
    OC1RS = value; //缓冲寄存器值
}

//获取缓冲寄存器值(占空比)
uint16_t OCMP1_CompareSecondaryValueGet (void)
{
    return (uint16_t)OC1RS; //缓冲寄存器值
}

//
void OCMP1_CallbackRegister(OCMP_CALLBACK callback, uintptr_t context)
{
    ocmp1Obj.callback = callback;

    ocmp1Obj.context = context;
}

//中断服务函数
void OUTPUT_COMPARE_1_InterruptHandler (void)
{
    IFS0CLR = _IFS0_OC1IF_MASK;    //Clear IRQ flag

    if( (ocmp1Obj.callback != NULL))
    {
        ocmp1Obj.callback(ocmp1Obj.context);
    }
}




占空比调节函数

//占空比调节函数
int tempvalue=100;
int flag=1;
void PWM_Modify(void)
{
    if(flag==1)
    {
        if(tempvalue<15000)
        {
            tempvalue+=30;
        }
        else
        {
            flag=0;
        }
    }

    if(flag==0)
    {
        if(tempvalue>100)
        {
            tempvalue-=30;
        }
        else
        {
            flag=1;
        }
    }

    OCMP1_CompareSecondaryValueSet(tempvalue);
}


使用特权

评论回复
6
kxsi|  楼主 | 2021-8-9 13:34 | 只看该作者
实验验证

点击编译按钮,编译提示BUILD SUCCESSFUL,点击烧录,提示Programming/Verify complete,开发板上的LED灯呈呼吸灯变化。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

44

主题

3309

帖子

2

粉丝