• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

初学SPWM之程序怪现状!!要么脉冲不稳定,要么在一段上缺失脉冲,要么下降沿抖动。

最近调了一个基于C8051F340单片机的SPWM程序。但总不能输出想要的波形。要么脉冲不稳定,要么在一段上缺失脉冲,要么下降沿抖动。请各位大侠指点迷津。

硬件平台:C8051F340单片机(利用其扩展功能--PCA定时器/计数器的高速输出模式)
软件平台:SILION(keil的一个相似版本新华龙单片机专用的)
(注:SPWM是就是在PWM的基础上改变了调制脉冲方式,脉冲宽度时间占空比按正弦规率排列,这样输出波形经过适当的滤波可以做到正弦波输出。)
目的波形:脉冲宽度按数组内容变化。数组元素个数为一个周期。比如:数组元素为100,200,300,200,100;这样可以形成“窄-中-宽-中-窄-窄-中-宽-中-窄……”的波形
失败波形:脉冲虽按数组内容变化。但每一组(窄-中-宽-中-窄)之间相隔大约有5.4ms的低电平,大约算了一下,好像正好是65536个时钟时间。但从程序中却找不到这个时间流失到哪里去了。

#include                  // SFR declarations
unsigned char counter=0;
sfr16 PCA0CP0 = 0xFB;                  // 定义比较器0的地址。这样就可以操作这个16位的比较器了(不用高低8位分别操作了)。

unsigned int code PWM[10]={100,500,200,400,300,300,200,400,100,500};
unsigned int NEXT_COMPARE_VALUE;       // 定义变量(下一次放入的值)

void OSCILLATOR_Init (void);
void PORT_Init (void);
void PCA0_Init (void);

void main (void) 
{
  PCA0MD = 0x00;// 关看门狗
  PORT_Init ();                       // 初始化端口
  OSCILLATOR_Init ();                 // 初始化时钟//不熟悉此单片机的可以不用管这两步设置,此单片机的例程中都用的这两步。
  PCA0_Init ();                       // 初始化PCA0定时器/计数器
  EA = 1;                             // 开总中断
  while (1)
  { 
    if(counter==10)// 如果数组遍历完,重新开始 
    {
      counter=0;
      NEXT_COMPARE_VALUE=0;//PWM[0];
      PCA0L=0;
      PCA0H=0;
    }
  }   
}

void OSCILLATOR_Init (void)//时钟设置:设为使用系统时钟12MHZ
{
   OSCICN = 0x83;                      // Set internal oscillator to run
                                       // at its maximum frequency
   CLKSEL = 0x00;                      // Select the internal osc. as
                                       // the SYSCLK source
}
void PORT_Init (void)//端口设置:设置内部的PWM通过P0.0输出
{
   XBR0    = 0x00;
   XBR1    = 0x41;                     // Route CEX0 to P0.0,
                                       // Enable crossbar and weak pull-ups
   P0MDOUT |= 0x01;                    // Set CEX0 (P0.0) to push-pull
}

void PCA0_Init (void)//设置PCA定时计数器。工作方式为高速输出模式。允许匹配翻转,允许匹配中断。
{
   PCA0CN = 0x00;                      // 停止PCA定时器/计数器,并清除各种中断标志
   PCA0MD = 0x08;                      // PCA定时器/计数器使用系统时钟,即12MHZ

   PCA0CPM0 = 0x4D; //此处用的是比较模块0// 高速输出模式(当计数器值与比较器值相等时P0.0电平发生翻转),
                                // 使能比较器的匹配中断功能(当计数器值与比较器值相等时产生中断-可以在中断中放入下次值以产生PWM),
                                // 使能比较器的匹配标志(当计数器值与比较器值相等时此位由硬件置1,但需软件清0-需在中断中清0)
   PCA0L = 0x00;                // 初始化PCA定时器/计数器初值
   PCA0H = 0x00;
   PCA0CPL0 = PWM[0] & 0x00FF;   // 放入比较器0初始值(此处我放入数组第一元素)
   PCA0CPH0 = (PWM[0] & 0xFF00) >> 8;
   NEXT_COMPARE_VALUE = PCA0CP0 + PWM[1];//设置下一次放入比较器0的值
   counter=2;
   EIE1 |= 0x10;                       // 使能PCA定时器/计数器全局中断
   CR = 1;                             // 启动PCA定时器/计数器
}


