打印
[技术问答]

定时器任意占空比pwm

[复制链接]
593|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wwppd|  楼主 | 2023-5-21 14:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#include < reg52.h >
    sbit PWMOUT = P1 ^ 7; //方波输出通道
sbit KEY1 = P3 ^ 0;
sbit KEY2 = P3 ^ 1;
sbit KEY3 = P3 ^ 2;
unsigned char HighRH = 0; //高电平重载值的高字节
unsigned char HighRL = 0; //高电平重载值的低字节
unsigned char LowRH = 0; //低电平重载值的高字节
unsigned char LowRL = 0; //低电平重载值的低字节
unsigned char KeySta[4] = { //按键的当前状态
    1, 1, 1, 1
};
void ConfigPWM(unsigned int fr, unsigned char dc); //启动PWM,fr是频率,dc为占空比
void ClosePWM(); //关闭方波输出
void KeyScan(); //按键扫描函数,需在定时中断中调用
void KeyDriver(); //按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用

void main() {
        unsigned int i;
        EA = 1; //开总中断
        while (1) {
            //ConfigPWM(100, 5);                //频率100Hz,占空比10%
            for (i = 0; i < 40000; i++); //不断发送ConfigPWM中的方波
            //ClosePWM();      
            KeyScan();
            KeyDriver();
        }
    }
    /* 配置并启动PWM,fr-频率,dc-占空比 */
void ConfigPWM(unsigned int fr, unsigned char dc) {
        unsigned int high, low;
        unsigned long tmp;
        tmp = (11059200 / 12) / fr; //计算一个周期所需的计数值
        high = (tmp * dc) / 100; //计算高电平所需的计数值
        low = tmp - high; //计算低电平所需的计数值
        high = 65536 - high + 12; //计算高电平的重载值并补偿中断延时
        low = 65536 - low + 12; //计算低电平的重载值并补偿中断延时
        HighRH = (unsigned char)(high >> 8); //高电平重载值拆分为高低字节
        HighRL = (unsigned char) high;
        LowRH = (unsigned char)(low >> 8); //低电平重载值拆分为高低字节
        LowRL = (unsigned char) low;
        TMOD &= 0xF0; //清零T0 的控制位
        TMOD |= 0x01; //配置T0 为模式1
        TH0 = HighRH; //加载T0 重载值
        TL0 = HighRL;
        ET0 = 1; //使能T0 中断
        TR0 = 1; //启动T0
        PWMOUT = 1; //输出高电平
    }
    /* 关闭PWM */
void ClosePWM() {
        TR0 = 0; //停止定时器
        ET0 = 0; //禁止中断
        PWMOUT = 0; //输出低电平
    }
    /* 按键扫描函数,需在定时中断中调用 */
void KeyScan() {
        unsigned char i;
        static unsigned char keybuf[4] = { //按键扫描缓冲区
            0xFF, 0xFF, 0xFF, 0xFF
        };
        //按键值移入缓冲区
        keybuf[0] = (keybuf[0] << 1) | KEY1; //按键按下的时候,KEY会变成0XFF,使得keybuf = 0x00
        keybuf[1] = (keybuf[1] << 1) | KEY2;
        keybuf[2] = (keybuf[2] << 1) | KEY3;
        //消抖后更新按键状态
        for (i = 0; i < 3; i++) {
            if (keybuf[i] == 0x00) { //连续8 次扫描值为0,即16ms 内都是按下状态时,可认为按键已稳定的按下
                KeySta[i] = 0;
            } else if (keybuf[i] == 0xFF) { //连续8 次扫描值为1,即16ms 内都是弹起状态时,可认为按键已稳定的弹起
                KeySta[i] = 1;
            }
        }
    }
    /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver() {
        unsigned char i;
        static unsigned char backup[4] = {
            1, 1, 1, 1
        }; //备份按键扫描
        for (i = 0; i < 4; i++) //循环检测4 个按键
        {
            if (backup[i] != KeySta[i]) //检测按键动作
            { //如果不一样,代表该按键已经被按下
                if (backup[i] != 0) //按键按下时执行动作
                {
                    if (i == 0) //按键为0,旋转-90
                    {
                        ConfigPWM(50, 3); //频率50Hz,20ms,占空比10%
                        for (i = 0; i < 40000; i++);
                        ClosePWM();

                    } else if (i == 1) //按键为1,旋转0
                    {
                        ConfigPWM(50, 8); //频率50Hz,20ms,占空比3%
                        for (i = 0; i < 40000; i++);
                        ClosePWM();
                    } else if (i == 2) //按键为0,旋转90
                    {
                        ConfigPWM(50, 13); //频率50Hz,20ms,占空比8%
                        for (i = 0; i < 40000; i++);
                        ClosePWM();
                    }
                }
                backup[i] = KeySta[i]; //刷新前一次的备份值
            }
        }
    }
    /* T0 中断服务函数,产生PWM 输出 */
