1、PIC32参考资源

PIC32系列参考手册 中文版  链接地址:PIC32系列参考手册 第16章 输出比较

image.png

2、脉宽调制模式介绍

当控制位 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 周期边界处置为有效。

3、输出比较模块配置为 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。

4、PWM 输出波形

image.png

带故障保护输入引脚的 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输出时序图

image.png

I/O 引脚控制

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

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

image.png

节能和调试模式下的操作

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 寄存器值不受影响。

5、PWM脉宽调整模式Harmony配置

1、在Project Graph界面中添加定时器TMR2以及输出比较OCMP1,并配置定时器(可参考前面文章配置,不赘述);

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

image.png

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

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

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

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

2、写修改占空比函数;

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

6、具体代码分析

文件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);
}

7、实验验证

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

image.png————————————————

版权声明:本文为CSDN博主「Huangtop」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Huangtop/article/details/119390495