zanjun 发表于 2024-3-27 14:38:19

关于PWM

STC8A8K32S4单片机,增强15位PWM
PWMC=99
时钟=定时器T2=30ms,
归零中断改高低电平触发点,下面是部分数据
1、PWM2T2=0,PWM2T1=100,PWM3T2=0,PWM3T1=0,
2、PWM2T2=0,PWM2T1=95,PWM3T2=95,PWM3T1=0,
3、PWM2T2=0,PWM2T1=90,PWM3T2=90,PWM3T1=0,
4、PWM2T2=0,PWM2T1=85,PWM3T2=85,PWM3T1=0,
5、PWM2T2=0,PWM2T1=80,PWM3T2=80,PWM3T1=0,
期望是,
1、PWM2开100个时钟,PWM3关
2、PWM2先开95个时钟,然后PWM3开5个时钟
3、PWM2先开90个时钟,然后PWM3开10个时钟
4、PWM2先开85个时钟,然后PWM3开15个时钟
5、PWM2先开80个时钟,然后PWM3开20个时钟
结果是1/2/3/4,只有PWM2开,
到第五个中断,才正常,
折腾了好几天,百思不得其解,

zanjun 发表于 2024-3-27 15:08:30

本帖最后由 zanjun 于 2024-3-27 15:20 编辑




//30毫秒@22.1184MHz,PWM时钟=30ms,适应电磁阀开关响应时间
void Init_Timer2(void)               
{
        AUXR &= B11110011;                //T2定时方式,12T
        T2L = 0x00;                                                //设置定时初值
        T2H = 0x28;                                                //设置定时初值,30ms
        IE2 &= B11111011;                        //关定时器2中断
        AUXR |= B00010000;                //定时器2开始计时
}


//时钟T2=30ms,周期3000ms,计数100次,3000ms归零中断中修改4路PWM的高低电平位置和时间
//4路增强PWM,PWM2、PWM3、PWM4、PWM5
void Init_PWM(void)
{

        Init_Timer2();

        //在 PWM计数器计数的过程中, ENPWM 控制位被关闭时, PWM 计数会立即停止,当再次使能 ENPWM
        //控制位时, PWM 的计数会从 0 开始重新计数,而不会记忆 PWM 停止计数前的计数值
        PWMCR = 0;                                                        //关闭PWM波形发生器,关闭归零中断
        PWMCFG = 0;                                                 //清中断标志
        PWMIF = 0;                                                        //清反转中断标志
        PWMFDCR = 0;                                                //异常检测关


        P_SW2 |= B10000000;                        //访问XFR

        //PWM2,PWM3,PWM4,PWM5
        PWMCKS = B00010000;                        //PWM 时钟为T2溢出脉冲,30ms,

       
        PWMCH = 0;
        PWMCL = 99;                                                        //设置 PWM 周期为 100 个 PWM 时钟,3000ms,//2500ms


        PWM2CR = B10000000;                        //使能PWM2口输出(推挽),初始低电平,关通道中断,关触发点中断
        PWM2HLD = B00000000;                //正常输出,可以强制高电平,或低电平
        PWM3CR = B10000000;                               
        PWM3HLD = B00000000;                       

       

        //设定每个周期中输出PWM波形的2个触发点
        //当计数值=T1设定值,PWM输出低电平
        //当计数值=T2设定值,PWM输出高电平
        //当计数值=T1=T2,只输出低电平

        //阀A
        PWM2T2= PWMT2;                        //PWM2 在计数值为 T2 地方输出高电平,
        PWM2T1= PWMT1;                        //PWM2 在计数值为 T1 地方输出低电平

        //阀B
        PWM3T2= PWMT2;                        //PWM3 在计数值为 T2 地方输出高电平,
        PWM3T1= PWMT1;                        //PWM3 在计数值为 T1 地方输出低电平
                       

        P_SW2 &= B01111111;                        //恢复访问XRAM
       
        PWMCR = B11000000;                        //开启PWM波形发生器,和归零中断
        EA = 1;
}



void PWM_Interrupt(void) interrupt 22
{

      PWMCFG = 0;                                       //清中断标志

      PWMIF = 0;                                        //C7IF,C6IF...C0IF
      P_SW2 |= B10000000;                //访问XFR
      
      //阀A
      PWM2T2= PWMT2;                //PWM2 在计数值为 T2 地方输出高电平,
      PWM2T1= PWMT1;                //PWM2 在计数值为 T1 地方输出低电平
      //PWM2T2L= 99;                //电磁阀可以通
      //PWM2T1L= 0;

      //阀B
      PWM3T2= PWMT2;                //PWM3 在计数值为 T2 地方输出高电平,
      PWM3T1= PWMT1;                //PWM3 在计数值为 T1 地方输出低电平
      //PWM3T2L= 90;                //PWM2 在计数值为 T2 地方输出高电平,
      //PWM3T1L= 0;                //PWM2 在计数值为 T1 地方输出低电平
      
      P_SW2 &= B01111111;                //恢复访问XRAM
      
      //置标志,向上位机要下一个数据
      PWMWantDataFlag = 1;
}

