Aqui les pongo unos programas uasndo lenguaje ensamblador , estoy pensando en poderme reunir en mi pais, proponer la creacion de personas apasionadas a los dspiucs, para lo cual estoy definiendo detalles para dar una charla sobre dspics.
; files obtained in internet
; La estructura del programa en language ensamblador para un dspic es
;
ramirotaipe@yahoo.com 593-03-2603171
; codigo internacional – codigo de proincia- numero del usuario
; PODRA CAMBIAR LA EDUCACION QUIEN TENGA EL CORAJE DE
; PENSAR LIBRTEMENTE Y ACTUAR
; Dispongo de todos los libros mostrados en este foro de microcontroladores si ;deseas llama no de dspics .
; EL A/D es habilitado para mostrar 2 pots sobre el demo board
; conectado a AN7 and AN12. VR1 es usado to vary the V/Hz ratio de la
; modulacion. VR2 es usado to vary the modulacion frecuencia. Por
; experimentacion con los 2 pot ajustando, puedes encontrar un optimo V/Hz
; ratio para manejar el motor
.equ __30F6010, 1
.include "C:pic30_toolssupportincp30f6010.inc"
.global __reset
;..............................................................................
;CONFIGURACION DEL DSPIC30F6010
;..............................................................................
config __FOSC, CSW_FSCM_OFF & XT_PLL4 ;use un oscilador XT
config __FWDT, WDT_OFF ;Desabilitado Watchdog Timer
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & MCLR_EN
;BOR habilitado
; EL dspic empiesa a funcionar despues de 16ms .
config __FGS, CODE_PROT_OFF ; Proteccion de codigo desabilitado
;..............................................................................
;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
; 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
;..............................................................................
;Code Section in Program Memory
;..............................................................................
.text ;Start of Code section
__reset:
MOV #__SP_init, W15 ;Inicializa puntero de píla
MOV #__SPLIM_init, W0 ;Inicializa el registro limite puntero de pila
MOV W0, SPLIM
NOP ;agrega NOP a la SPLIM initiacializacion
CALL _wreg_init ;llama a subrutina _wreg_init subroutine
;Opcionalmente use RCALL in lugar de CALL
call Setup ; Call the routine to setup I/O and PWM
;------------------------------------------------------------------------------
; Inicializacion de variables
;------------------------------------------------------------------------------
clr Frequency
clr Amplitude
;------------------------------------------------------------------------------
; Principal lazo del codigo
; The PWM interrupt flag is polled in the main loop
;------------------------------------------------------------------------------
Loop: btss IFS2,#PWMIF ; poll the PWM interrupt flag
bra CheckADC ; si esto es 1 logico, continue
call Modulation ; call the sinewave modulation
bclr IFS2, #PWMIF ; Clear the PWM interrupt flag
CheckADC:
btss IFS0,#ADIF
bra Loop
call ReadADC
bra 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 y AN12 values to get
sl W0,#5,W5 ; 1.15 fractional data.
mpy W4*W5,A ; multiply freq, 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
; 3 instrucciones siguientes inicialize el TBLPAG y pointer register
; for access a la 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
mov #Offset_120,W4 ; This is the value for a 120 degree offset
mov Amplitude,W6 ; Load the Amplitude scaling factor
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 120 degree offset value for phase 2
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 la phase 1 pointer right a get el upper 6 bits
sl W9,#1,W9 ; Left shift by one to convert to byte address
lsr W2,#10,W10 ; Shift la phase 2 pointer right a get el upper 6 bits
sl W10,#1,W10 ; Left shift by one to convert to byte address
lsr W3,#10,W11 ; Shift la phase 3 pointer right a get la 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. El next block of instructions calculates el
; 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 PWM scaling factor a produce 50% offset
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 PWM scaling factor produce 50% offset
mov W8,PDC2 ; Write the PWM duty cycle
; The next block of code calculates the duty cycle for phase 3.
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 PWM scaling factor 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
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
mov #0x0077,W0 ; complementary mode, #1, #2, and #3
mov W0,PWMCON1 ; pairs are enabled
mov #0x000F,W0 ; 2usec deadtime at 7.38 MIPS
mov W0,DTCON1
mov #PWM_Scaling, W0 ; set period 16KHz PWM at 7.38 MIPS
mov W0,PTPER
mov #0x0001,W0
mov W0,SEVTCMP ; setup 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 ; FIN DEL CODIGO DE PROGRAMA