void PCA0_ISR (void) interrupt 11
{
   if (CCF0)                           // 如果模块0匹配中断标志为1
   {
    //CR=0;
    CCF0 = 0;                        // 清模块0中断标志.
    PCA0CPL0 = (NEXT_COMPARE_VALUE & 0x00FF);//放入比较器0下一次的值
    PCA0CPH0 = (NEXT_COMPARE_VALUE & 0xFF00)>>8;
    NEXT_COMPARE_VALUE = PCA0CP0 + PWM[counter];//计算下一次的值
    counter++;
    //CR=1;
   }
   else                                // 如果是其它模块产生的中断.
   {
      PCA0CN &= ~0x86;                 // 清除这些模块的中断标志
   }
}
全部回复(20)
正序查看
倒序查看
2011-04-18 07:06

有高手来指点一下么?

0
回复
2011-04-18 14:04
天书。
0
回复
2011-04-18 15:29
@电源猎头
天书。

有吗?是不是太乱了?

0
回复
kinto
LV.5
5
2011-04-18 17:25

程序有没有跑飞?

0
回复
2011-04-19 08:04
@kinto
程序有没有跑飞?

没有跑飞。波形很稳定。但不是我想要的。

我觉得应该出这样的波形:

 

但这个程序出的波形是:

 

中间那段低电平大约5.4ms(我算了一下是65536次计数时间)。但是每一组波形倒是很稳定。没有抖动什么的。 

0
回复
2011-04-19 21:10
@ainadexiaoqiang
没有跑飞。波形很稳定。但不是我想要的。我觉得应该出这样的波形:[图片] 但这个程序出的波形是:[图片] 中间那段低电平大约5.4ms(我算了一下是65536次计数时间)。但是每一组波形倒是很稳定。没有抖动什么的。 
看波形,应该是中断,加载PWM值太快?
0
回复
无衣
LV.6
8
2011-04-19 22:30
@ainadexiaoqiang
没有跑飞。波形很稳定。但不是我想要的。我觉得应该出这样的波形:[图片] 但这个程序出的波形是:[图片] 中间那段低电平大约5.4ms(我算了一下是65536次计数时间)。但是每一组波形倒是很稳定。没有抖动什么的。 
不知道你的驱动电路是怎样的,上面那个波形如何驱动MOS管?我倒觉得下面那个实际波形是对的,只不过是频率有点不准.如果是按上面波形设计的,可在调试时打开反汇编窗口看看.
0
回复
2011-04-20 09:35
@无衣
不知道你的驱动电路是怎样的,上面那个波形如何驱动MOS管?我倒觉得下面那个实际波形是对的,只不过是频率有点不准.如果是按上面波形设计的,可在调试时打开反汇编窗口看看.

我现在迷惑了。

SPWM的波形应该是:1.周期固定,但占空比随时间变化的PWM?(体现在示波器上是上升沿固定,下降沿按正弦变化的速度左右摆动?)

         2.周期固定,占空比也随时间变化。但体现在示波器上是一组稳定的等周期,但不等占空比的脉冲?

到底是这两种哪一种呢?

请指点。。

0
回复
无衣
LV.6
10
2011-04-20 19:26
@ainadexiaoqiang
我现在迷惑了。SPWM的波形应该是:1.周期固定,但占空比随时间变化的PWM?(体现在示波器上是上升沿固定,下降沿按正弦变化的速度左右摆动?)         2.周期固定,占空比也随时间变化。但体现在示波器上是一组稳定的等周期,但不等占空比的脉冲?到底是这两种哪一种呢?请指点。。
我也是初学正弦波,发过一个求教的贴子:http://bbs.dianyuan.com/topic/608685
0
回复
2011-04-21 09:24
@无衣
我也是初学正弦波,发过一个求教的贴子:http://bbs.dianyuan.com/topic/608685

