打印

DSP 的PWM输出出现异常

[复制链接]
2302|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
faller_up|  楼主 | 2014-11-19 09:08 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
整个程序的思想是AD 实时采样,用PWM实时输出AD的采样值,把PWM当DA用。
用的是F28M35x开发板,下面是C28x整个的程序

#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <string.h>

#define C28_FREQ 150 //C28 CPU frequency in MHz
#define CC_TBPRD 7500

extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;

float Value_num;

interrupt void adc1_isr(void);
//interrupt void Epwm1_INT_isr(void);

Uint16 AD_result_A0;
Uint16 Value_CMPA1;


void main(void)
{
InitSysCtrl(); // Init C28 core
EALLOW;
GpioG1CtrlRegs.GPADIR.bit.GPIO4 = 1; // GPIO4 as output
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // GPIO0 = ePWM1A
EDIS;

memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

InitFlash();

Value_num=CC_TBPRD/4095.0;

DINT;
InitPieCtrl();
IER=0x0000;
IFR=0x0000;
InitPieVectTable();
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.ADCINT1 = &adc1_isr;
EDIS;


InitCpuTimers();
ConfigCpuTimer(&CpuTimer0, C28_FREQ, 100); //SOC


//Enable INT
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
IER |= M_INT1;
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

//configure EPwm1
EPwm1Regs.TBPRD =CC_TBPRD; //
EPwm1Regs.TBCTL.all = 0; // clear all bits in TBCTL
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2; // CLKDIV = 2
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // HSPCLKDIV =1
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // count mode = up-mode
//fpwm =fcpu / ( TBPRD * CLKDIV * HSPCLKDIV)

EPwm1Regs.CMPCTL.bit.SHDWAMODE=CC_SHADOW ;
EPwm1Regs.CMPCTL.bit.LOADAMODE=CC_CTR_PRD;

EPwm1Regs.AQCTLA.bit.CAU=AQ_SET;
EPwm1Regs.AQCTLA.bit.PRD=AQ_CLEAR;

EPwm1Regs.CMPA.half.CMPA=0;


//configure ADC
InitAdc1();
EALLOW;
Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;
Adc1Regs.ADCCTL1.bit.INTPULSEPOS = 1;                                           // ADCINT1 trips after AdcResults latch
Adc1Regs.INTSEL1N2.bit.INT1E = 1;                           // Enabled ADCINT1
Adc1Regs.INTSEL1N2.bit.INT1CONT = 0;                               // Disable ADCINT1 Continuous mode
Adc1Regs.INTSEL1N2.bit.INT1SEL =0;                     // setup EOC0 to trigger ADCINT1 to fire

Adc1Regs.ADCSOC0CTL.bit.CHSEL = 0;                          // set SOC0 channel select to ADC1in_B0
Adc1Regs.ADCSOC0CTL.bit.TRIGSEL = 5;                    // Set SOC0 start trigger to trigger1 // ADC Trigger 1 of the ADC
Adc1Regs.ADCSOC0CTL.bit.ACQPS =6;                   // set SOC0 S/H Window to 7 ADC

AnalogSysctrlRegs.TRIG1SEL.all = 1;                    // Assigning TINT0 to ADC-TRIGGER 1 // Clock Cycles, (6 ACQPS + 1)
EDIS;

CpuTimer0Regs.TCR.bit.TSS = 0;                      // start T0
while(1)
{

}
}

interrupt void adc1_isr(void)
{
AD_result_A0= Adc1Result.ADCRESULT0;

Value_CMPA1=CC_TBPRD-AD_result_A0*Value_num;

EPwm1Regs.CMPA.half.CMPA=Value_CMPA1;

Adc1Regs.ADCINT标志寄存器CLR.bit.ADCINT1 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

GpioG1DataRegs.GPADAT.bit.GPIO4 ^= 1;
}

放了一个GPIO04 的电平反转在AD中断中看AD采样的频率是否正常,可以看到频率是5K,脉宽有5ns到50ns的变化。

问题描述如下:

(为了清晰描述这个问题,不考虑AD过采样)现在AD用10K的采样速度采集5K的的正弦输入信号,也就是输入信号一个周期有两个采样值,对应的PWM占空比应该变化两次。
但是出现了下图中的问题(两种错误都有出现),在某个地方,CMPA的值与理论上采样值不对应的情况。现在已证实AD采样值是没有错误的,(把采样值放在一个很大的数组里面,在MATLAB中看,没有错误)
揣测是CMPA的值有的时候没有装载到当前寄存器上或者是什么原因。


这种错误出现的频率是大概0.15s每次,如果作如下修改:
#define CC_TBPRD 3750
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV4;
这样PWM的周期还是10K ,但是这种错误出现的错误时0.5S;
#define CC_TBPRD 15000
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
PWM的周期还是10K ,基础上看不到错误的出现。

一直找不到原因,麻烦大家指教,不胜感谢!

相关帖子

沙发
airwill| | 2014-11-19 22:48 | 只看该作者
我看, 这是因为 PWM 周期和 ADC 采样周期不同步引起的.
想办法设置成 PWM 的定时器触发 ADC

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
faller_up + 1 赞一个!
板凳
faller_up|  楼主 | 2014-11-20 10:11 | 只看该作者
airwill 发表于 2014-11-19 22:48
我看, 这是因为 PWM 周期和 ADC 采样周期不同步引起的.
想办法设置成 PWM 的定时器触发 ADC ...

果然是这个原因~  非常感谢!

使用特权

评论回复
地板
小木欧尼| | 2014-11-20 16:36 | 只看该作者
airwill 发表于 2014-11-19 22:48
我看, 这是因为 PWM 周期和 ADC 采样周期不同步引起的.
想办法设置成 PWM 的定时器触发 ADC ...

厉害啊

使用特权

评论回复
5
faller_up|  楼主 | 2014-11-21 15:58 | 只看该作者
后来发现其实是PWM分频后的10K,与ADC的trigger CPU timer0的10K之间是存在一个频差的,造成了以上错误。用PWM的SOC触发确实能根除这个问题。

使用特权

评论回复
6
zhangmangui| | 2014-11-21 22:27 | 只看该作者
faller_up 发表于 2014-11-21 15:58
后来发现其实是PWM分频后的10K,与ADC的trigger CPU timer0的10K之间是存在一个频差的,造成了以上错误。用 ...

恩   谢谢分享

使用特权

评论回复
7
vivilzb1985| | 2014-11-23 20:55 | 只看该作者
查查外部电路的,看是不是受环境影响了诶。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

39

帖子

1

粉丝