fengyu200208 发表于 2026-6-24 16:08:40

STC32G8K48产生SPWM不正常

用STC32G8K48手册上的例程,
通过P2.4和P2.5管脚,用SPWMP生成50Hz正玄波,现在发现输出的还是方波,
怀疑是PWM没有进入中断改变占空比造成的。
看下中断设置也没有问题,麻烦帮看一下什么原因。



#include "STC32G.h"

//************************************************************************
#define PWMA_1            0x00      //P:P1.0N:P1.1
#define PWMA_2            0x01      //P:P2.0N:P2.1
#define PWMA_3            0x02      //P:P6.0N:P6.1

#define PWMB_1            0x00      //P:P1.2N:P1.3
#define PWMB_2            0x04      //P:P2.2N:P2.3
#define PWMB_3            0x08      //P:P6.2N:P6.3

#define PWM3_1            0x00      //P:P1.4N:P1.5
#define PWM3_2            0x10      //P:P2.4N:P2.5
#define PWM3_3            0x20      //P:P6.4N:P6.5

#define PWM4_1            0x00      //P:P1.6N:P1.7
#define PWM4_2            0x40      //P:P2.6N:P2.7
#define PWM4_3            0x80      //P:P6.6N:P6.7
#define PWM4_4            0xC0      //P:P3.4N:P3.3

#define ENO1P             0x01      
#define ENO1N             0x02
#define ENO2P             0x04      
#define ENO2N             0x08
#define ENO3P             0x10      
#define ENO3N             0x20
#define ENO4P             0x40      
#define ENO4N             0x80

//************************************************************************
//SPWM查表索引

u16 PWMA_Duty;
u8 PWM_Index;

//************************************************************************
unsigned int code T_SinTable[]=
{
      1220,1256,1292,1328,1364,1400,1435,1471,1506,1541,1575,1610,1643, 1677,1710,1742,1774,1805,1836,1866,
      1896,1925,1953,1981,2007,2033,2058,2083,2106,2129,2150,2171,2191, 2210,2228,2245,2261,2275,2289,2302,
      2314,2324,2334, 2342,2350,2356,2361,2365,2368,2369,2370,2369,2368,2365, 2361,2356,2350,2342,2334,2324,
      2314,2302,2289,2275,2261,2245,2228,2210,2191,2171,2150,2129,2106,2083,2058,2033,2007,1981,1953,1925,
      1896,1866,1836,1805,1774,1742,1710,1677,1643,1610,1575,1541,1506,1471,1435,1400,1364,1328,1292,1256,
      1220,1184,1148,1112,1076,1040,1005,969 ,934 ,899 ,865 ,830 ,797 ,763 ,730 ,698 ,666 ,635 ,604 ,574 ,
      544,515,487, 459 ,433 ,407 ,382 ,357 ,334 ,311 ,290 ,269 ,249 ,230 ,212 ,195 ,179 ,165 ,151 ,138 ,
      126,116,106,98 ,90,84,79,75,72,71,70,71,72,75,79,84,90,106 ,98,116,
      126,138,151, 165 ,179 ,195 ,212 ,230 ,249 ,269 ,290 ,311 ,334 ,357 ,382 ,407 ,433 ,459 ,487 ,515,
      544,574,604, 635 ,730 ,763 ,797 ,666 ,698 ,830 ,865 ,899 ,934 ,969 ,1005,1040,1076,1112,1148, 1184
};      

//**********************************************************************
//功能:PWM3初始化
//入口:
//出口:

void Pwm3Init(void)
{      
      PWM_Index=0;      
      
      PWMA_Duty = 1220;   //占空比
      
      PWMA_CCER1 = 0x00;      //写 CCMRx 前必须先清零 CCxE 关闭
      PWMA_CCER2 = 0x00;
      
      //*************************捕获/比价模式寄存器1P789
      PWMA_CCMR3 = 0x60;

      PWMA_CCER2 = 0x05;         //PWM3通道输出使能和极性

      PWMA_ARRH= 0x09;               //设置周期时间
      PWMA_ARRL= 0x60;
      
      PWMA_CCR3H=(u8)(PWMA_Duty >> 8);      //设置占空比时间
      PWMA_CCR3L = (u8)(PWMA_Duty);
      
      PWMA_DTR = 0x0C;                        //设置死区时间   12*T ck_psc

      PWMA_ENO = 0x00;
      PWMA_ENO |= ENO3P;
      PWMA_ENO |= ENO3N;
      
      PWMA_PS = 0x00;                  //高级 PWM 通道输出脚选择位
      PWMA_PS |= PWM3_2;      //选择 PWMA_3 通道P24 P25         
      
      //*****************************刹车寄存器
      PWMA_BKR= 0x80;         //使能主输出
      
      //*****************************PWMA中断使能寄存器允许      PWM更新中断
      PWMA_IER= 0x01;         //使能中断   
      PWMA_CR1 |= 0x01;       //开始计时
      EA=1;                   //打开总中断
}      

