找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 20069|回复: 14
打印 上一主题 下一主题
收起左侧

分享两种STC15定时器模拟PWM的方法

  [复制链接]
跳转到指定楼层
楼主
刚刚搜了一下,发现坛里还没有这样分析PWM的帖子,然后发了一个。
手电LED控制或马达转速控制都离不开PWM,下面有两种方法可以模拟PWM的。如果不正确希望各位指教。



//用定时器装载方式模拟PWM,这种方法PWM周期短,分辩率高,1毫秒内可以做到11000格分辩率,
//缺点:高低电平会的百分之一格不受控制
#include "reg51.h"
#include<intrins.h>
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr AUXR      = 0x8e;//辅助寄存器
sbit P20   = P2^0; //PWM输出脚   
sbit P17   = P1^7; //按键增量
sbit P16   = P1^6; //按键减少   
unsigned int HIGHDUTY,LOWDUTY;//高低时间存放寄存器
unsigned char num;//记录分辩个数
bit flag;
void Delayms(unsigned int ms)//1mS@11.0592MHz
{unsigned char i, j;
        while(ms--)
        {        _nop_();
        _nop_();
        _nop_();
                i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);}
}
void main()
{  
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        AUXR = 0x80;        //定时器0为1T模式
        TMOD &= 0xf0;       //设置定时器0为模式0(16位自动重装载)
        TR0 = 1;            //定时器0开始计时
        ET0 = 1;            //使能定时器0中断
        EA = 1;
        HIGHDUTY=54477+(11058/255)*num;
        LOWDUTY=54477+(11058/255)*(256-num);
    while (1)
        {
       if(!P17)
        {
        Delayms(90);         
         if(!P17)
        {
        //while(!P17);
        num++;             //按制分辩率,uchar字符型范围0~255格
        HIGHDUTY=54477+(11058/255)*num;/*求占空比高位,0xD4CD = 54477;
        程序装载初始值54477一直跑到65535共花时间1000微秒,
        65535-54477=11058,11058就是1000微秒。
        (11058再除以分辩率255)等于一格所需的时间,要点空比高位多少就剩多少 */
        LOWDUTY=54477+(11058/255)*(255-num);//求占空比高位低位
         }
       }
         if(!P16)
        {
        Delayms(90);         
         if(!P16)
        {
        //while(!P16);
        num--;                        
        HIGHDUTY=54477+(11058/255)*num;
        LOWDUTY=54477+(11058/255)*(255-num);//
         }
       }
    }
}
void tm0() interrupt 1//定时器0中断服务程序
{
   flag = !flag;
    if (flag)//反转标志去执行高低电平的时间   
    {
        TL0 = HIGHDUTY;                //设置定时初值
        TH0 = HIGHDUTY>>8;//设置定时初值
        P20=1;//输出高电位
    }
    else
    {
        TL0 = LOWDUTY;                //设置定时初值
        TH0 = LOWDUTY>>8;        //设置定时初值
        P20=0;//输出低电位
    }
}

---------------------------------------------------------------------------------------------------------------------------


//用定时器计算方式模拟PWM,高低电平容易控制
//缺点:这种方法周期能做到1KHz以内,大多数马达或调光设置会闪烁
#include "reg51.h"
#include<intrins.h>
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfr AUXR      = 0x8e;//辅助寄存器
sbit P20   = P2^0; //PWM输出脚   
sbit P17   = P1^7; //按键增量
sbit P16   = P1^6; //按键减少   
unsigned char num;//记录分辩个数
void Delayms(unsigned int ms)                //1mS@11.0592MHz
{unsigned char i, j;
        while(ms--)
        {        _nop_();
        _nop_();
        _nop_();
                i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);}
}
void main()
{   P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    AUXR = 0x80;            //定时器0为1T模式
    TMOD &= 0xf0;           //设置定时器0为模式0(16位自动重装载)
    TR0 = 1;                //定时器0开始计时
    ET0 = 1;                //使能定时器0中断
    EA = 1;
    num=10;  //给初始值
    while (1)
        {
       if(!P17)
        {
        Delayms(10);         
         if(!P17)
        {        
                num++;
         }
       }
        if(!P16)
         {
        Delayms(10);         
         if(!P16)
        {
                num--;
         }
       }
    }
}
void tm0() interrupt 1//定时器0中断服务程序
{ static unsigned char k;
        TL0 = 0xF5;        //设置定时初值 按1T时钟计算,1uS一次
        TH0 = 0xFF;        //设置定时初值 按1T时钟计算,1uS一次
        k++;
        if(k>num)P20=1;//输出高电位
        else P20=0;//输出低电位
}