PWMT2[],PWMT1[],数组保存着下一个PWM触发点数据

梁工 发表于 2024-3-27 16:03:51

每路PWM都可以单独设置输出高低电平的时刻。
PWM中断里设置的匹配值T1、T2,不影响当前的周期,下一个周期起作用。

zanjun 发表于 2024-3-27 17:00:40

本帖最后由 zanjun 于 2024-3-27 17:02 编辑

梁工 发表于 2024-3-27 16:03
每路PWM都可以单独设置输出高低电平的时刻。
PWM中断里设置的匹配值T1、T2,不影响当前的周期,下一个周期 ...
梁工,你好,
如果有时间,麻烦看看我的程序,我在中断里改T1和T2,有时不起作用,
最上面,说明了不正常的情况

zanjun 发表于 2024-3-27 17:10:57

zanjun 发表于 2024-3-27 17:00
梁工,你好,
如果有时间,麻烦看看我的程序,我在中断里改T1和T2,有时不起作用,
最上面,说明了不正常 ...

STC8A8K32S4单片机,增强15位PWM
PWMC=99
时钟=定时器T2=30ms,
我对PWM归零中断的理解是这样的,
设PWMC=99,当计数=99,计数器归零,发生归零中断,此时还需要一个30ms时钟,才真正完成一个PWM周期,也就是完整周期=100x30=3000ms
不知道,是不是这样

梁工 发表于 2024-3-27 18:36:28

zanjun 发表于 2024-3-27 17:10
STC8A8K32S4单片机,增强15位PWM
PWMC=99
时钟=定时器T2=30ms,


周期计数计到设定值,下一个时钟就归0,同时装载T1、T2值,并发起中断。
类似应用可以参考:
1、输出SPWM,就是每个归0中断都改变占空比。
2、输出声音,就是每个归0中断都改变占空比。
完全没有问题的。

zanjun 发表于 2024-3-27 20:25:53

梁工 发表于 2024-3-27 18:36
周期计数计到设定值,下一个时钟就归0,同时装载T1、T2值,并发起中断。
类似应用可以参考:
1、输出SPWM ...

谢谢,梁工
目前,现象就是上面说的那样
1、目前,怀疑单片机,STC8A8K32S4,目前似乎停产了,明天试试STC8A8K48D4
2、改触发点的值,一些特殊值,如T2=0,T1=100,PWMC=99

梁工 发表于 2024-3-27 21:23:23

zanjun 发表于 2024-3-27 20:25
谢谢,梁工
目前,现象就是上面说的那样
1、目前,怀疑单片机,STC8A8K32S4,目前似乎停产了,明天试试ST ...

本来不想再浪费时间去测试的,因为类似功能用得实在太多了。

但还是忍不住花时间测试了,为了观察明显,我Timer2用10ms,用30ms一样的效果,就是慢3倍。
占空比变化我也加大一些,你可以自己改回你要的占空比。

//        u16        code T_PWM = {100, 95, 90, 85, 80};   //用户要求,但是观察不明显
        u16        code T_PWM = { 80, 70, 60, 50, 40};


先看STC8A8K64S4A12,一上电P2.1有输出一个几ms的高电平,这个型号IO上电是准双向口输出高电平的。之后5个脉冲都正常:


再看STC8A8K64D4的,一切正常:






zanjun 发表于 2024-3-27 22:28:15

梁工 发表于 2024-3-27 21:23
本来不想再浪费时间去测试的,因为类似功能用得实在太多了。

但还是忍不住花时间测试了,为了观察明显, ...

再次感谢,明天试试你的程序,

zanjun 发表于 2024-3-29 17:00:36

梁工 发表于 2024-3-27 21:23
本来不想再浪费时间去测试的,因为类似功能用得实在太多了。

但还是忍不住花时间测试了,为了观察明显, ...

梁工好,
先设好第一组T1/T2,再启动PWM,此时会立即产生一个归零中断,在中断中设置第二组T1/T2,你上面说,不会影响上一个周期的T1/T2,这个T1/T2,还有影子寄存器?
除去启动那次的归零中断,之后的中断就好理解了,计数到设定值,产生中断,改T1/T2,前一个周期的T1/T2,已经没有用了。
页: [1] 2
查看完整版本: 关于PWM