//************************************************************************
//功能:PWM中断函数
//入口:
//出口:

void PWMA_ISR() interrupt 26
{      
      if(PWMA_SR1 & 0x02)
      {
                PWMA_SR1 &=~0x02;
                PWMA_Duty =T_SinTable;
                if(++PWM_Index>=200)
                        PWM_Index=0;      

                PWMA_CCR1H = (u8)(PWMA_Duty >> 8);      //设置占空比时间
                PWMA_CCR1L=(u8)(PWMA_Duty);
      }
      PWMA_SR1 = 0;
}               


//*****************************************************************

void IoInit(void)
{
      P0M1 = 0xfd;   //1111 1101
      P0M0 = 0x02;   //0000 0010

      P1M1 = 0x13;   //00010011
    P1M0 = 0xEC;   //11101100

      P2M1 = 0x00;   //0000 0000
      P2M0 = 0x38;   //0011 1000
      PwmIn1=0;
      PwmIn2=0;
      
      P3M1 = 0xC1;   //1100 0001
    P3M0 = 0x3E;   //0011 1110
}


//*********************************************************

int main(void)
{
      WTST = 0;                //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
      EAXSFR();                //扩展SFR(XFR)访问使能
      CKCON = 0;      //提高访问XRAM速度
      Pwm3Init();
      EA = 1;
      while(1)
      {


      }
}


梁工 发表于 2026-6-24 16:34:16

示波器观察,占空比没有变化?

fengyu200208 发表于 2026-6-24 16:35:19

占空比没有变化

fengyu200208 发表于 2026-6-24 16:37:08

按照手册上的例程,我就是把IO口调整了,刚才AI说PWM3和PWMA的中断号不一样,我也没有看到用哪个中断号?

ercircle 发表于 2026-6-24 16:41:56


简单例程可先问AI助手,也许一把就解了。


fengyu200208 发表于 2026-6-24 17:05:36

谢谢,现在输出的波形占空比可以改变了。我的方案用芯片驱动一个50Hz的AC电机,但现在看出来的波形异常,不是一个正弦波,是不是PWM输出的频率和电机的L和外并的电容不匹配造成的?

神农鼎 发表于 2026-6-24 17:06:25


神农鼎 发表于 2026-6-24 17:06:55

<p>我看到这个帖子的内容了。这是关于 <strong>STC32G8K48 使用 PWM3(P2.4/P2.5)产生 SPWM 却输出方波</strong> 的问题。问题核心在于 <strong>PWM3 是 PWMA 的通道3,不是独立的外设</strong>,从手册例程修改时需要相应调整多个寄存器配置。</p>
<hr />
<h2>🔍 问题分析</h2>
<p>根据 STC32G 手册第26章(高级PWM),STC32G 只有两组 PWM 定时器:</p>
<table>
<thead>
<tr>
<th>组别</th>
<th>包含通道</th>
<th>中断号</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>PWMA</strong></td>
<td>通道1<del>4(PWM1</del>PWM4)</td>
<td><strong>中断26</strong></td>
</tr>
<tr>
<td><strong>PWMB</strong></td>
<td>通道5<del>8(PWM5</del>PWM8)</td>
<td><strong>中断27</strong></td>
</tr>
</tbody>
</table>
<p><strong>PWM3(P2.4/P2.5)属于 PWMA 的通道3,中断号仍然是 26</strong>,所以&quot;中断号不对&quot;不是根本原因。</p>
<hr />
<h2>🛠 例程用的是通道1,你需要改到通道3</h2>
<p>手册例程 <code>26.10.15</code> 用的是 <strong>PWMA 通道1(PWM1P/P1.0, PWM1N/P1.1)</strong>,你改成 PWM3(P2.4/P2.5)后,<strong>以下寄存器必须同步修改</strong>,不能只改引脚选择:</p>
<h3>✅ 需要修改的地方对照表</h3>
<table>
<thead>
<tr>
<th>项目</th>
<th>原例程(通道1)</th>
<th>改为通道3(P2.4/P2.5)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>通道模式配置</strong></td>
<td><code>PWMA_CCMR1 = 0x60;</code></td>
<td>→<code>PWMA_CCMR3 = 0x60;</code></td>
</tr>
<tr>
<td><strong>输出使能</strong></td>
<td><code>PWMA_CCER1 = 0x05;</code>(使能CC1P/CC1N)</td>
<td>→<code>PWMA_CCER1 |= 0x50;</code>(使能<strong>CC3P/CC3N</strong>)</td>
</tr>
<tr>
<td><strong>占空比寄存器</strong></td>
<td><code>PWMA_CCR1H / PWMA_CCR1L</code></td>
<td>→<code>PWMA_CCR3H / PWMA_CCR3L</code></td>
</tr>
<tr>
<td><strong>输出使能IO</strong></td>
<td><code>PWMA_ENO |= ENO1P | ENO1N;</code></td>
<td>→<code>PWMA_ENO |= ENO3P | ENO3N;</code></td>
</tr>
<tr>
<td><strong>引脚选择</strong></td>
<td><code>PWMA_PS |= PWMA_3;</code>(P6.0/P6.1)</td>
<td>→<code>PWMA_PS |= PWM3_2;</code>(<strong>P2.4/P2.5</strong>)</td>
</tr>
<tr>
<td><strong>中断中更新</strong></td>
<td>更新 <code>PWMA_CCR1</code></td>
<td>→ 更新**<code>PWMA_CCR3</code>**</td>
</tr>
</tbody>
</table>
<hr />
<h3>📝 修正后的关键代码示意</h3>
<pre><code class="language-c">// ---- 引脚选择 ----
PWMA_PS |= PWM3_2;       // PWM3映射到 P2.4/P2.5