谢谢。看了你的帖子。很受启发。不过我觉得单极性,查表法,调压,调频。这些用51应该可以吧?我用的是增强型的51,C8051F340.速度不错。不行可行性怎么样。

0
回复
afei8856
LV.4
12
2012-05-04 16:19
@ainadexiaoqiang
谢谢。看了你的帖子。很受启发。不过我觉得单极性,查表法,调压,调频。这些用51应该可以吧?我用的是增强型的51,C8051F340.速度不错。不行可行性怎么样。
340还是很不错偶的
0
回复
yitt
LV.9
13
2012-05-05 05:30
@afei8856
340还是很不错偶的
试一下水看看效果
0
回复
2012-05-05 08:51
@ainadexiaoqiang
没有跑飞。波形很稳定。但不是我想要的。我觉得应该出这样的波形:[图片] 但这个程序出的波形是:[图片] 中间那段低电平大约5.4ms(我算了一下是65536次计数时间)。但是每一组波形倒是很稳定。没有抖动什么的。 

你想要的是双极性,出来的却是单极性。

0
回复
teckey_zuo
LV.1
15
2013-01-17 15:38
别那么麻烦啦,有更好用的MCU,开发工具便宜,不需要烧入器都可以下载程序到Flash里边,正弦表也可以不需要,英飞凌 XC822 XC836  ,带硬件乘法器和除法器,看附件的波形。

有需要支持的发站内消息哟。

 

0
回复
yinxiangtuo
LV.5
16
2013-01-17 16:05
求SPWM函数……
0
回复
1179300092
LV.8
17
2013-01-20 09:30
@yinxiangtuo
求SPWM函数……
0
回复
ker304
LV.4
18
2013-08-16 16:42
@宛东骄子
你想要的是双极性,出来的却是单极性。
你的中断函数耗时太长,而且丢失的那一个脉冲一定是序列当中,占空比最小的那个。原因是你的重载值写入之前。PCA计数器已经跑在了前面,所以电平不会反转。比如说你跑了65500个时钟的低电平后,应该加一个36的高电平吧!应该进中断了吧!于是PUSH了一堆的数据,并且计算、赋值、判断、返回……注意!此时PCA仍在计数,并且已经跑出了36时钟。这时PCA计数器已经大于PCA0CPx中的值,当然不会翻转,只有跑了一圈之后,16位(65536)计数器才重新匹配了你的PCA0CPx中的值。并翻转。所以你的感觉就是丢了一个周期的电平变化。
0
回复
ker304
LV.4
19
2014-09-05 23:54
你的中断函数耗时太长,而且丢失的那一个脉冲一定是序列当中,占空比最小的那个。原因是你的重载值写入之前。PCA计数器已经跑在了前面,所以电平不会反转。比如说你跑了65500个时钟的低电平后,应该加一个36的高电平吧!应该进中断了吧!于是PUSH了一堆的数据,并且计算、赋值、判断、返回……注意!此时PCA仍在计数,并且已经跑出了36时钟。这时PCA计数器已经大于PCA0CPx中的值,当然不会翻转,只有跑了一圈之后,16位(65536+36)计数器才重新匹配了你的PCA0CPx中的值。并翻转。所以你的感觉就是丢了一个周期的电平变化。
0
回复
momo023
LV.1
20
2014-09-23 11:24

是我之前用C8051F120 做了一个SPWM输出的小程序

0
回复
loudianxin
LV.7
21
2014-10-04 23:17
@ainadexiaoqiang
没有跑飞。波形很稳定。但不是我想要的。我觉得应该出这样的波形:[图片] 但这个程序出的波形是:[图片] 中间那段低电平大约5.4ms(我算了一下是65536次计数时间)。但是每一组波形倒是很稳定。没有抖动什么的。 

给的占空比太大  计数溢出了吧

0
回复