void InterruptTimer0() interrupt 1 {
    //如果一开始是高,那么中断到了之后输出低即可完成PWM
    if (PWMOUT == 1) //当前输出为高电平时,装载低电平值并输出低电平
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }
    //如果一开始是低,那么中断到了之后输出高即可开始产生PWM
    else //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}


使用特权

评论回复
沙发
tpgf| | 2023-6-5 15:32 | 只看该作者
所有的定时器都可以实现任意的占空比吗?还是说必须使用特殊的定时器啊

使用特权

评论回复
板凳
nawu| | 2023-6-5 16:13 | 只看该作者
tpgf 发表于 2023-6-5 15:32
所有的定时器都可以实现任意的占空比吗?还是说必须使用特殊的定时器啊

好像不可以吧 至少普通的定时器不能实现任意占空比

使用特权

评论回复
地板
aoyi| | 2023-6-5 16:27 | 只看该作者
为什么我看到有的帖子说不能实现百分百占空比呢

使用特权

评论回复
5
zljiu| | 2023-6-5 16:47 | 只看该作者
通常情况下我们如何消除pwm的死区部分呢

使用特权

评论回复
6
gwsan| | 2023-6-5 16:59 | 只看该作者
我们使用普通的引脚可以模拟这种pwm的输出吗

使用特权

评论回复
7
tfqi| | 2023-6-5 17:23 | 只看该作者
gwsan 发表于 2023-6-5 16:59
我们使用普通的引脚可以模拟这种pwm的输出吗

不如专用的模块方便 只需要配置就行 你的想法还得io进行配合

使用特权

评论回复
8
belindagraham| | 2023-6-6 15:22 | 只看该作者
怎么用定时器中断控制pwm的占空比

使用特权

评论回复
9
pixhw| | 2023-6-7 13:10 | 只看该作者
调速占空比根据实际情况如何调节?

使用特权

评论回复
10
modesty3jonah| | 2023-6-7 21:32 | 只看该作者
通过修改计数值和重载值,可以动态地改变PWM信号的占空比

使用特权

评论回复
11
jtracy3| | 2023-6-8 22:18 | 只看该作者
根据所需的占空比和定时器的计数时间,计算出相应的计数值和重载值。

使用特权

评论回复
12
burgessmaggie| | 2023-6-8 23:16 | 只看该作者
用51单片机定时器中断产生两路占空比可调的pwm波形

使用特权

评论回复
13
mattlincoln| | 2023-6-10 10:17 | 只看该作者
用定时器怎么调节占空比?               

使用特权

评论回复
14
modesty3jonah| | 2023-6-10 10:48 | 只看该作者
如何在每周期修改pwm占空比               

使用特权

评论回复
15
10299823| | 2023-6-10 11:31 | 只看该作者
选择一款合适的定时器,并进行相应的初始化配置。其中,定时器的计数时间需要根据实际需求进行设置,一般可以选择10us或20us左右的时间间隔。

使用特权

评论回复
16
everyrobin| | 2023-6-10 11:41 | 只看该作者
基本原理是使用定时器来产生固定频率的脉冲信号,通过改变占空比来控制输出信号的电平。

使用特权

评论回复
17
jtracy3| | 2023-6-10 12:07 | 只看该作者
在定时器中断处理函数中不断更新计数值和重载值,从而产生固定频率和任意占空比的PWM信号。

使用特权

评论回复
18
tabmone| | 2023-6-10 12:20 | 只看该作者
定时器任意占空比PWM技术是一种常见的工业控制技术,它可以实现电机调速、LED调光等应用。

使用特权

评论回复
19
chenqianqian| | 2023-6-11 19:37 | 只看该作者
任意占空比是通过改变计时值实现的。

使用特权

评论回复
20
georgeliu2016| | 2023-7-1 14:01 | 只看该作者
点呼吸灯效果杠杠的。

使用特权

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

本版积分规则

44

主题

2721

帖子

2

粉丝