// ---- 通道3模式配置 ----
PWMA_CCER1 = 0x00;       // 先清通道使能
PWMA_CCER2 = 0x00;
PWMA_CCMR3 = 0x60;       // 配置通道3为PWM模式
PWMA_CCER1 |= 0x50;      // 使能通道3输出(CC3P=1, CC3NE=1)

// ---- 占空比用 CCR3 ----
PWMA_CCR3H = (u8)(PWMA_Duty &gt;&gt; 8);
PWMA_CCR3L = (u8)(PWMA_Duty);

// ---- 输出使能 ----
PWMA_ENO |= ENO3P;       // 使能 PWM3P 输出
PWMA_ENO |= ENO3N;       // 使能 PWM3N 输出

// ---- 中断仍然是 26 号 ----
void PWMA_ISR() interrupt 26
{
    if (PWMA_SR1 &amp; 0x01)
    {
      PWMA_SR1 &amp;= ~0x01;
      PWMA_Duty = T_SinTable;
      if (++PWM_Index &gt;= 200) PWM_Index = 0;
      PWMA_CCR3H = (u8)(PWMA_Duty &gt;&gt; 8);// ← 关键:改为 CCR3
      PWMA_CCR3L = (u8)(PWMA_Duty);
    }
    PWMA_SR1 = 0;
}
</code></pre>
<hr />
<h3>🧪 快速自查清单</h3>
<ol>
<li>❓ <code>PWMA_CCMR3</code> 是否配置为 <code>0x60</code>?(不是 CCMR1)</li>
<li>❓ <code>PWMA_CCER1</code> 是否设置了 bit4(CC3P)和 bit5(CC3NE)?(即 <code>0x50</code>)</li>
<li>❓ 占空比写入的是 <code>PWMA_CCR3</code> 而不是 <code>PWMA_CCR1</code>?</li>
<li>❓ 中断函数中更新的是 <code>PWMA_CCR3</code>?</li>
<li>❓ 输出使能 <code>PWMA_ENO</code> 用的是 <code>ENO3P | ENO3N</code>?</li>
<li>❓ 引脚选择 <code>PWMA_PS</code> 写的是 <code>PWM3_2</code>(<code>0x10</code>)?</li>
</ol>
<p>如果以上都改对了,SPWM 应该可以正常输出正弦波。你检查一下代码里哪些地方还没改过来?</p>
<hr />
<p><a href="https://www.stcaimcu.com/plugin.php?id=twpx_xunsearch&amp;mod=forum&amp;q=https%3A%2F%2Fwww.stcaimcu.com%2Fthread-24296-1-1.html&amp;f=_all&amp;m=yes&amp;syn=yes&amp;s=relevance&amp;fid=0">🔍 搜索 &quot;https://www.stcaimcu.com/thread-24296-1-1.html&quot;</a></p>

神农鼎 发表于 2026-6-24 17:09:02






狂热主宰 发表于 2026-6-24 17:22:23

fengyu200208 发表于 2026-6-24 16:37
按照手册上的例程,我就是把IO口调整了,刚才AI说PWM3和PWMA的中断号不一样,我也没有看到用哪个中断号? ...

可能没配对寄存器
AI助手可以分析外设配置
这类寄存器配置通常按照手册流程
页: [1] 2
查看完整版本: STC32G8K48产生SPWM不正常