huiyong828 发表于 2024-4-6 23:53:03

请教高速高级(HSPWM)模式下怎么实现(频率-占空比)调节相位差180度PWM信号

本帖最后由 huiyong828 于 2024-4-6 23:55 编辑

普通PWM模式下,可以正常输出波形
代码如下:
void      PWMA_config(void)
{
      u8      ccer1;
      u8      ccer2;
      u8      ps;
      u8      eno;

      
      P2M0 = 0xff; P2M1 = 0x00;
      P3M0 = 0x40; P3M1 = 0x00;

      P27 = 0;
      P36 = 0;
      
      P_SW2 |= 0x80;                //SFR enable
      PWMA_ENO    = 0;      // IO输出禁止
      PWMA_IER    = 0;      // 禁止中断
      PWMA_SR1    = 0;      // 清除状态
      PWMA_SR2    = 0;      // 清除状态
      PWMA_CR1    = 0;      // 清除控制寄存器
      PWMA_CR2    = 0;      // 清除控制寄存器
      ccer1 = 0;
      ccer2 = 0;
      ps    = 0;
      eno   = 0;
      PWMA_ISR_En = 0;

      PWMA_PSCRH = 0;                        // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
      PWMA_PSCRL = 5;                // 预分频, PWM时钟 = 12MHz/(11+1)=1MHz
      PWMA_DTR   = 5;                        // 死区时间配置, n=0~127: DTR= n T,   0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
                                                      //                              0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T,   0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
      PWMA_ARRH    = (PWMA_PERIOD-1)/256;      // 自动重装载寄存器,控制PWM周期
      PWMA_ARRL    = (PWMA_PERIOD-1)%256;
      PWMA_ISR_En |= 0x01;                // 使能更新中断

      PWMA_CCMR1= 0x68;                // 通道模式配置, PWM模式1, 预装载允许
      PWMA_CCR1H= pwma1/256;      // 比较值, 控制占空比(高电平时钟数)
      PWMA_CCR1L= pwma1%256;
      ccer1 |= 0x0D;                        // 开启比较输出, 高电平有效    使能PWM1PPWM1N
      ps    |= 1;                              // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1,
      eno   |= 0x03;                        // IO输出允许,bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,bit3: ENO2N,bit2: ENO2P,bit1: ENO1N,bit0: ENO1P
//      PWMA_ISR_En |= 0x02;      // 使能中断

      PWMA_CCMR2 = 0x40;                // 强制输出低
      PWMA_CCR2H = PWMA_PHASE2/256;      // 匹配值
      PWMA_CCR2L = PWMA_PHASE2%256;
      ccer1 |= 0xD0;                        // 开启比较输出, 高电平有效                        使能PWM2PPWM2N
      ps    |= (1<<2);                // 选择IO, 0:选择P1.2 P1.3, 1:选择P2.2 P2.3, 2:选择P6.2 P6.3,
      eno   |= 0x0C;                        // IO输出允许,bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,bit3: ENO2N,bit2: ENO2P,bit1: ENO1N,bit0: ENO1P
      PWMA_ISR_En |= 0x04;      // 使能通道2匹配中断

      PWMA_CCER1= ccer1;      // 捕获/比较使能寄存器1
      PWMA_CCER2= ccer2;      // 捕获/比较使能寄存器2
      PWMA_PS   = ps;                // 选择IO
      PWMA_IER    = PWMA_ISR_En;      //设置允许通道1~4中断处理

      PWMA_BKR    = 0x80;                // 主输出使能 相当于总开关
      PWMA_CR1    = 0x81;                // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
      PWMA_EGR    = 0x01;                //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
      PWMA_ENO    = eno;                // 允许IO输出

      PPWMA= 1;      //PWMA中断设置为最高优先级为3,别的中断优先级都小于3
      PPWMAH = 1;
}


上图波形正常。

工程程序



改为高速PWM模式,按照上述参数配置,运行不正常

