×
嵌入式 > 技术百科 > 详情

单片机驱动CPLD的PWM正弦信号发生器设计

发布时间:2020-06-20 发布时间:
|
  前面几期给读者介绍了单片机+CPLD 系统设计,本篇继续挖掘CPLD 潜力,给出一种单片机驱动CPLD的PWM 正弦信号发生器设计,充分体现了CPLD 的灵活多变,配合单片机控制,其妙无穷,以下方案均在Mini51 板上实现。

  脉宽调制PWM(Pulse Width Modulation)是利用数字输出信号对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。

  一、PWM原理

  PWM 是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM 信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON) 或断(OFF) 的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。

  只要带宽足够,任何模拟值都可以使用PWM 进行编码。

  如图1 所示,用一系列等幅不等宽的脉冲来代替一个正弦半波,正弦半波N 等分,看成N 个相连的脉冲序列,宽度相等,但幅值不等;用矩形脉冲代替,等幅,不等宽,中点重合,面积(冲量)相等,宽度按正弦规律变化。

图1 用PWM波代替正弦半波

  SPWM 波形——脉冲宽度按正弦规律变化而和正弦波等效的PWM 波形。

  二、基于CPLD的PWM方案

  一个PWM 发生器必须包括计数器,数据比较器,另外就是配置PWM 参数的时钟分频寄存器和占空比寄存器,结构框图如图2 所示,这些电路都可以用CPLD 来实现。

图2 PWM控制器结构框图

  高频时钟信号经分频器驱动计数器,计数器如图3 所示,总是从Bottom 到Top 的循环计数,计数器的输出和占空比寄存器里的数据经数据比较器比较,输出PWM 信号,当计数器输出小于占空比设定值时输出低电平(0),否则输出高电平(1),如图3(b)(c)所示。

图3 PWM信号发生器时序波形图

  从图中还可以看出,计数器的周期就是PWM 信号的周期,通过修改占空比寄存器从而实现对输出PWM 信号高低电平比例控制,图3(b)是占空比为P1 的PWM输出,图3(c)是占空比为P2 的PWM 输出,它们周期相同,高低电平的比例不同。[page]

    下面用硬件描述语言来设计CPLD 的内部电路,这里给出VerilogHDL 版本的参考代码。

  module Mini51b_PWM(P0,ALE,P27,WR,PWM);// 模块电路命名和端口说明。

  input [7:0]P0;// 数据输入接MCU 数据P0 口

  input ALE,P27,WR;// 几个MCU 读写控制引脚

  output PWM;//PWM 信号输出

  wire [7:0]addr;// 内部地址线

  reg [7:0]daPWMc,daPWMs;// 定义计数器和占空比设定寄存器

  reg [3:0]divPWM,divPWMc;// 分频控制变量

  reg PWM;// 输出锁存器

  assign addr = ALE?P0 : addr; // 低八位地址锁存

  always @(negedge WR)// 在MCU 写信号有效时执行寄存器设定

  begin

  case({P27,addr[4:0]}) // 根据地址选择寄存器

  6\'b10_1000: daPWMs <= P0;// 写带地址的寄存器

  6\'b10_1001: divPWM <= P0[3:0];// 写带地址的寄存器

  default:begin// 其它地址则让寄存器保持不变

  daPWMs <= daPWMs;

  divPWM <= divPWM;

  end

  endcase

  end

  always @(posedge ALE) begin// 这里利用MCU 的ALE 做时钟信号

  if(divPWMc == divPWM) begin // 与分频系数比较

  divPWMc<=0;

  if(daPWMc<100) daPWMc <= daPWMc+1; //PWM 调整精度1%

  else daPWMc <= 0;

  if(daPWMs < daPWMc) PWM <= 0;//PWM 发生器

  else PWM <= 1;

  end

  else divPWMc <= divPWMc+1;// 时钟分频

  end

  endmodule

  关于单片机与CPLD 之间的接口请读者参考本刊前几期笔者撰写的文章。

  与之对应的MCU 测试程序为:

  #include

  #include

  #define PWM XBYTE[0xffe8]

  #define DIV XBYTE[0xffe9]

  void main()

  {

  DIV = 15; //PWM 信号频率计算晶振22.1184M/6/100/

  (DIV+1)=2.30K(实测2.281K)

  PWM=50; // 设定占空比50%,前面计数器范围为0~99

  while(1) ;

  }

[page]

    执行单片机程序,选择不同的分频系数和占空比值,从CPLD 的引脚输出PWM 信号示波器截图如图4所示。

