PIC 定时器创建 PWM

问题描述 投票:0回答:1

我正在尝试在 PIC18F13k22 中使用timer0模块。

我想要做的就是打开 LED,然后在

TMR0IF == 1
时关闭,并在 PROTEUS 中对其进行模拟。这是一场斗争,我确信我只是错过了一些简单的东西。

我已经使用了延迟功能,并成功地打开和关闭了不同的LED。但现在尝试使用定时器,LED 亮起,但保持亮起状态,并且模拟没有其他变化。我尝试过使用

PORTBbits.RB4
并且同样没有发生任何变化。我正在使用 PROTEUS 8 和 MPLAB X IDE。

LED 通过 220R 电阻连接到引脚 RB4/LB4 和 GND。

void main(void)
{
    TRISB = 0;
    PORTB = 0;
    T0CON = 0x07;   
    T0CONbits.T08BIT = 1;
    T0CONbits.T0PS = 0b111;
    T0CONbits.PSA = 0;
    T0CONbits.T0SE = 1;
    INTCONbits.TMR0IE = 1;
    T0CONbits.T0CS = 0;
    TMR0H = 0xFF;
    TMR0L = 0x00;
    T0CONbits.TMR0ON = 1;
    
    while (1)
    {
        LATBbits.LB4 = 1;

        if (TMR0IF == 1)
        {
            LATBbits.LB4 = 0;
            TMR0IF = 0;
            T0CONbits.TMR0ON = 0;
        }
    }
}
c timer microcontroller pic led
1个回答
0
投票

实际上 LED 发生了变化,但我们看不到,因为变化发生得太快了。让我们先编写

while
循环的逐步文本算法,看看会发生什么。

  1. 初始化系统
  2. 将 B4 引脚设置为高电平 -
    while
    循环从这里开始
  3. 定时器溢出?
  4. 否,则转到步骤 1(保持将 B4 引脚设置为高电平)
  5. 是的,将 B4 引脚设置为低电平,清除标志,关闭定时器并转到步骤 1(保持将 B4 引脚设置为高电平)

您在上面的步骤中看到了什么吗?尤其是第4步?
B4实际上设置为低电平,但是经过一些指令后,B4又设置回高电平!
如果我们假设您使用 4 MHz 的振荡器频率,则指令周期时间将为 1/(4000000/4) = 1 微秒。考虑到该指令周期时间,在将 B4 设置为低状态和将 B4 设置回高状态之间只有 2 条指令。也就是说,如果我们计算汇编分支指令,那么只有 2 条可见指令,总共 4 条指令,这样流程就从

while
循环继续进行。 4 条指令使输出状态变化之间有 4 微秒的延迟,使其对我们来说非常不可见。

此外,代码的逻辑对于实现您的目标来说有些问题。如果你想在定时器溢出后关闭LED并直观地看到效果,你不应该无限循环。方法如下:

// Set B4 high once
LATBbits.LB4 = 1;

// Now wait for the Timer to overflow
while(TMR0IF == 0)
 ;

// If the flow reached here, then timer has overflowed
TMR0IF = 0;
T0CONbits.TMR0ON = 0;
// Set B4 low
LATBbits.LB4 = 0;

// Halt here
while(1)
 ;

如果您的要求意味着您要循环,那么此代码不完整,无法完成这项工作。如果我们考虑您的评论:

我试图让它关闭,以响应当 TMR0H 溢出到 TMR0L 的值时触发的溢出标志。然后我希望计时器模块也关闭以节省电量以了解此功能。

您可以让处理器进入睡眠状态以节省电量。那么带有循环的代码将完成如下:

while (1)
{
    LATBbits.LB4 = 1;

    if (TMR0IF == 1)
    {
        LATBbits.LB4 = 0;
        TMR0IF = 0;
        T0CONbits.TMR0ON = 0;
        
        // Put the processor to sleep (power saving)
        SLEEP();
    }
}

但是这一次,当处理器从省电状态唤醒时,LED 会亮起,但不会关闭,因为定时器被禁用。因此计时器应该保持运行。您不必关心定时器,因为当系统通过睡眠指令进入省电状态时,定时器的振荡器电源将自动切断,并且定时器无法继续在睡眠状态下运行。除非另有说明,否则您不会通过 IO 引脚从外部向定时器时钟供电。
数据表中,第 9.4 节:

由于 Timer0 在休眠模式下关闭,TMR0 中断无法将处理器从休眠状态唤醒

即使不使用中断,定时器关闭也是有效的。因此,我们可以省略禁用计时器以获得所需的行为。最终代码如下:

while (1)
{
    LATBbits.LB4 = 1;

    if (TMR0IF == 1)
    {
        LATBbits.LB4 = 0;
        TMR0IF = 0;
        
        // Put the processor to sleep (power saving)
        SLEEP();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.