void HSPwmConfig(void)
{
      u8      ccer1;
      u8      ccer2;
      u8      ps;
      u8      eno;

      HSPWMA_CFG = 0x03;                        //使能PWMA相关寄存器异步访问功能
      
      //通过异步方式设置PWMA的相关寄存器
      
//      WritePWMA((u8)&PWMA_ENO, 0x00);                        // IO输出禁止
//      WritePWMA((u8)&PWMA_IER, 0x00);                        // 禁止中断
//      WritePWMA((u8)&PWMA_SR1, 0x00);                        // 清除状态
//      WritePWMA((u8)&PWMA_SR2, 0x00);                        // 清除状态
//      WritePWMA((u8)&PWMA_CR1, 0x00);                        // 清除控制寄存器
//      WritePWMA((u8)&PWMA_CR2, 0x00);                        // 清除控制寄存器
      
      WritePWMA((u8)&PWMA_CCER1, 0x00);
      WritePWMA((u8)&PWMA_CCER2, 0x00);
      
      ccer1 = 0;
      ccer2 = 0;
      ps    = 0;
      eno   = 0;
      PWMA_ISR_En = 0;
      
//      WritePWMA((u8)&PWMA_PSCRH, 0x00);                // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
//      WritePWMA((u8)&PWMA_PSCRL, 5);                // 预分频, PWM时钟 = 12MHz/(11+1)=1MHz
      WritePWMA((u8)&PWMA_DTR, 5);                        // 死区时间配置, n=0~127: DTR= n T,   0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
                                                                                                                                                      //                                                      0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T,   0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,      
      WritePWMA((u8)&PWMA_ARRH, (PWMA_PERIOD-1)/256);                        // 自动重装载寄存器,控制PWM周期
      WritePWMA((u8)&PWMA_ARRL, (PWMA_PERIOD-1)%256);               
      PWMA_ISR_En |= 0x01;                // 使能更新中断
      
      WritePWMA((u8)&PWMA_CCMR1, 0x68);                                        // 通道模式配置, PWM模式1, 预装载允许

      WritePWMA((u8)&PWMA_CCR1H, (u8)(pwma1/256));      // 比较值, 控制占空比(高电平时钟数)      
      WritePWMA((u8)&PWMA_CCR1L, (u8)(pwma1%256));      
      ccer1 |= 0x0D;                        // 开启比较输出, 高电平有效    使能PWM1PPWM1N
      ps    |= 1;                              // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1,
      eno   |= 0x03;                        // IO输出允许,bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,bit3: ENO2N,bit2: ENO2P,bit1: ENO1N,bit0: ENO1P
      //      PWMA_ISR_En |= 0x02;      // 使能中断
                        
      WritePWMA((u8)&PWMA_CCMR2, 0x40);                                        // 强制输出低
      WritePWMA((u8)&PWMA_CCR2H, (u8)(PWMA_PHASE2/256));      //设置输出PWM的占空比
      WritePWMA((u8)&PWMA_CCR2L, (u8)(PWMA_PHASE2%256));      

      ccer1 |= 0xD0;                        // 开启比较输出, 高电平有效                        使能PWM2PPWM2N
      ps    |= (1<<2);                // 选择IO, 0:选择P1.2 P1.3, 1:选择P2.2 P2.3, 2:选择P6.2 P6.3,
      eno   |= 0x0C;                        // IO输出允许,bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,bit3: ENO2N,bit2: ENO2P,bit1: ENO1N,bit0: ENO1P
      PWMA_ISR_En |= 0x04;      // 使能通道2匹配中断
      
      WritePWMA((u8)&PWMA_CCER1, ccer1);                        // 捕获/比较使能寄存器1
      WritePWMA((u8)&PWMA_CCER2, ccer2);                        // 捕获/比较使能寄存器2
      PWMA_PS = ps;                                                                                                                // 选择IO               
      
      WritePWMA((u8)&PWMA_IER, PWMA_ISR_En);      //设置允许通道1~4中断处理

      
      WritePWMA((u8)&PWMA_BKR, 0x80);                                        //使能主输出
      WritePWMA((u8)&PWMA_CR1, 0x81);                                        //使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
      WritePWMA((u8)&PWMA_EGR, 0x01);                                        //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
      WritePWMA((u8)&PWMA_ENO, eno);                                        // 允许IO输出
      
}