图4 不同占空比的PWM信号示波器截图

  三、SPWM

  如果将占空比按正弦规律随着时间变化,就可以得到正弦调制的PWM 信号,也就是SPWM。如图5 所示,该信号经过阻容滤波可以得到正弦模拟信号,这里的运放做电压跟随器用,对信号驱动能力进行放大。实际得到的正弦信号示波器截图效果如图6 所示。

图5 SPWM阻容滤波电路

图6 正弦信号示波器截图

[page]

    正弦信号发生器MCU 演示程序:

  #include

  #include

  #define PWM XBYTE[0xffe8]

  unsigned char code sine_dot[32]={49,59,68,77,84,90,95,98,99,98,95,90,84,77,68,59,49,40,30,22,14,8,4,1,0,1,4,8,14,22,30,40};// 正弦表

  void main()

  {

  unsigned char i=0;

  while(1) {

  PWM = sine_dot[i];

  i=(i++)&0x1f;

  }// 如果要严格控制SPWM 的周期,这里的while 循环请用定时器来驱动

  }

  四、三路精确相位差正弦信号发生器

  对CPLD 改进设计,很容易实现多路PWM 输出。

  例如设计具有精确相位差的三相正弦信号,CPLD 电路VerilogHDL 程序如下:

  module Mini51b_PWM(P0,ALE,P27,WR,PWM);

  input [7:0]P0;

  input ALE,P27,WR;

  output [2:0]PWM;

  wire [3:0]addr;

  reg [7:0]daPWMc;

  reg [7:0]daPWMs0,daPWMs1,daPWMs2;

  reg [2:0]PWM;

  wire clk,nclk,a,b,c,d;

  assign addr= (ALE)?P0[3:0]:addr; // 低八位地址锁存

  always @(negedge WR)

  begin

  case({P27,addr})

  5\'H10: daPWMs0 <= P0;// 写带地址的寄存器

  5\'H11: daPWMs1 <= P0;// 写带地址的寄存器

  5\'H12: daPWMs2 <= P0;// 写带地址的寄存器

  default:

  begin

  daPWMs0 <= daPWMs0;

  daPWMs1 <= daPWMs1;

  daPWMs2 <= daPWMs2;

  end

  endcase

  end

  always @(posedge clk) begin

  daPWMc <= daPWMc+1; //PWM 调整精度1%

  if(daPWMs0 < daPWMc) PWM[0] <= 0;//PWM 发生器

  else PWM[0] <= 1;

  if(daPWMs1 < daPWMc) PWM[1] <= 0;//PWM 发生器

  else PWM[1] <= 1;

  if(daPWMs2 < daPWMc) PWM[2] <= 0;//PWM 发生器

  else PWM[2] <= 1;

  end

  assign nclk=!clk;

  LCELL A0(。in(nclk), .out(a));

  LCELL A1(。in(a), .out(b));

  LCELL A2(。in(b), .out(c));

  LCELL A3(。in(c), .out(d));

  LCELL A4(。in(d), .out(clk));//PWM 时钟来自CPLD 内部

  LCELL 延迟电路振荡器

  endmodule

  与之对应的MCU 演示程序:

  #include

  #include

  #define PWM0 XBYTE[0xfff0]

  #define PWM1 XBYTE[0xfff1]

  #define PWM2 XBYTE[0xfff2]

  unsigned char code sine_dot[36]= //8 阶,36 点正弦表

  {

  0x80,0x96,0xab,0xbf,0xd2,0xe2,0xee,0xf8,0xfe,0xff,0xfe,0xf8,

  0xee,0xe2,0xd2,0xc0,0xab,0x96,0x80,0x69,0x54,0x40,0x2

  d,0x1e,

  0x11,0x07,0x01,0x00,0x01,0x07,0x10,0x1d,0x2d,0x3f,0x53,

  0x69

  };

  void main()

  {

  unsigned char a,b,c;

  a=0;

  while(1) {

  a %= 36;// 对36 取余数及0~35

  b=(a+12)%36;// 较a 路滞后120 度相位

  c=(a+24)%36;// 较a 路滞后240 度相位

  PWM0 = sine_dot[a];

  PWM1 = sine_dot[b];

  PWM2 = sine_dot[c];

  a++;

  }

  }

  实际得到的三相正弦信号示波器截图效果如图7所示,只是双踪示波器同时只能看两路信号。

图7 具有精确相位差的三相正弦信号示波器截图

  五、结束语

  今后,MCU+CPLD 结构将是很多电子系统设计的一种基本架构,MCU 可以用程序实现复杂智能的控制与检测,CPLD 又可以实现灵活多变的外围扩展电路设计,尤其是可以用硬件实现特殊的MCU 无法实现的功能,弥补MCU 响应速度慢影响实时性问题,两者互补,完全实现硬件软设计,使得同一硬件平台能够通过软件实现更多的功能。

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
中国国产第三代核电实现并网发电