Re: 請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
你好.....
可以請你幫我看ㄧ下這個程式哪裡需要修改才能達到60Hz嗎? 因為我不太懂他的振幅要在哪邊調整...... 麻煩高手幫忙一下..... #define __dsPIC30F2010__ #include <uart.h> #include <adc12.h> #include <timer.h> #include <math.h> #include <p30F2010.h> #include <uart.h> #include <stdio.h> //#include "APP009V2_LCD.h" #define pi 3.1415926 #define FCY 7372800 * 2 #define MAX_HALF_DUTY 730 // Max Duty is 180 , but multiplex with 100 #define Volt0 736 void Initial_Timer1( void ) ; void Initial_CAN( void ) ; void DelayNmSec(unsigned int ) ; void InitADC10(void); void MotPWM_Initial(void); //--------------------------------------------------------------------------- // Configuration bits _FOSC(CSW_FSCM_OFF & XT_PLL8); //XT with 8xPLL oscillator, Failsafe clock off _FWDT(WDT_OFF); //Watchdog timer disabled _FBORPOR(PBOR_OFF & MCLR_EN); //Brown-out reset disabled, MCLR reset enabled _FGS(CODE_PROT_OFF); //Code protect disabled typedef struct tagLEDBITS { unsigned :8; unsigned LED_Val:8; } PORTDBITSS; extern volatile PORTDBITSS LED_Ctrl __attribute__((__near__)); unsigned char TxData[10] = {0,0,0,0,0,0,0,0,0,0} ; unsigned int ValuePDC ; int SinTable[92] ; int LoopVar1 ; int U_Degree ; int V_Degree ; int W_Degree ; int T1IF_Flag ; int T1IF_Counter ; unsigned int Temp_Uint ; void __attribute__((__interrupt__)) _T1Interrupt(void) { U_Degree += 3; if ( U_Degree > 360 ) U_Degree = 0 ; { if ( U_Degree <= 90 ) ValuePDC = ( SinTable[U_Degree]) + Volt0 ; else if ( U_Degree > 90 && U_Degree <= 180 ) ValuePDC = ( SinTable[180 - U_Degree] )+ Volt0 ; else if ( U_Degree > 180 && U_Degree <= 270 ) ValuePDC = Volt0 - ( SinTable[U_Degree - 180] ) ; else if ( U_Degree > 270 && U_Degree <= 360 ) ValuePDC = Volt0 - ( SinTable[360-U_Degree] ) ; PDC1 = ValuePDC ; } V_Degree = U_Degree + 180 ; if ( V_Degree > 360 ) V_Degree = V_Degree - 360 ; { if ( V_Degree <= 90 ) ValuePDC = ( SinTable[V_Degree] )+ Volt0 ; else if ( V_Degree > 90 && V_Degree <= 180 ) ValuePDC = ( SinTable[180 - V_Degree ] )+ Volt0 ; else if ( V_Degree > 180 && V_Degree <= 270 ) ValuePDC = Volt0 - ( SinTable[V_Degree - 180]) ; else if ( V_Degree > 270 && V_Degree <= 360 ) ValuePDC = Volt0 - ( SinTable[360-V_Degree] ) ; PDC2 = ValuePDC ; } //W_Degree = U_Degree + 240 ; //if ( W_Degree > 360 ) W_Degree = W_Degree - 360 ; //{ //if ( W_Degree <= 90 ) //ValuePDC = ( SinTable[W_Degree] )+ Volt0 ; //else if ( W_Degree > 90 && W_Degree <= 180 ) //ValuePDC = ( SinTable[180 - W_Degree ])+ Volt0 ; //else if ( W_Degree > 180 && W_Degree <= 270 ) //ValuePDC = Volt0 - ( SinTable[W_Degree - 180]) ; //else if ( W_Degree > 270 && W_Degree <= 360 ) //ValuePDC = Volt0 - ( SinTable[360-W_Degree]) ; //PDC3 = ValuePDC ; //} } void __attribute__((__interrupt__)) _PWMInterrupt(void) { IFS2bits.PWMIF = 0 ; } int main( void ) { for ( LoopVar1 = 0 ; LoopVar1 < 91 ; LoopVar1 += 1) { SinTable[LoopVar1] = sin( (3.1415926 * LoopVar1) / (double)180 ) * MAX_HALF_DUTY ; } Initial_Timer1( ) ; MotPWM_Initial( ) ; TRISD &= 0x00ff ; U_Degree = 0 ; T1IF_Flag = 0 ; T1IF_Counter = 0 ; //putrsLCD("dsPIC30F2010 Dem") ; //setcurLCD(0,1) ; //putrsLCD("PWM Running ") ; while (1) { } } void DelayNmSec(unsigned int N) { unsigned int j; while(N--) for(j=0;j < 1000;j++); } void Initial_Timer1( void ) { ConfigIntTimer1( T1_INT_PRIOR_7 & T1_INT_ON ) ; OpenTimer1( T1_ON & T1_IDLE_STOP & T1_GATE_OFF & T1_PS_1_1 & T1_SYNC_EXT_OFF & T1_SOURCE_INT , 2048 ) ; } void MotPWM_Initial(void) { IEC2bits.PWMIE = 0 ; // Disable PWM Interrupt !! IEC2bits.FLTAIE = 0 ; OVDCON = 0xff00 ; // Inactive all PWM OUTPUT !! TRISE = 0xffc0 ; PTCON = 0xa000 ; // Configure as 0b1010 0000 0000 0000 // PWM Time Base OFF , PWM Time Base OP in free running Mode PWMCON1 = 0x0077 ; // Configure as 0b0000000000010001 // PWM I/O in complementary Mode and only PWM1L/H as PWM output PWMCON2 = 0x0000 ; // Configure as 0b0000000000000000 DTCON1 = 0x0101 ; // Configure as 0b0000001000000010 ; FLTACON = 0x0000 ; IPC9bits.PWMIP = 6 ; // --------------------------------------------------------------------------------- // The Switching Frequency !! // PWM resolution >= 10 bits , // PDCx[1:15] compare with PTMR [0:14] // PDCx(0) compare with MSB of prescaler counter // So, PTPER is 9 bit if resolution of PDCx is 10 bit // Setting PWM Frequency = 20K // PTPER = ( (7372800*2)/ 20000 ) -1 = 736.28 = 736 // PWM Frequency will be Fcy/736 = 20.0K // Formular !! PTPER = (Fcy/(FPWM*PTMR Prescaler)) - 1 // --------------------------------------------------------------------------------- PTPER = 736 ; // PWM Time Base Period Register ValuePDC = 0x00 ; PDC1 = ValuePDC ; PDC2 = ValuePDC ; //PDC3 = ValuePDC ; }
發表於: 2007/6/11 9:09
|
|||
|
Re: 急救.....請大家幫忙一下.....
|
||||
---|---|---|---|---|
新會員
|
我不是要做 six step
只是想讓PWM達到自動調變作用.... 目前有做出自動調變.... 不過不知道是不是程式哪邊有問題.... 還是說外部震盪器沒有完全震盪起來.... 我原本設定的是60Hz的PWM信號.... 出來卻是1.32kHz的信號..... 所以想請教各位高手.... 是不是我的外部震盪器的關係.... 還是說我程式內部有問題... 我用的是dspic 30F2010....
發表於: 2007/6/11 8:47
|
|||
|
Re: 急救.....請大家幫忙一下.....
|
||||
---|---|---|---|---|
新會員
|
不是ㄧPO在PO....而是問題沒解決阿...
所以想在請教不同的問題阿....
發表於: 2007/6/7 18:31
|
|||
|
急救.....請大家幫忙一下.....
|
||||
---|---|---|---|---|
新會員
|
各位高手.....
可以請教一下.... 我要60Hz的PWM信號..... 程式如下.... #define __dsPIC30F2010__ #include <uart.h> #include <adc12.h> #include <timer.h> #include <math.h> #include <p30F2010.h> #include <uart.h> #include <stdio.h> //#include "APP009V2_LCD.h" #define pi 3.1415926 #define FCY 7372800 * 2 #define MAX_HALF_DUTY 730 // Max Duty is 180 , but multiplex with 100 #define Volt0 736 void Initial_Timer1( void ) ; void Initial_CAN( void ) ; void DelayNmSec(unsigned int ) ; void InitADC10(void); void MotPWM_Initial(void); //--------------------------------------------------------------------------- // Configuration bits _FOSC(CSW_FSCM_OFF & XT_PLL8); //XT with 8xPLL oscillator, Failsafe clock off _FWDT(WDT_OFF); //Watchdog timer disabled _FBORPOR(PBOR_OFF & MCLR_EN); //Brown-out reset disabled, MCLR reset enabled _FGS(CODE_PROT_OFF); //Code protect disabled typedef struct tagLEDBITS { unsigned :8; unsigned LED_Val:8; } PORTDBITSS; extern volatile PORTDBITSS LED_Ctrl __attribute__((__near__)); unsigned char TxData[10] = {0,0,0,0,0,0,0,0,0,0} ; unsigned int ValuePDC ; int SinTable[92] ; int LoopVar1 ; int U_Degree ; int V_Degree ; int W_Degree ; int T1IF_Flag ; int T1IF_Counter ; unsigned int Temp_Uint ; void __attribute__((__interrupt__)) _T1Interrupt(void) { U_Degree += 3; if ( U_Degree > 360 ) U_Degree = 0 ; { if ( U_Degree <= 90 ) ValuePDC = ( SinTable[U_Degree]) + Volt0 ; else if ( U_Degree > 90 && U_Degree <= 180 ) ValuePDC = ( SinTable[180 - U_Degree] )+ Volt0 ; else if ( U_Degree > 180 && U_Degree <= 270 ) ValuePDC = Volt0 - ( SinTable[U_Degree - 180] ) ; else if ( U_Degree > 270 && U_Degree <= 360 ) ValuePDC = Volt0 - ( SinTable[360-U_Degree] ) ; PDC1 = ValuePDC ; } V_Degree = U_Degree + 180 ; if ( V_Degree > 360 ) V_Degree = V_Degree - 360 ; { if ( V_Degree <= 90 ) ValuePDC = ( SinTable[V_Degree] )+ Volt0 ; else if ( V_Degree > 90 && V_Degree <= 180 ) ValuePDC = ( SinTable[180 - V_Degree ] )+ Volt0 ; else if ( V_Degree > 180 && V_Degree <= 270 ) ValuePDC = Volt0 - ( SinTable[V_Degree - 180]) ; else if ( V_Degree > 270 && V_Degree <= 360 ) ValuePDC = Volt0 - ( SinTable[360-V_Degree] ) ; PDC2 = ValuePDC ; } //W_Degree = U_Degree + 240 ; //if ( W_Degree > 360 ) W_Degree = W_Degree - 360 ; //{ //if ( W_Degree <= 90 ) //ValuePDC = ( SinTable[W_Degree] )+ Volt0 ; //else if ( W_Degree > 90 && W_Degree <= 180 ) //ValuePDC = ( SinTable[180 - W_Degree ])+ Volt0 ; //else if ( W_Degree > 180 && W_Degree <= 270 ) //ValuePDC = Volt0 - ( SinTable[W_Degree - 180]) ; //else if ( W_Degree > 270 && W_Degree <= 360 ) //ValuePDC = Volt0 - ( SinTable[360-W_Degree]) ; //PDC3 = ValuePDC ; //} } void __attribute__((__interrupt__)) _PWMInterrupt(void) { IFS2bits.PWMIF = 0 ; } int main( void ) { for ( LoopVar1 = 0 ; LoopVar1 < 91 ; LoopVar1 += 1) { SinTable[LoopVar1] = sin( (3.1415926 * LoopVar1) / (double)180 ) * MAX_HALF_DUTY ; } Initial_Timer1( ) ; MotPWM_Initial( ) ; TRISD &= 0x00ff ; U_Degree = 0 ; T1IF_Flag = 0 ; T1IF_Counter = 0 ; //putrsLCD("dsPIC30F2010 Dem") ; //setcurLCD(0,1) ; //putrsLCD("PWM Running ") ; while (1) { } } void DelayNmSec(unsigned int N) { unsigned int j; while(N--) for(j=0;j < 1000;j++); } void Initial_Timer1( void ) { ConfigIntTimer1( T1_INT_PRIOR_7 & T1_INT_ON ) ; OpenTimer1( T1_ON & T1_IDLE_STOP & T1_GATE_OFF & T1_PS_1_1 & T1_SYNC_EXT_OFF & T1_SOURCE_INT , 2048 ) ; } void MotPWM_Initial(void) { IEC2bits.PWMIE = 0 ; // Disable PWM Interrupt !! IEC2bits.FLTAIE = 0 ; OVDCON = 0xff00 ; // Inactive all PWM OUTPUT !! TRISE = 0xffc0 ; PTCON = 0xa000 ; // Configure as 0b1010 0000 0000 0000 // PWM Time Base OFF , PWM Time Base OP in free running Mode PWMCON1 = 0x0077 ; // Configure as 0b0000000000010001 // PWM I/O in complementary Mode and only PWM1L/H as PWM output PWMCON2 = 0x0000 ; // Configure as 0b0000000000000000 DTCON1 = 0x0101 ; // Configure as 0b0000001000000010 ; FLTACON = 0x0000 ; IPC9bits.PWMIP = 6 ; // --------------------------------------------------------------------------------- // The Switching Frequency !! // PWM resolution >= 10 bits , // PDCx[1:15] compare with PTMR [0:14] // PDCx(0) compare with MSB of prescaler counter // So, PTPER is 9 bit if resolution of PDCx is 10 bit // Setting PWM Frequency = 20K // PTPER = ( (7372800*2)/ 20000 ) -1 = 736.28 = 736 // PWM Frequency will be Fcy/736 = 20.0K // Formular !! PTPER = (Fcy/(FPWM*PTMR Prescaler)) - 1 // --------------------------------------------------------------------------------- PTPER = 736 ; // PWM Time Base Period Register ValuePDC = 0x00 ; PDC1 = ValuePDC ; PDC2 = ValuePDC ; //PDC3 = ValuePDC ; } 不過我的PWM信號....沒有60Hz.... 我用的是dspic 30F2010 震盪器....6MHz....電容用15pF 不知道是不是沒有震盪起來.... 造成輸出達到1.32kHz的PWM信號.... 請教各位高手.... 我的問題到底在哪??? 還有怎樣才能達到60Hz的PWM信號輸出....
發表於: 2007/6/7 17:42
|
|||
|
Re: 請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
我已經做出來會自動調變的PWM....
不過無法輸出60Hz的弦波..... 不知道是不是外部震盪器不足..... 因為請問震盪器6MHz需要搭配多少的電容值....
發表於: 2007/6/7 14:50
|
|||
|
Re: 請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
我有試過如果輸入值變化...
Duty會跟隨著改變.... 但是無法達到自動變動的Duty.... 是否有哪邊可以改變嗎??? 或是有什麼程式可以達到簡單的PWM自動調變的方法嗎???
發表於: 2007/6/6 13:33
|
|||
|
Re: 請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
可以請教....
我有找到用組語寫的PWM.... 程式裡有讀取 Sine table的值.... 不過測試時.... 卻只讀0值.... 而非整個 Sine table之值.... 可以請教怎麼修改嗎??? 下列是我所找到之程式.... ;****************************************************************************** ; * ; Filename : acim_vhz.s * ; * ;****************************************************************************** ; Notes: * ; ====== * ; The A/D is enabled to sample two pots on the dsPICDEM-MC1 demo board * ; connected to AN7 and AN12. VR1 is used to vary the V/Hz ratio of the * ; modulation. VR2 is used to vary the modulation frequency. By * ; experimenting with the two pot settings, you can find an optimal V/Hz * ; ratio to drive the motor. * ;****************************************************************************** ;*** This code has been modified to drive a split phase motor with a ;*** H bridge, OR with a single complementary output pair. .equ __30F2010, 1 .include "C:\pic30_tools\support\inc\p30f2010.inc" .global __reset ;.............................................................................. ;Configuration bits: ;.............................................................................. config __FOSC, CSW_FSCM_OFF & XT_PLL4 ;Turn off clock switching and ;fail-safe clock monitoring and ;use the XT osc and 4x PLL as ;system clock config __FWDT, WDT_OFF ;Turn off Watchdog Timer config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & MCLR_EN ;Set Brown-out Reset voltage and ;and set Power-up Timer to 16msecs config __FGS, CODE_PROT_OFF ;Set Code Protection Off for the ;General Segment ;.............................................................................. ;Uninitialized variables in Near data memory (Lower 8Kb of RAM) ;.............................................................................. .section .nbss, "b" ; This variable is added to the 16-bit sine wave table pointer at each ; PWM period. A value of 246 will provide 60 Hz modulation frequency ; with 16 KHz PWM Frequency: .space 2 ; This variable is used to set the modulation amplitude and scales the ; value retrieved from the sine wave table. Valid values range from 0 ; to 32767 Amplitude: .space 2 ; This variable is the pointer to the sinewave table. It is incremented ; by the value of the Frequency variable at each PWM interrupt. Phase: .space 2 ;.............................................................................. ;Constants stored in Program space ;.............................................................................. .section .sine_table, "x" .align 256 ; This is a 64 entry sinewave table covering 360 degrees of the ; sine function. These values were calculated using Microsoft ; Excel and pasted into this program. SineTable: .hword 0,3212,6393,9512,12539,15446,18204,20787,23170,25329 .hword 27245,28898,30273,31356,32137,32609,32767,32609,32137,31356,30273,28898 .hword 27245,25329,23170,20787,18204,15446,12539,9512,6393,3212,0,-3212,-6393 .hword -9512,-12539,-15446,-18204,-20787,-23170,-25329,-27245,-28898,-30273 .hword -31356,-32137,-32609,-32767,-32609,-32137,-31356,-30273,-28898,-27245 .hword -25329,-23170,-20787,-18204,-15446,-12539,-9512,-6393,-3212 ;.............................................................................. ; Constants for this application ;.............................................................................. ; This constant is used to scale the sine lookup value to the valid range ; of PWM duty cycles. This is based on the value written to PTPER. We will ; PTPER = 230 for this application, which allows duty cycles between 0 and ; 460. The sine table data is signed, so we will multiply the table data ; by 230, then add a constant offset to scale the lookup data to positive ; values .equ PWM_Scaling, 230 ;.equ xd, 100 ; The pointer to the sign wave table is 16 bits. Adding 0x5555 to the ; pointer will provide a 120 degree offset and 0xAAAA will give a 240 ; degree offset. These offsets are used to get the lookup values for ; phase 2 and phase 3 of the PWM outputs. ;.equ Offset_120, 0x5555 ;*** Added this offset to drive the split phase motor. We need an output ;*** that is shifted by 180 degrees. .equ Offset_180,0x8000 ;.............................................................................. ;Code Section in Program Memory ;.............................................................................. .text ;Start of Code section __reset: MOV #__SP_init, W15 ;Initalize the Stack Pointer MOV #__SPLIM_init, W0 ;Initialize the Stack Pointer Limit Register MOV W0, SPLIM NOP ;Add NOP to follow SPLIM initialization CALL _wreg_init ;Call _wreg_init subroutine ;Optionally use RCALL instead of CALL call Setup ; Call the routine to setup I/O and PWM ;------------------------------------------------------------------------------ ; Variable initialization ;------------------------------------------------------------------------------ clr Frequency clr Amplitude ;------------------------------------------------------------------------------ ; Main loop code ; The PWM interrupt flag is polled in the main loop ;------------------------------------------------------------------------------ Loop: btss IFS2,#PWMIF ; poll the PWM interrupt flag bra CheckADC ; if it is set, continue call Modulation ; call the sinewave modulation routine bclr IFS2, #PWMIF ; Clear the PWM interrupt flag ;call Loop CheckADC: btss IFS0,#ADIF bra Loop call ReadADC bra Loop ;call Loop ;------------------------------------------------------------------------------ ; ADC processing subroutine ;------------------------------------------------------------------------------ ReadADC: push.d W0 push.d W4 mov ADCBUF0,W0 ; Read the ADC results into W0 mov ADCBUF1,W1 ; and W1. asr W0,#2,W4 ; Right shift by 2 bits to get the mov W4,Frequency ; modulation frequency. sl W1,#5,W4 ; Left shift AN7 and AN12 values to get sl W0,#5,W5 ; 1.15 fractional data. mpy W4*W5,A ; multiply frequency by V/Hz gain to get sac A,W0 ; mod. amplitude. Store result in W0 mov #28000,W1 ; Limit modulation amplitude to avoid cp W1,W0 ; dead-time induced distortion in PWM bra GE,NoLimit ; modulation. mov W1,W0 NoLimit: mov W0,Amplitude pop.d W4 pop.d W0 return ;------------------------------------------------------------------------------ ; PWM sine wave modulation subroutine ;------------------------------------------------------------------------------ Modulation: push.d W0 ; Save off working registers push.d W2 push.d W4 push.d W6 push.d W8 push.d W10 ; The next three instructions initialize the TBLPAG and pointer register ; for access to the sinewave data in program memory using table reads. mov #tblpage(SineTable),W0 mov W0,TBLPAG mov #tbloffset(SineTable),W0 ; The next block of instructions loads various constants and variables ; used in the sinewave modulation routine. mov Phase,W1 ; Load the sinewave table pointer ;*** Modified the offset to 180 degrees for split phase motor. mov #Offset_180,W4 ; This is the value for a 180 degree offset mov Amplitude,W6 ; Load the Amplitude scaling factor ;mov #1,W6 mov #PWM_Scaling,W7 ; Load the PWM scaling value mov Frequency,W8 ; Load the Frequency constant that will ; be added to the table pointer at each ; interrupt. ; This is the pointer adjustment code. The Frequency value is added ; to the sine pointer to move through the sine table. Then, offsets ; are added to this pointer to get the phase 2 and phase 2 pointers. ; Note: If different phase offsets are desired, other constant values ; can be used here. Add 0x4000 to get a 90 degree offset, 0x8000 will ; provide a 180 degree offset. Here, 0x5555 has been loaded to W4 ; to provide 120 degrees. add W8,W1,W1 ; Add the Frequency value to the sine pointer add W1,W4,W2 ; Add 180 degree offset value for phase 2 ;*** Don't need the following line for split phase motor ;add W2,W4,W3 ; Add another 120 degree offset for phase 3 ; The sine table has 64 entries, so the pointers are right shifted ; to get a 6-bit pointer value. lsr W1,#10,W9 ; Shift the phase 1 pointer right to get the upper 6 bits sl W9,#1,W9 ; Left shift by one to convert to byte address lsr W2,#10,W10 ; Shift the phase 2 pointer right to get the upper 6 bits sl W10,#1,W10 ; Left shift by one to convert to byte address ;*** Removed for split phase motor ;lsr W3,#10,W11 ; Shift the phase 3 pointer right to get the upper 6 bits ;sl W11,#1,W11 ; Left shift by one to convert to byte address ; Now, the pointer for each phase is added to the base table pointer ; to get the absolute table address for the lookup value. The lookup ; value is then scaled for the correct amplitude and for the range ; of valid duty cycles. The next block of instructions calculates ; the duty cycle for phase 1. The phase 2 and phase 3 code is the same. add W0,W9,W9 ; Form the table address for phase 1 tblrdl [W9],W5 ; Read the lookup value for phase 1 mpy W5*W6,A ; Multiply by the amplitude scaling sac A,W5 ; Store the scaled result mpy W5*W7,A ; Multiply by the PWM scaling factor sac A,W8 ; Store the scaled result add W7,W8,W8 ; Add the PWM scaling factor to produce 50% offset ;mov #xd,W8 mov W8,PDC1 ; Write the PWM duty cycle ; The next block of code calculates the duty cycle for phase 2. add W0,W10,W10 ; Form the table address for phase 2 tblrdl [W10],W5 ; Read the lookup value for phase 2 mpy W5*W6,A ; Multiply by the amplitude scaling sac A,W5 ; Store the scaled result mpy W5*W7,A ; Multiply by the PWM scaling factor sac A,W8 ; Store the scaled result add W7,W8,W8 ; Add the PWM scaling factor to produce 50% offset ;mov #xd,W8 mov W8,PDC2 ; Write the PWM duty cycle ; The next block of code calculates the duty cycle for phase 3. ;*** Don't need the following block of code for split phase motor. ;add W0,W11,W11 ; Form the table address for phase 3 ;tblrdl [W11],W5 ; Read the lookup value for phase 3 ;mpy W5*W6,A ; Multiply by the amplitude scaling ;sac A,W5 ; Store the scaled result ;mpy W5*W7,A ; Multiply by the PWM scaling factor ;sac A,W8 ; Store the scaled result ;add W7,W8,W8 ; Add the PWM scaling factor to produce 50% offset ;mov W8,PDC3 ; Write the PWM duty cycle ; Now, save off the adjusted sinewave table pointer so it can be ; used during the next iteration of this code. mov W1,Phase ;inc xd pop.d W10 ; restore working registers pop.d W8 pop.d W6 pop.d W4 pop.d W2 pop.d W0 return ; return from the subroutine ;------------------------------------------------------------------------------ ; PWM and ADC setup code ;------------------------------------------------------------------------------ Setup: ; The first thing we need to do before enabling the PWM is to ; configure the I/O and reset the power module. The control board ; has a driver IC that buffers the PWM control lines. The active ; low output enable for this buffer is on port RD11. ; The power module has an active high reset line which is connected ; to port RE9. clr PORTD clr PORTE mov #0xF7FF,W0 ; Make RD11 an output to drive PWM buffer mov W0,TRISD ; output enable. mov #0xFDFF,W0 ; mov W0,TRISE ; Make RE9 an output for power module reset ; Now, ensure the power module is reset by driving the reset line for ; a few usec. bset PORTE,#9 repeat #39 nop bclr PORTE,#9 ; Setup the ADC mov #0x0404,W0 ; scan inputs mov W0,ADCON2 ; 2 sample/converts per interrupt mov #0x0003,W0 ; mov W0,ADCON3 ; Tad is 2*Tcy clr ADCHS ; clr ADPCFG ; all A/D pins Analog mode clr ADCSSL ; bset ADCSSL,#7 ; enable scan of AN7 bset ADCSSL,#12 ; enable scan of AN12 mov #0x8066,W0 ; enable A/D, PWM trigger, auto sample mov W0,ADCON1 ; bclr IFS0,#ADIF ; clear A/D interrupt flag ; Now, setup the PWM registers ;*** Modified next line of code for split phase motor. mov #0x0033,W0 ; complementary mode, #1, #2 mov W0,PWMCON1 ; pairs are enabled mov #0x000F,W0 ; 2usec deadtime at 7.38 MIPS mov W0,DTCON1 mov #PWM_Scaling, W0 ; set period for 16KHz PWM at 7.38 MIPS mov W0,PTPER mov #0x0001,W0 ; mov W0,SEVTCMP ; setup the special event trigger for the ADC mov #0x0F00,W0 ; set the special event postscaler to 1:16 mov W0,PWMCON2 ; mov #0x8002,W0 ; PWM timebase enabled, center aligned mode mov W0,PTCON return ; return from the Setup routine ;.............................................................................. ;Subroutine: Initialization of W registers to 0x0000 ;.............................................................................. _wreg_init: CLR W0 MOV W0, W14 REPEAT #12 MOV W0, [++W14] CLR W14 RETURN ;--------End of All Code Sections --------------------------------------------- .end ;End of program code in this file
發表於: 2007/6/5 15:37
|
|||
|
Re: 請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
我有試過裡面的Soure Core....
不過不知為何還是無法做調整..... 有沒有更明確的講法呢??? 還有我有找到感應馬達控制.... 不過依舊無法自動調變..... 是否ㄧ定要外加電壓作為調整才行呢??? 還有程式需要如何修改??? 下列是我所使用之範例程式.... // *********************************************************************** // File : EX15_3_MCPWM.C // Purpose : 練習如何使用 Microchip C30 提供的 PWM 函式庫 // // 使用的函式庫: // pwm // adc10 // // *********************************************************************** #define __dsPIC30F2010__ #include <p30F2010.h> #include <pwm.h> // 將pwm函式的原型宣告檔案含入 #define FCY 7372800 * 2 // 因為使用頻率為將外部 7.3728 MHz * 8 的模式 , 每一指令週期需 4 個 clock // 所以 FCY = (7.3728 * 8 / 4 ) MHz = 7372800* 2 _FOSC(CSW_FSCM_OFF & XT_PLL8); //XT with 8xPLL oscillator, Failsafe clock off _FWDT(WDT_OFF); //Watchdog timer disabled _FBORPOR(PBOR_OFF & MCLR_EN); //Brown-out reset disabled, MCLR reset enabled _FGS(CODE_PROT_OFF); //Code protect disabled void Init_MCPWM(void); const char My_String1[]="Ex 15 - MCPWM" ; // 宣告字串於 Program Memory (因為 const 宣告) char My_String2[]="VR1: VR2: " ; // 宣告字串於 Data Memory int main(void) { Init_MCPWM( ); while (1); } /******************************************************/ // Subroutine to configure the Motor Control PWM module void Init_MCPWM(void) { /* Holds the PWM interrupt configuration value*/ unsigned int config; /* Holds the value to be loaded into dutycycle register */ unsigned int period; /* Holds the value to be loaded into special event compare register */ unsigned int sptime; /* Holds PWM configuration value */ unsigned int config1; /* Holds the value be loaded into PWMCON1 register */ unsigned int config2; /* Holds the value to configure the special event trigger postscale and dutycycle */ unsigned int config3; /* The value of ‘dutycyclereg’ determines the duty cycle register(PDCx) to be written */ unsigned int dutycyclereg; unsigned int dutycycle; unsigned char updatedisable; /* Configure pwm interrupt enable/disable and set interrupt priorties */ config = (PWM_INT_DIS & PWM_FLTA_DIS_INT & PWM_INT_PR1 & PWM_FLTA_INT_PR0); ConfigIntMCPWM( config ); /* Configure PWM to generate square wave of 50% duty cycle */ SetMCPWMDeadTimeGeneration(PWM_DTA20 & PWM_DTAPS4 & PWM_DTB40 & PWM_DTBPS4); dutycyclereg = 1; dutycycle = 0x1FF; updatedisable = 0; // SetDCMCPWM(dutycyclereg,dutycycle,updatedisable); PDC1=0x1FF; PDC2=0x1FF; PDC3=0x1FF; period = 0x2ff; sptime = 0x0; config1 = (PWM_EN & PWM_IDLE_STOP & PWM_OP_SCALE1 & PWM_IPCLK_SCALE1 & PWM_MOD_FREE); config2 = (PWM_MOD1_COMP & PWM_MOD2_COMP & PWM_PDIS3H & PWM_PEN2H & PWM_PEN1H & PWM_PDIS3L & PWM_PEN2L & PWM_PEN1L); config3 = (PWM_SEVOPS1 & PWM_OSYNC_PWM & PWM_UEN); OpenMCPWM(period,sptime,config1,config2,config3); }
發表於: 2007/6/5 15:33
|
|||
|
請教.....關於脈寬調變(PWM)
|
||||
---|---|---|---|---|
新會員
|
請問一下....
dspic的PWM信號可以做自動調變嗎??? 不知為何我的PWM信號只能送固定的DUTY.... 我也有參考網站上的範例程式.... 不過就是無法做出自動調變的PWM.... 我現在是想利用PWM於變頻器上.... 而無回授控制之PWM......需求20kHZ切換頻率.... 變頻器需切成60Hz之交流電源.... 是否懇請板主賜教..... 告知有什麼方法可以自動調變.... 或者是有什麼方法可以做出SPWM的控制信號.... 麻煩板主.....急求
發表於: 2007/6/3 0:30
|
|||
|