为什么我这样输出PWM时,使用中断输出的那个PWM引脚会多输出几个波形。
<h1>我想输出两路PWm,然后相位可调的,实现功能需要PWM输出几百毫秒再暂停,这样轮询输出。现在出现的问题是每次暂停再开始时使用中断的那个引脚会提前输出两个PWM波形。有没有大哥知道啥情况</h1><p>`uchar mode=1;<br />
#define MAIN_Fosc 11059200L //定义主时钟<br />
uchar PWMB_ISR_En; //每个通道可以单独允许中断处理, bit4:通道4, bit3:通道3, bit2:通道2, bit1:通道1, bit0:更新中断.0000<br />
#define PWMB_DUTY MAIN_Fosc/12/45 //周期45<br />
#define PWMB_DUTY90 MAIN_Fosc/12/90 //周期90<br />
//#define PWMB_DUTY MAIN_Fosc/12/90 //周期90<br />
#define PWMB_PHASE2 (PWMB_DUTY/2) //通道2相位差<br />
#define PWMB_PHASE290 (PWMB_DUTY90/360) //通道2相位差<br />
uint pwmb1; //PWMB1(PWM5)输出高电平时间<br />
uint pwmb2; //PWMB2(PWM6)输出高电平时间<br />
uint pwmb3; //PWMB1(PWM5)输出高电平时间<br />
uint pwmb4; //PWMB2(PWM6)输出高电平时间<br />
bit B_OutState; //中断使用, 用户层不可见.<br />
bit B_OutState2; //中断使用, 用户层不可见.<br />
void PWMB_config(void)<br />
{<br />
uchar ccer1;<br />
uchar ccer2;<br />
uchar ps;<br />
uchar eno;</p>
<pre><code>P_SW2 |= 0x80; //SFR enable
PWMB_CCMR1 = 0x00; // 通道模式配置, 匹配模式1, 禁止预装载, 匹配时输出高
PWMB_CCMR2 = 0x00; // 通道模式配置, 匹配模式1, 禁止预装载, 匹配时输出高
PWMB_CCMR3 = 0x00; // 通道模式配置, 匹配模式1, 禁止预装载, 匹配时输出高
PWMB_CCMR4 = 0x00; // 通道模式配置, 匹配模式1, 禁止预装载, 匹配时输出高
PWMB_ENO = 0; // IO输出禁止
PWMB_IER = 0; // 禁止中断
PWMB_SR1 = 0; // 清除状态
PWMB_SR2 = 0; // 清除状态
PWMB_CR1 = 0; // 清除控制寄存器
PWMB_CR2 = 0; // 清除控制寄存器
ccer1 = 0;
ccer2 = 0;
ps = 0;
eno = 0;
PWMB_ISR_En = 0;
PWMB_PSCR = 11; // 预分频寄存器, PWM时钟 = 12MHz/(11+1)=1MHz, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
PWMB_DTR= 0; // 死区寄存器, PWMB无效
PWMB_ARR= PWMB_DUTY-1; // 自动重装载寄存器,控制PWM周期
PWMB_ISR_En |= 0x01; // 使能更新中断
</code></pre>
<p>/////////////////////////////////////////////<br />
PWMB_CCMR3 = 0x68; // 通道模式配置, PWM模式1, 预装载允许<br />
PWMB_CCR7= pwmb3; // 比较值, 控制占空比(高电平时钟数)<br />
ccer2 |= 0x05; // 开启比较输出, 高电平有效0x01<br />
ps |= 0x20; // 选择IO, 0:选择P2.0, 1:选择P1.7, 2:选择P0.0, 3:选择P7.4,<br />
eno |= 0x10; // IO输出允许,bit6: ENO8P, bit4: ENO7P,bit2: ENO6P,bit0: ENO5P</p>
<pre><code>PWMB_CCMR4 = 0x40; // 通道模式配置, PWM模式1, 预装载允许
</code></pre>
<p>// PWMB_CCR8= PWMB_PHASE2; // 比较值, 控制占空比(高电平时钟数)<br />
PWMB_CCR8= 0; // 比较值, 控制占空比(高电平时钟数)<br />
ccer2 |= 0x50; // 开启比较输出, 高电平有效<br />
ps |= 0x80; // 选择IO, 0:选择P2.0, 1:选择P1.7, 2:选择P0.0, 3:选择P7.4,<br />
eno |= 0x40; // IO输出允许,bit6: ENO8P, bit4: ENO7P,bit2: ENO6P,bit0: ENO5P<br />
PWMB_ISR_En |= 0x10; // 使能中断</p>
<p>//////////////////////////////////////<br />
// PWMB_CCER1= ccer1; // 捕获/比较使能寄存器1<br />
PWMB_CCER2= ccer2; // 捕获/比较使能寄存器2<br />
PWMB_PS = ps; // 选择IO<br />
PWMB_IER = PWMB_ISR_En; //设置允许通道1~4中断处理</p>
<pre><code>PWMB_BKR = 0x80; // 主输出使能 相当于总开关
PWMB_CR1 = 0x81; // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
PWMB_EGR = 0x01; //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
PWMB_ENO = 0; // 允许IO输出
</code></pre>
<p>}<br />
// PWMB_PS = (0<<6)+(0<<4)+(0<<2)+0; //选择IO, 4项从高到低(从左到右)对应PWM8 PWM7 PWM6 PWM5<br />
//PWMB_PS PWM8 PWM7 PWM6 PWM5<br />
// 00 P2.3 P2.2 P2.1 P2.0<br />
// 01 P3.4 P3.3 P5.4 P1.7<br />
// 02 P0.3 P0.2 P0.1 P0.0<br />
// 03 P7.7 P7.6 P7.5 P7.4</p>
<p>//========================================================================<br />
// 函数: void PWMB_ISR(void) interrupt PWMB_VECTOR<br />
// 描述: PWMA中断处理程序.<br />
// 参数: None<br />
// 返回: none.<br />
// 版本: V1.0, 2021-6-1<br />
//========================================================================<br />
void PWMB_ISR(void) interrupt PWMB_VECTOR<br />
{<br />
uchar sr1;<br />
uchar sr2;<br />
sr1 = PWMB_SR1; //为了快速, 中断标志用一个局部变量处理<br />
PWMB_SR1 = 0; //清除中断标志<br />
sr2 = PWMB_SR2; //为了快速, 中断标志用一个局部变量处理<br />
PWMB_SR2 = 0; //清除中断标志<br />
sr1 &= PWMB_ISR_En; //每个通道可以单独允许中断处理<br />
sr2 &= PWMB_ISR_En; //每个通道可以单独允许中断处理<br />
if(sr1 & 0x01) //更新中断标志<br />
{<br />
PWMB_CCR7= pwmb3; // 匹配值<br />
// if((mode == 3) || (mode == 6) || (mode == 9))PWMB_CCR8= PWMB_PHASE290; // 匹配值<br />
if((mode == 3) || (mode == 6) || (mode == 9))PWMB_CCR8= pwmb3+10; // 匹配值<br />
else PWMB_CCR8= PWMB_PHASE2; // 匹配值<br />
PWMB_CCMR4 = 0x70; // 通道模式配置, PWM模式2, 禁止预装载, 匹配时输出高<br />
B_OutState2 = 0;<br />
}</p>
<pre><code>if(sr1 & 0x10) //通道2匹配中断标志
{
if(!B_OutState2)
{
B_OutState2= 1;
PWMB_CCMR4= 0x50; // 通道模式配置, 强制为有效电平
</code></pre>
<p>// if((mode == 3) || (mode == 6) || (mode == 9))PWMB_CCR8 = PWMB_PHASE290 + pwmb4; // 匹配值, PWM6在400时刻输出低电平<br />
if((mode == 3) || (mode == 6) || (mode == 9))PWMB_CCR8 = pwmb3+pwmb4+10; // 匹配值, PWM6在400时刻输出低电平<br />
else PWMB_CCR8 = PWMB_PHASE2 + pwmb4;<br />
PWMB_CCMR4= 0x60; // 通道模式配置, PWM模式1, 匹配时输出低电平<br />
}<br />
else PWMB_CCMR4= 0x40; // 通道模式配置, 强制为无效电平<br />
}<br />
} `</p>
<p>void PWM_Mode()<br />
{<br />
if(power&&qiangdu&&time)<br />
{<br />
if((mode==1) || (mode==4) || (mode==7) || (mode==10))<br />
{<br />
PWMB_ENO =0X50;<br />
pwmb3 =8+(qiangdu *5);<br />
pwmb4 =8+(qiangdu *5);<br />
}<br />
else if((mode==2) || (mode==5) || (mode==8))<br />
{<br />
tim_pwm++;<br />
if(tim_pwm >=1212)tim_pwm =0;<br />
if(tim_pwm < 950)<br />
{<br />
PWMB_ENO =0X50;<br />
pwmb3 =8+(qiangdu *5);<br />
pwmb4 =8+(qiangdu *5);<br />
}<br />
else<br />
{<br />
PWMB_ENO =0;<br />
P02 =0; P03 =0;<br />
pwmb3 =0; pwmb4 =0;<br />
}<br />
}<br />
else if((mode==3) || (mode==6) || (mode==9))<br />
{<br />
tim_pwm++;<br />
if(tim_pwm >=600)tim_pwm =0;<br />
if(tim_pwm < 251)<br />
{<br />
PWMB_ENO =0X50;<br />
pwmb3 =8+(qiangdu *5);<br />
pwmb4 =8+(qiangdu *5);<br />
}<br />
else<br />
{<br />
PWMB_ENO =0;<br />
P02 =0; P03 =0;<br />
pwmb3 =0; pwmb4 =0;<br />
}<br />
}<br />
}<br />
else<br />
{<br />
tim_pwm =0;<br />
PWMB_ENO &=~0x50;<br />
P02 =0; P03 =0;<br />
pwmb3 =0; pwmb4 =0;<br />
}<br />
}</p>
<p>上面的是PWM配置,下面的是调用</p>
<p><img src="data/attachment/forum/202504/15/154016t7959uz805w5ku97.png" alt="image.png" title="image.png" /></p>
<p><img src="data/attachment/forum/202504/15/154104uc4nnopadkcg9c9g.png" alt="image.png" title="image.png" /></p>
<p>图二是将图一前面多出来的波形放大看的,多出2个波形,占空比小的是固定占空比,占空比大的跟后面输出的占空比一样。</p>
在您提供的代码中,您描述的问题是在使用中断输出PWM时,PWM引脚会多输出几个波形。这种情况通常与中断处理、PWM配置以及定时器的同步问题有关。以下是一些可能的原因和解决方案,供您参考:
1. 中断处理延迟
中断处理函数的执行时间可能会影响PWM输出的准确性。如果中断处理函数中有较长的代码或延迟,可能会导致PWM输出提前或延迟。建议您检查中断处理函数的执行时间,并尽量减少其中的复杂操作。
2. PWM配置问题
在您的代码中,PWM的周期和占空比是通过宏定义的。请确保这些宏定义的值与您的实际需求一致。特别是PWMBDUTY和PWMBPHASE2的定义,需要确保它们与您期望的PWM周期和相位差匹配。
3. 定时器同步问题
PWM输出通常依赖于定时器的计数和比较寄存器。如果定时器的计数器和比较寄存器没有正确同步,可能会导致PWM输出异常。建议您在启动PWM输出之前,确保定时器的计数器和比较寄存器已经正确初始化,并且在暂停和重新启动PWM输出时,重新同步这些寄存器。
4. 中断优先级和嵌套
如果系统中存在多个中断源,中断优先级和嵌套可能会影响PWM输出的准确性。建议您检查中断优先级设置,确保PWM相关的中断具有足够的优先级,以避免被其他中断打断。
5. 硬件特性
某些微控制器的PWM模块可能具有特定的硬件特性或限制,例如输出缓冲、死区时间等。建议您查阅相关微控制器的参考手册,了解PWM模块的详细特性,并根据需要进行配置。
6. 代码优化
在您的代码中,PWMBconfig函数的实现没有完全展示。建议您检查该函数的实现,确保PWM模块的配置正确无误。特别是ccer1、ccer2、ps和eno等寄存器的配置,需要与PWM输出模式相匹配。
7. 调试和测试
为了进一步定位问题,建议您使用调试工具(如逻辑分析仪或示波器)观察PWM输出的波形,并与预期波形进行对比。通过调试和测试,您可以更直观地发现问题所在,并进行针对性的优化。
示例代码优化
以下是一个简化的PWM配置和中断处理示例,供您参考:
c
define MAINFosc 11059200L
define PWMBDUTY (MAINFosc / 12 / 45)
define PWMBPHASE2 (PWMBDUTY / 2)
uint pwmb1, pwmb2;
bit BOutState;
void PWMBconfig(void) {
// 配置PWM模块
// 例如:设置定时器、比较寄存器、输出模式等
// 具体配置根据您的微控制器手册进行
}
void PWMBISR(void) interrupt PWMINTERRUPTVECTOR {
if (BOutState) {
// 处理PWM输出
// 例如:更新比较寄存器、切换输出状态等
}
}
void main(void) {
PWMBconfig();
while (1) {
// 启动PWM输出
BOutState = 1;
// 延时几百毫秒
delayms(500);
// 暂停PWM输出
BOutState = 0;
// 延时几百毫秒
delayms(500);
}
}
总结
通过以上分析和优化,您应该能够解决PWM输出异常的问题。如果问题仍然存在,建议您进一步检查硬件连接、微控制器的参考手册以及相关的中断和PWM配置。希望这些建议对您有所帮助!
[本文内容由国芯人工智能辅助生成,仅供参考]
页:
[1]