dsPIC30F4011PWM引脚输出电平问题

2020-02-08 09:11发布

如题,PWM输出设置为自由运行模式,当占空比为1时,输出的电平不是5V,而是2.5V。这是为什么呢?程序在下面:
#include "p30F4011.h"
#include "D:PIC-PROJECTMotor-ControlSMC162SMC162.h"
#include "math.h"

/*********************************************************************/
_FOSC(CSW_FSCM_OFF & XT_PLL8);  //Run this project using an external crystal
                                //routed via the PLL in 16x multiplier mode
                                //For the 7.3728 MHz crystal we will derive a
                                //throughput of 7.3728e+6*4/4 = 7.3728 MIPS(Fcy)
                                //,135 nanoseconds instruction cycle time(Tcy).
_FWDT(WDT_OFF);                 //Turn off the Watch-Dog Timer.
_FBORPOR(MCLR_EN & PWRT_OFF & PWMxH_ACT_HI & PWMxL_ACT_HI & RST_IOPIN);   //Enable MCLR reset pin and turn off the
                                //power-up timers.
_FGS(CODE_PROT_OFF);            //Disable Code Protection
//_FICD( ICS_NONE );
//_FICD( ICS_PGD3 );              //调试端口选择,但是不能用于下载程序!
//_FICD( ICS_PGD2 );
//_FICD( ICS_PGD1 );
_FICD( ICS_PGD );
/*********************************************************************/
#define FCY         16000000     // xtal = 8Mhz; PLLx8
#define MILLISEC    FCY/10000        // 1 mSec delay constant
#define FPWM        20000       // 20000

#define DISABLE_FIRING PWMCON1 = 0x0700;PTCONbits.PTEN=0
#define ENABLE_PWM  PWMCON1 = 0x0077;PTCONbits.PTEN=1
#define TURN_LEFT()   LATDbits.LATD0 = 1;LATDbits.LATD1 = 0
#define TURN_RIGHT()   LATDbits.LATD1 = 1;LATDbits.LATD0 = 0
#define TURN_STRAIGHT()   LATDbits.LATD1 = 0;LATDbits.LATD0 = 0
     
void DelayNmSec(unsigned int N);
volatile int i=0;
volatile unsigned int PDC1_TEMP=400;/*定义占空比1变量*/
volatile unsigned int PDC2_TEMP=0;/*定义占空比2变量*/
volatile unsigned char  direction=0;//定义方向左转标记位
void T1_init(void)
{
        T1CON=0;
        TMR1=0;
        PR1=(FCY/256);
        T1CON=0x8030;
        IFS0bits.T1IF=0;
        IEC0bits.T1IE=1;
}
void PWM_init(void)
{
        PORTE=0;
        PWMCON1=0x0077;
        DTCON1=0x000F;
        PTPER=800;//800
        OVDCON=0x3f00;
        IPC9bits.PWMIP=7;
        PTCON=0x8000;//PWM工作在自由运行模式
        IEC2bits.PWMIE=0;
        IFS2bits.PWMIF=0;/*清零中断标志*/       
}
int main(void)
{

       
        //清所有的端口
        PORTB=0;
        PORTC=0;
        PORTD=0;
        PORTE=0;
        PORTF=0xffff;
        ADPCFG=0xffff;

        //确保禁止点火
        DISABLE_FIRING;

        //设定端口方向       
        //注意:DSPIC30F 与 ATMEL AVR设置端口相反,DSPIC30F:0为输出    AVR:0为输入                                       
        TRISB = 0xffff;        // RB15:输出比较错误 -> 输入
//                                        // RB14-0:模拟端口 -> 输入
//                                                       
        TRISC = 0x4000;        // RC14: S2起始/停止开关 -> 输入
                                        // RC13 is state LED -> 输入
                                        // 其余的C端口设定为输出
                                                       
        TRISD = 0x0000;        // D口设置为输出
                                                       
        TRISE = 0x0100;        // RE8: PWM出错按钮 -> 输入
                                        // RE5-0:PWM信号 -> 输出
        TRISF = 0x0000;
//        T1_init();
        PWM_init();
        LcdInit();
//        DelayNmSec(500);
        PutStr(0,0,"Hello!");
        PutStr(0,1,"dsPIC30F4011");
        TURN_STRAIGHT();
        TURN_LEFT();
        while(1)
        {       
                if(PORTBbits.RB6==0)
                {
                        DelayNmSec(10);
                        if(PORTBbits.RB6==0)
                        {
                                while(PORTBbits.RB6==0);
                                PutStr(0,0,"go forword!     ");
                                ENABLE_PWM;
                                PDC2=0;
                                PDC1=1000;
//                                if(PDC1_TEMP>800)
//                                {
//                                        PDC1_TEMP=40;
//                                }
//                                else
//                                {
//                                        PDC1_TEMP+=40;       
//                                }
                        }
                }
                else if(PORTBbits.RB7==0)
                {
                        DelayNmSec(10);
                        if(PORTBbits.RB7==0)
                        {
                                while(PORTBbits.RB7==0);
                                PutStr(0,0,"go back!       ");
                                ENABLE_PWM;
                                PDC1=0;
                                if(PDC2>800)
                                {
                                        PDC2=40;
                                }
                                else
                                {
                                        PDC2+=40;       
                                }
                        }
                }
                else if(PORTBbits.RB8==0)
                {
                        DelayNmSec(10);
                        if(PORTBbits.RB8==0)
                        {
                                while(PORTBbits.RB8==0);
                                if(direction==1)
                                {
                                        direction=2;
                                }
                                else if(direction==2)
                                {
                                        direction=0;
                                }
                                else
                                {
                                        direction=1;
                                }
                               
                                switch(direction)
                                {
                                        case 0:PutStr(0,0,"go straight!");TURN_STRAIGHT();break;
                                        case 1:PutStr(0,0,"turn left!");TURN_LEFT();break;
                                        case 2:PutStr(0,0,"turn right!");TURN_RIGHT();break;
                                        default:PutStr(0,0,"direction wrong!");break;
                                }
                               
                        }
                }
        }        // end of while (1)
}
       


