carlsun 发表于 2020-7-10 10:40:27

分享:新唐的51单片机用定时器1模拟PWM

本帖最后由 carlsun 于 2020-7-10 18:08 编辑

近来一个案子需要用到呼吸灯(渐亮渐暗的那种)。画板时没注意到,这组灯的IO非PWM输出口,于是用定时器1模拟了一下PWM。本身不用定时器以前也有做过用延时方式模拟。但是这个案子里呼吸灯工作还有蛮多其他事情要做,所以放到定时器中断里,以减少对其它指令的影响。
由于本人泥腿子出身,套路,思路都是自己琢磨的。所以仅供参考。肯定有其它方便很多的方式实现这一功能。请无意中看到本文的高手勿喷。欢迎指点。旨在给学习单片机的同学参考一下而已。词不达意,不啰嗦。

void Timer1_ISR (void) interrupt 3
{
    TR1 = 0;               //定时器工作在0/1模式下时,一定记得:在读写TH0/TL0时一定要先清零TR0,使计时关掉后再读写;
    TH1 = th1_tmp ;       
    TL1 = tl1_tmp ;                      //加载初值
        /*================================================================
    多组呼吸灯用模拟PWM来实现,此程序用来自动变换模拟PWM的DUTY,
    参数中:hxd_duty代表呼吸的DUTY,此参数以每3MS变化一次的速度在0~100与100~0之间变化,变化一个
    周期为6秒,即按客户要求六秒呼吸一次       
        ====================================================================*/
        if(hxd_status)         //呼吸灯
        {
                hxd_time++;          //呼吸计时               
                if(hxd_time >= 1500)   //一次0.02MS,1500次3MS,加100次,3秒,减100次3秒,一个回合6秒
                {
                        hxd_time = 0;
                        if(hxd_up)      //渐亮标志
                        {
                                hxd_duty++;   //渐亮
                                if(hxd_duty >= 100)   //亮到100,
                                {
                                  hxd_duty = 100;   
                                        hxd_up   =   0;
                                }
                                else
                                {
                                  hxd_duty--;      //渐暗
                                        if(hxd_duty <= 1)
                                        {
                                          hxd_duty = 1;
                                                hxd_up   = 1;
                                        }
                                }
                        }
                }
                hx_tim++;      //0.02mS自增一次
                if(hx_tim >= 100){hx_tim = 0;}                 //两MS一个周期:500HZ
                if(hx_tim < hxd_pwm) {charge_led = 1;} //在周期内,时间没有到DUTY,灯亮
                else {charge_led = 0;}               
      
        }
        TR1 = 1;                  //加载完成后继续计时
}

carlsun 发表于 2020-7-10 10:49:41

void Timer0_ISR (void) interrupt 3    :应该是timer1

armok. 发表于 2020-7-10 10:52:54

打赏!

庆祝论坛“打赏”功能实施, 现在开始发技术主题,可以获得打赏
https://www.amobbs.com/thread-5735948-1-1.html

carlsun 发表于 2020-7-10 11:07:37

armok. 发表于 2020-7-10 10:52
打赏!

庆祝论坛“打赏”功能实施, 现在开始发技术主题,可以获得打赏


{:titter:} 多谢莫大。第一个帖就收到莫大的打赏。

carlsun 发表于 2020-7-14 11:34:53

这个有问题。调试好的看下面
void Timer1_ISR (void) interrupt 3
{
    TR1 = 0;               //定时器工作在0/1模式下时,一定记得:在读写TH0/TL0时一定要先清零TR0,使计时关掉后再读写;
    TH1 = th1_tmp ;       
    TL1 = tl1_tmp ;                      //加载初值
        /*================================================================
    多组呼吸灯用模拟PWM来实现,此程序用来自动变换模拟PWM的DUTY,
    参数中:hxd_duty代表呼吸的DUTY,此参数以每3MS变化一次的速度在0~100与100~0之间变化,变化一个
    周期为6秒,即按客户要求六秒呼吸一次       
        ====================================================================*/
        if(hxd_status)         //呼吸灯
        {
                hxd_time++;          //呼吸计时               
                if(hxd_time >= 1500)   //一次0.02MS,1500次3MS,加100次,3秒,减100次3秒,一个回合6秒
                {
                        hxd_time = 0;
                        if(hxd_up)      //渐亮标志
                        {
                                hxd_duty++;   //渐亮
                                if(hxd_duty >= 100)   //亮到100,
                                {
                                  hxd_duty = 100;   
                                        hxd_up   =   0;
                                }
                        }
                        else
                        {
                                hxd_duty--;      //渐暗
                                if(hxd_duty <= 1)
                                {
                                        hxd_duty = 1;
                                        hxd_up   = 1;
                                }
                        }
                }
                hxd_tim++;      //0.02mS自增一次
                if(hxd_tim >= 100){hxd_tim = 0;}                 //两MS一个周期:500HZ
                if(hxd_tim <= hxd_duty) {charge_led = 1;} //在周期内,时间没有到DUTY,灯亮
                else {charge_led = 0;}               
        }
       
        TR1 = 1;                  //加载完成后继续计时
}

lnso 发表于 2020-10-30 22:06:53

定个标志位
页: [1]
查看完整版本: 分享:新唐的51单片机用定时器1模拟PWM