嵌入式学习小组
直播中

叹久

9年用户 841经验值
擅长:可编程逻辑 光电显示 接口/总线/驱动
私信 关注

N76E003 PWM如何捕获占空比?

我在使用 n76e003做占空比捕获的时候,发现频率5K 占空比0.1%的时候 捕获会出错误。有没有大佬有成熟的占空比捕获的程序给我参考一下。

回帖(1)

fansz

2024-1-11 11:34:08
实现PWM占空比捕获的方法主要有两种:外部计数、定时器计数。对于N76E003来说,它只有一个16位定时器,因此我们可以采用定时器计数的方法实现PWM占空比捕获。

具体来说,我们可以通过如下步骤来实现:

1. 配置定时器为PWM输入模式,并启用定时器中断。

2. 在定时器中断中读取定时器计数值,并将其存储到缓冲区中。

3. 当检测到PWM信号下降沿时,计算两个相邻的计数值之间的差值,得到占空比。

需要注意的是,在使用定时器计数来实现PWM占空比捕获时,占空比的精度和捕获频率都与定时器的分频值有关,因此需要根据具体应用场景进行适当的配置。另外,由于N76E003的定时器只有16位,因此在高速PWM应用场景下可能会出现溢出的情况,需要额外进行处理。

下面是一份具体实现PWM占空比捕获的代码供参考:

```c
#include
#include
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"

#define PWM_PIN P12
#define TIMER_PRESCALER 48 // 定时器分频值,可根据具体应用场景调整
#define TIMER_COUNT_MAX 0xFFFF // 定时器最大计数值,根据定时器分频值和系统时钟频率计算得到

volatile uint16_t high_time, low_time, period_time;
volatile uint16_t timer_count_buf[2], timer_overflow_cnt;

void timer_isr(void) interrupt 1
{
    static uint8_t idx = 0;

    if (TF0) // 定时器溢出中断
    {
        timer_overflow_cnt++;
    }

    timer_count_buf[idx] = TH0 << 8 | TL0; // 读取定时器计数值

    if (idx == 1) // 检测到PWM下降沿
    {
        high_time = timer_count_buf[1] - timer_count_buf[0];
        low_time = TIMER_COUNT_MAX - high_time;
        period_time = TIMER_COUNT_MAX * timer_overflow_cnt + timer_count_buf[1] + 1;

        timer_overflow_cnt = 0; // 重置计数器溢出计数值
    }

    idx = (idx + 1) % 2;
}

int main(void)
{
    TIMER0_MODE1_ENABLE; // 配置定时器为16位计数模式
    TIMER0_PWM_INPUT_ENABLE; // 配置定时器为PWM输入模式
    TIMER0_INTERRUPT_ENABLE; // 启用定时器中断

    PWM_PIN = 1; // 使能PWM输入引脚

    while (1)
    {
        // do something
    }

    return 0;
}
```

在上面的代码中,我们使用定时器0来实现PWM占空比捕获,定时器模式为16位计数模式,采用PWM输入模式。在定时器中断中,我们读取定时器计数值,并在检测到PWM下降沿时计算两个相邻的计数值之间的差值,从而得到PWM的占空比和周期时间。值得注意的是,在计算周期时间时,我们需考虑到计数器溢出的情况,因为当PWM信号周期非常长时,可能会出现多次计数器溢出的情况。因此,我们需要在中断处理函数中记录计数器溢出的次数,并将其乘以定时器的最大计数值加上当前计数值,从而得到准确的周期时间。

希望以上代码能对你有所帮助。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分