//---------------------------------------------------------------------
// This is a generic 1ms delay routine to give a 1mS to 65.5 Seconds delay
// For N = 1 the delay is 1 mS, for N = 65535 the delay is 65,535 mS.
// Note that FCY is used in the computation.  Please make the necessary
// Changes(PLLx4 or PLLx8 etc) to compute the right FCY as in the define
// statement above.

void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
        for(j=0;j < MILLISEC;j++);
}

void __attribute__((__interrupt__,no_auto_psv))_T1Interrupt(void)
{
        IFS0bits.T1IF=0;
        PORTE=1<<i;
        i++;
        if(i==6)
        {
                i=0;
        }
       
}
void __attribute__((__interrupt__,auto_psv))_PWMInterrupt(void)
{
        IFS2bits.PWMIF=0;/*清零中断标志*/
        PDC1=PDC1_TEMP;
        PDC2=PDC2_TEMP;
               
}       
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
surf_131
1楼-- · 2020-02-08 09:16
没有足够注释的代码。懒惰的码农。怀疑从别处抄来的代码,并非自己仔细设计而得。
手册没有(手上有4013的,不一样),找到dspic30系列编程手册。所谓“占空比1”是指PDC1/PCD2都达到了800(与PTPER的值相同)同时直流电压是2.5v?之后这个电压就跳回0v?程序里面确实有PDC1/2逐步提升到800的内容,但能否实现则要看按键识别控制部分了。
若是开机缺省状态,PDC1/2确实应该是占空比0.5。
程序上看不出绝对的错误。
lamapig
2楼-- · 2020-02-08 11:34
surf_131 发表于 2012-6-10 12:51
没有足够注释的代码。懒惰的码农。怀疑从别处抄来的代码,并非自己仔细设计而得。
手册没有(手上有4013的 ...

多谢您的回帖,是我自己敲的代码,确实注释很少,惭愧惭愧。
当PDC值大于PETER值的时候,输出也是2.5V,按照手册上说的,只要PDC大于PETER寄存器的值,输出就应该是持续的高电平才对,可是我用万用表测得2.5V。
surf_131
3楼-- · 2020-02-08 12:28
 精彩回答 2  元偷偷看……
lamapig
4楼-- · 2020-02-08 13:32
surf_131 发表于 2012-6-10 17:32
关键是有没有从0到2.5v的变化。没有,基本就是硬件问题,或者是引脚与模拟功能共用没有设置对ANSEL之类。
...

好的,谢谢您。我调试的时候,按键设置不同的PDC值,输出电压是有变化的,从0到2.5V。我再按照您的方法试试去。
lamapig
5楼-- · 2020-02-08 18:25
surf_131 发表于 2012-6-10 17:32
关键是有没有从0到2.5v的变化。没有,基本就是硬件问题,或者是引脚与模拟功能共用没有设置对ANSEL之类。
...

我试了一下,根据按键输入,PWM输出会从0到2.5V均匀递进变化。但是就是不能到4V以上。。。。
tiancaigao7
6楼-- · 2020-02-08 23:07
你没有仔细看手册,上面写的很清楚,PDCx需要左移1位,然后和周期寄存器比较。也就是应该PDC*2才是真正的占空比。

一周热门 更多>