void PWMA_ISR(void) interrupt PWMA_VECTOR
{


//      u8      sr2;
      sr1 = ReadPWMA(&PWMA_SR1);      //为了快速, 中断标志用一个局部变量处理
      
      WritePWMA((u8)&PWMA_SR1, 0);
      WritePWMA((u8)&PWMA_SR2, 0);
      PWMA_SR2 = 0;
      PWMA_SR1 = 0;
      

//      sr2 = PWMA_SR2;      //为了快速, 中断标志用一个局部变量处理
      sr1 &= PWMA_ISR_En;      //每个通道可以单独允许中断处理

      P36 = ~P36;                              //测试用
      if(sr1 & 0x01)      //更新中断标志
      {
               
                WritePWMA((u8)&PWMA_CCR2H, (u8)(PWMA_PHASE2/256));      // 通道2匹配值
                WritePWMA((u8)&PWMA_CCR2L, (u8)(PWMA_PHASE2%256));      
                WritePWMA((u8)&PWMA_CCMR2, 0x70);                                                                              // 通道模式配置, PWM模式2, 禁止预装载, 匹配时输出高
                B_OutState = 0;
      }

      if(sr1 & 0x04)      //通道2匹配中断标志
      {
                if(!B_OutState)
                {
                        B_OutState = 1;
                        WritePWMA((u8)&PWMA_CCMR2, 0x50);                              // 通道模式配置, 强制为有效电平      
                        WritePWMA((u8)&PWMA_CCR2H, (u8)((PWMA_PHASE2+pwma1)/256));      // 通道2匹配值
                        WritePWMA((u8)&PWMA_CCR2L, (u8)((PWMA_PHASE2+pwma1)%256));      
                        WritePWMA((u8)&PWMA_CCMR2, 0x60);                              // 通道模式配置, PWM模式1, 匹配时输出低电平
                }
                else      WritePWMA((u8)&PWMA_CCMR2, 0x40);                // 通道模式配置, 强制为无效电平      

      }

}

电子DIY小家 发表于 2024-4-7 08:13:40

频率比较高的时候建议直接用带硬件移相的芯片,例如STC8H2K17U

huiyong828 发表于 2024-4-7 08:22:48

本帖最后由 huiyong828 于 2024-4-7 08:24 编辑

频率最高频率10-100KHz,现在用的是STC32G

AI-32位8051 发表于 2024-4-7 10:10:24

RMB0.99 的 USB, STC8H2K08U-45MHz-TSSOP20/SOP16,已开始供货
51世界火热的夏天全面来临 全面 进入 USB 时代 !
硬件USB 支持 仿真/下载, RTC 实时时钟, 年/月/日/时/分/秒
真12位ADC, 144MHz-16位高级PWM新增硬件移相功能
串口1/串口2:
===都支持串口接收硬件超时侦测
===都支持帧错误数据检测和自动地址识别
T11,强大的24位低功耗定时器/系统定时器,支持低功耗唤醒
P1.2口在P5.4口上共享,P1.0/P1.1的全部数字功能可以交换
STC8H2K08U-45MHZ-TSSOP20/SOP16,USB, RMB 0.99
PWM硬件移相的 I/O :PWMAPS5/P1.3, PWMAPS6/P1.5
STC8H2K08U要让51成为永恒的经典:钻石恒久远,51永流传
https://www.stcaimcu.com/data/attachment/forum/202401/15/092706ail7zoqtaoipo3lr.jpg

【新提醒】0.99元USB-STC8H2K08U,144MHz-PWM硬件移相,51全面进入USB时代 - 第3页 - 51 发烧友,UAC,极致音频,大国工匠,艺术人生,乐林漫步 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4707&page=3#pid50750

乘风飞扬 发表于 2024-4-7 10:20:28

huiyong828 发表于 2024-4-7 08:22
频率最高频率10-100KHz,现在用的是STC32G

高速PWM输出频率太高导致调节速度跟不上。
高速PWM使用异步模式配置寄存器,消耗的时间会更多一些。
将PWM时钟调低一些试试,例如设置:
HSCLKDIV = 8;

huiyong828 发表于 2024-4-7 11:49:22

乘风飞扬 发表于 2024-4-7 10:20
高速PWM输出频率太高导致调节速度跟不上。
高速PWM使用异步模式配置寄存器,消耗的时间会更多一些。
将PW ...

是这个问题,因为开关频率需要在10KHz到100KHz调节,进入中断后处理异步模式寄存器操作复杂,芯片吃不消导致的问题
页: [1]
查看完整版本: 请教高速高级(HSPWM)模式下怎么实现(频率-占空比)调节相位差180度PWM信号