评分

参与人数 2黑币 +112 收起 理由
catlu + 12
admin + 100 回帖助人的奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:146949 发表于 2017-3-12 23:01 | 只看该作者
终于知道第一种PWM为什么会不受控了。因为定时器内指令执行时间过长超出定时器设定的时间时会导致系统崩溃。
当定时器赋值为TH0=0xFF,TL0=0xFF时,那怕是在定时器内运行很少的指令也很可能会导致指令未执行完就溢出了。
所以如果有人用第一种PWM时,切记赋值不要过大"TH0=0xFF,TL0=0xFF"否则会有问题。。!
回复

使用道具 举报

板凳
ID:167357 发表于 2017-3-13 07:04 | 只看该作者
学习了@@
回复

使用道具 举报

地板
ID:170318 发表于 2017-3-13 14:20 | 只看该作者
谢谢楼主啦!!分享很好
回复

使用道具 举报

5#
ID:175439 发表于 2017-3-28 19:11 | 只看该作者
楼主,你这个我怎么弄不成PWM波呢,反应都没有
回复

使用道具 举报

6#
ID:146949 发表于 2017-3-28 20:16 | 只看该作者
jgp886585 发表于 2017-3-28 19:11
楼主,你这个我怎么弄不成PWM波呢,反应都没有

你用的是什么单片机?我是在STC15W4kK58S4的平台上试的,有两个按键可以调加大的减小占空比。我都在示波器上试过的。你用其他型号的单片机注意有些IO初始化和AUXR寄存器等要设置。
回复

使用道具 举报

7#
ID:175439 发表于 2017-3-29 11:20 | 只看该作者
wosiyabo 发表于 2017-3-28 20:16
你用的是什么单片机?我是在STC15W4kK58S4的平台上试的,有两个按键可以调加大的减小占空比。我都在示波 ...

我是STC15W1K16S,我按照你的第一种方式来弄的,弄了之后灯能点亮,但是怎么弄亮度都不变,谢谢!
回复

使用道具 举报

8#
ID:175439 发表于 2017-3-29 11:44 | 只看该作者
还有楼主,输出脚不需要设置成推挽么?谢谢
回复

使用道具 举报

9#
ID:65956 发表于 2018-11-19 11:51 | 只看该作者
谢谢您的分享,谢谢你的经验分享!
回复

使用道具 举报

10#
ID:499701 发表于 2019-7-5 13:08 | 只看该作者
第二种方法用过,的确频率跑不高,我做的最高才300hz
回复

使用道具 举报

11#
ID:94449 发表于 2020-2-29 10:31 | 只看该作者
wosiyabo 发表于 2017-3-12 23:01
终于知道第一种PWM为什么会不受控了。因为定时器内指令执行时间过长超出定时器设定的时间时会导致系统崩溃 ...

是说第一种方式不好,要用第二种?
回复

使用道具 举报

12#
ID:94449 发表于 2020-2-29 10:37 | 只看该作者
//缺点:高低电平会的百分之一格不受控制

这句怎么理解呢?
回复

使用道具 举报

13#
ID:833307 发表于 2020-11-3 14:06 | 只看该作者
是不是再搞一台示波器,哎 ,小白很迷茫啊
回复

使用道具 举报

14#
ID:833307 发表于 2020-11-3 14:08 | 只看该作者
wosiyabo 发表于 2017-3-12 23:01
终于知道第一种PWM为什么会不受控了。因为定时器内指令执行时间过长超出定时器设定的时间时会导致系统崩溃 ...

回复

使用道具 举报

15#
ID:298713 发表于 2022-8-17 09:12 | 只看该作者
本帖最后由 wjw7680 于 2022-8-17 15:49 编辑

第二个程序根本实现不了PWM,只要中断11次,k值就会超过num,P20=1一直输出高电平。第一个也有问题,定时器初值在TR0=0时对TL0,TH0赋初值才有效。中断内没有TR0=0,没法改变定时器内的TL0,TH0。这个程序估计是直接抄来的,没验证过
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表