Code:
+TITLE 'SUPER PWM FOR 12-BIT PIC' ;-------------------------------------------------------------------------------------------------------------------------------------- ; PROGRAM DESCRIPTION ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; THIS EXAMPLE SHOWS HOW TO CREATE A HIGH RESOLUTION VARIABLE PWM IN A 12-BIT PIC ; ; FEATURES: ; 16-BIT BIT-BANG PWM ; VARIABLE PERIOD ; VARIABLE DUTY CYCLE ; INSTRUCTION CYCLE RESOLUTION ; NO INTERRUPTS ; ; THIS PROGRAM EXECUTES THE MAIN PROGRAM CODE IN SMALL CHUNKS, BETWEEN THESE CHUNKS THE PROGRAM LOOKS AT THE TIMER VALUE AND ; UPDATES THE OUTPUT WHEN NEEDED ; ; NOTE: DUE TO THE TIMER OVERHEAD THERE IS A LIMIT TO THE MAXIMUM FREQUENCY (VERY SHORT PERIODS ARE NOT POSSIBLE WITH THIS CODE) ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; CONSTANTS DEFINITIONS ;-------------------------------------------------------------------------------------------------------------------------------------- ; GPIO BITS PWM EQU 0 ; PWM OUTPUT (ACTIVE HIGH) ;-------------------------------------------------------------------------------------------------------------------------------------- ; VARIABLE DEFINITIONS ;-------------------------------------------------------------------------------------------------------------------------------------- CBLOCK H'10' TIMER_LOW ; ENABLE PROBLEM FREE (ROLLOVER FREE) TESTING AND COPYING OF THE TIMER TIMER_HIGH ; USED TO EXTEND THE TIMER0 RESOLUTION TO A 16-BIT TOTAL CALCPOINTER ; USED TO SEQUENTIALLY PERFORM ALL CALCULATIONS A0 ; PWM HIGH TIME (INSTRUCTION CYCLES) A1 ; B0 ; PWM LOW TIME (INSTRUCTION CYCLES) TO BE COPIED TO Y B1 ; Y0 ; PWM LOW TIME (INSTRUCTION CYCLES) Y1 ; ENDC ;-------------------------------------------------------------------------------------------------------------------------------------- ; START OF PROGRAM ;-------------------------------------------------------------------------------------------------------------------------------------- ORG H'000' ; TELL THE ASSEMBLER TO PLACE FOLLOWING PROGRAM CODE AT BOTTOM OF THE PROGRAM MEMORY START MOVLW B'00000000' ; MAKE GP0(PWM) LOW: PWM OFF MOVWF GPIO ; MOVLW B'11111110' ; MAKE GP0(PWM) OUTPUT TRIS GPIO ; CLRF ADCON0 ; AD-CONVERTER OFF CLRWDT ; WE NEED TO CLEAR THE WATCHDOG TIMER FIRST OR ELSE WE MAY GET A RESET, ALSO CLEARS PRESCALER CLRF TMR0 ; CLEAR TIMER0 AND THE PRESCALER MOVLW B'11001111' ; VALUE FOR NO WAKE-UP ON PIN CHANGE, NO PULL-UPS, TMR0 FROM INSTRUCTION CLOCK 1:1, ASSIGN THE OPTION ; PRESCALER TO THE WATCHDOG 1:128 (2.3 SECOND WATCHDOG TIMEOUT) CLRF A0 ; PWM FREQUENCY IS 100 HZ SO PWM PERIOD IS 10000 INSTRUCTIONS (FOSC = 4 MHZ) CLRF A1 ; A1:A0 = PWM HIGH TIME = 0 MOVLW D'16' ; B1:B0 = PWM LOW TIME = 10000 = 39:16 MOVWF B0 ; MOVLW D'39' ; MOVWF B1 ; GOTO PWM_DOWNFLANK_4 ; NOW GO RUN PWM LOOP ;-------------------------------------------------------------------------------------------------------------------------------------- ; PWM CODE ;-------------------------------------------------------------------------------------------------------------------------------------- JUMP_TO_CALC MOVF CALCPOINTER,W ; WE PERFORM ALL CALCULATION PARTS SEQUENTIALLY SINCE WE MUST ALLOW TIME FOR THE MAIN LOOP MOVWF PCL ; JUMP TO CALCULATION ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; BECAUSE THE 8TH BIT WILL ALWAYS BE RESET TO ZERO ;-------------------------------------------------------------------------------------------------------------------------------------- WAIT4DOWNFLANK CALL JUMP_TO_CALC ; GO DO MAIN STUFF AND PWM CALCULATIONS (THIS LINE CAN TAKE UP TO 36 INSTRUCTION CYCLES) MOVWF CALCPOINTER ; USE RETURN VALUE TO KEEP TRACK OF CALCULATION PROGRESS MOVF TMR0,W ; WE WANT A COPY FOR PROBLEM FREE (ROLLOVER FREE) TESTING AND COPYING OF THE TIMER VALUE SUBWF TIMER_LOW,F ; TEST FOR ROLLOVER, WE NEED TO BE HERE AT LEAST EVERY 256 INSTRUCTIONS OR WE'LL MISS ROLLOVER MOVWF TIMER_LOW ; SKPNC ; HAS TMR0 ROLLED OVER ? INCF TIMER_HIGH,F ; YES, INCREMENT TIMER HIGH BYTE MOVLW D'105' ; SEE IF IS TIME TO UPDATE THE PWM OUTPUT OR IF WE CAN DO THE OTHER STUFF ADDWF TIMER_LOW,W ; CHECK FOR ROLLOVER: T+36+25+44 = T + 105 = 256 = ROLLOVER, SO WE NEED TO ADD 105 SKPNC ; ROLLOVER ? INCFSZ TIMER_HIGH,W ; IS THERE TIME LEFT FOR THE OTHER TASKS ? GOTO WAIT4DOWNFLANK ; YES, GO DO THESE OTHER TASKS ;--------------- ---------------------------------------------------------------------------------------------- MOVLW D'44' ; CORRECT FOR OVERHEAD, WE WANT TO CHANGE THE PWM OUTPUT AT EXACT MOMENT OF TIMER ROLLOVER ADDWF TMR0,F ; RESULT OF THIS ADD MUST BE 255 MAXIMUM OR WE GET ILLEGAL JUMP ; REMEMBER TIMER KEEPS THE NEW VALUE FOR THREE FOLLOWING CYCLES BEFORE INCREMENTING ; BUT WE ALREADY START TESTING TIMER VALUE LOOP_1 BTFSC TMR0,7 ; HAS TIMER 0 ROLLED OVER ? GOTO LOOP_1 ; NO, LOOP AGAIN DECF TMR0,W ; W=1,2,3 ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT OF THE PROGRAM COUNTER WILL ALWAYS BE RESET TO ZERO C0 RETLW LOW(C0) ; PCL+0ALL CALCULATIONS DONE, WAITING FOR START OF NEW PWM PERIOD NOP ; PCL+1 NOP ; PCL+2 COMF Y0,W ; PCL+3, SET NEW TIME SETPOINT: MOVWF TMR0 ; T = 65535 - Y = 65535 - PWM LOW TIME MOVWF TIMER_LOW ; COMF Y1,W ; MOVWF TIMER_HIGH ; ;--------------- ---------------------------------------------------------------------------------------------- CHOOSE_DELAY_1 MOVLW D'123' ; PCL+3, SHORTEST TIME FOR LONG DELAY IS 123? INSTRUCTIONS (INCLUDING MEAS/CALC) SUBWF Y0,W ; CARRY IS CLEAR WHEN LESS MOVF Y1,W ; TEST HIGH BYTE OF DELAY TIME FOR ZERO SKPNZ ; IS THE HIGH BYTE ZERO ? SKPNC ; YES, IS THE LOW BYTE LESS THAN 123 ? GOTO PWMLONGDELAY2 ; NO, HIGH BYTE IS NOT ZERO/NO, LOW BYTE IS MORE, GO USE THE LONG DELAY LOOP MOVLW D'16' ; VARIABLE DELAY FROM 0..255 INSTRUCTIONS SUBWF Y0,W ; CHECK THE DELAY TIME SKPC ; IS THE DESIRED DELAY MORE THAN 16 ? GOTO LOW_VERYSHORT ; NO, SO THE PWM LOW TIME IS VERY SMALL: 0..15 CYCLES, GO USE THE VERY SHORT DELAY ;--------------- ---------------------------------------------------------------------------------------------- PWM_LOW_SHORT MOVWF TIMER_HIGH ; SET DELAY GOTO $+1 ; THREE INSTRUCTION CYCLE DELAY NOP ; MOVLW D'4' ; NEEDED FOR ADJUSTABLE DELAY PWM_DOWNFLANK_1 BCF GPIO,PWM ; MAKE THE PWM OUTPUT LOW LOOP_2 SUBWF TIMER_HIGH,F ; WE USE AN ADJUSTABLE DELAY SKPNC ; GOTO LOOP_2 ; COMF TIMER_HIGH,W ; IORLW B'00001000' ; ADD 8 TO W TO JUMP OVER VERY SHORT DELAY ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT WILL ALWAYS BE RESET TO ZERO ;--------------- ---------------------------------------------------------------------------------------------- LOW_VERYSHORT ADDWF Y0,W ; INVERT W AND THEN INCREMENT W SUBWF Y0,W ; ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT WILL ALWAYS BE RESET TO ZERO NOP ; PCL+0 PWM_DOWNFLANK_2 BCF GPIO,PWM ; 15, PCL+1, MAKE THE PWM OUTPUT LOW BCF GPIO,PWM ; 14, PCL+2 BCF GPIO,PWM ; 13 BCF GPIO,PWM ; 12 BCF GPIO,PWM ; 11 BCF GPIO,PWM ; 10 BCF GPIO,PWM ; 9 BCF GPIO,PWM ; 8 BCF GPIO,PWM ; 7 BCF GPIO,PWM ; 6 BCF GPIO,PWM ; 5 BCF GPIO,PWM ; 4 BCF GPIO,PWM ; 3 BCF GPIO,PWM ; 2 BCF GPIO,PWM ; 1 ;--------------- ---------------------------------------------------------------------------------------------- PWM_UPFLANK_1 BSF GPIO,PWM ; 0: MAKE THE PWM OUTPUT HIGH MOVF B0,W ; COPY NEW PWM TIMING VALUES: MOVWF Y0 ; Y = B = PWM LOW TIME MOVF B1,W ; MOVWF Y1 ; MOVLW LOW(C1) ; START NEW CALCULATIONS MOVWF CALCPOINTER ; COMF A1,W ; SET NEW TIME SETPOINT: MOVWF TIMER_HIGH ; T = 65535 - A = 65535 - PWM HIGH TIME COMF A0,W ; MOVWF TMR0 ; THE EXACT MOMENT OF WRITING THE NEW VALUE TO TMR0 IS CRITICAL MOVWF TIMER_LOW ; GOTO WAIT4DOWNFLANK ; ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- PWMLONGDELAY2 CALL C0 ; EIGHT CYCLE DELAY CALL C0 ; PWM_DOWNFLANK_3 BCF GPIO,PWM ; MAKE THE PWM OUTPUT LOW ;--------------- ---------------------------------------------------------------------------------------------- WAIT4UPFLANK CALL JUMP_TO_CALC ; GO DO MAIN STUFF AND PWM CALCULATIONS (THIS LINE CAN TAKE UP TO 36 INSTRUCTION CYCLES) MOVWF CALCPOINTER ; USE RETURN VALUE TO KEEP TRACK OF CALCULATION PROGRESS MOVF TMR0,W ; WE WANT A COPY FOR PROBLEM FREE (ROLLOVER FREE) TESTING AND COPYING OF THE TIMER VALUE SUBWF TIMER_LOW,F ; TEST FOR ROLLOVER, WE NEED TO BE HERE AT LEAST EVERY 256 INSTRUCTIONS OR WE'LL MISS ROLLOVER MOVWF TIMER_LOW ; SKPNC ; HAS TMR0 ROLLED OVER ? INCF TIMER_HIGH,F ; YES, INCREMENT TIMER HIGH BYTE MOVLW D'72' ; SEE IF IS TIME TO UPDATE THE PWM OUTPUT OR IF WE CAN DO THE OTHER STUFF ADDWF TIMER_LOW,W ; CHECK FOR ROLLOVER: T+36+25+11 = T + 72 = 256 = ROLLOVER, SO WE NEED TO ADD 72 SKPNC ; ROLLOVER ? INCFSZ TIMER_HIGH,W ; IS THERE TIME LEFT FOR THE OTHER TASKS ? GOTO WAIT4UPFLANK ; YES, GO DO THESE OTHER TASKS ;--------------- ---------------------------------------------------------------------------------------------- MOVLW D'11' ; CORRECT FOR OVERHEAD, WE WANT TO CHANGE THE PWM OUTPUT AT EXACT MOMENT OF TIMER ROLLOVER ADDWF TMR0,F ; RESULT OF THIS ADD MUST BE 255 MAXIMUM OR WE GET ILLEGAL JUMP ; REMEMBER TIMER KEEPS THE NEW VALUE FOR THREE FOLLOWING CYCLES BEFORE INCREMENTING ; BUT WE ALREADY START TESTING TIMER VALUE LOOP_3 BTFSC TMR0,7 ; HAS TIMER 0 ROLLED OVER ? GOTO LOOP_3 ; NO, LOOP AGAIN DECF TMR0,W ; W=1,2,3 ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT OF THE PROGRAM COUNTER WILL ALWAYS BE RESET TO ZERO NOP ; PCL+0 NOP ; PCL+1 NOP ; PCL+2 COMF A0,W ; PCL+3, SET NEW TIME SETPOINT: MOVWF TMR0 ; T = 65535 - A = 65535 - NEW PWM HIGH TIME MOVWF TIMER_LOW ; THE EXACT MOMENT OF WRITING THE NEW VALUE TO TMR0 IS CRITICAL COMF A1,W ; MOVWF TIMER_HIGH ; ;--------------- ---------------------------------------------------------------------------------------------- CHOOSE_DELAY_2 MOVLW D'123' ; PCL+3, SHORTEST TIME FOR LONG DELAY IS 123? INSTRUCTIONS (INCLUDING MEAS/CALC) SUBWF A0,W ; CARRY IS CLEAR WHEN LESS MOVF A1,W ; TEST HIGH BYTE OF DELAY TIME FOR ZERO SKPNZ ; IS THE HIGH BYTE ZERO ? SKPNC ; YES, IS THE LOW BYTE LESS THAN 123 ? GOTO DELAYED_JUMP ; NO, HIGH BYTE IS NOT ZERO/NO, LOW BYTE IS MORE, GO USE THE LONG DELAY LOOP MOVLW D'16' ; VARIABLE DELAY FROM 0..255 INSTRUCTIONS SUBWF A0,W ; CHECK THE DELAY TIME SKPC ; IS THE DESIRED DELAY MORE THAN 16 ? GOTO HIGH_VERYSHORT ; NO, SO THE PWM LOW TIME IS VERY SMALL: 0..15 CYCLES, GO USE THE VERY SHORT DELAY ;--------------- ---------------------------------------------------------------------------------------------- PWM_HIGH_SHORT MOVWF TIMER_HIGH ; SET DELAY GOTO $+1 ; THREE INSTRUCTION CYCLE DELAY NOP ; MOVLW D'4' ; NEEDED FOR ADJUSTABLE DELAY PWM_UPFLANK_2 BSF GPIO,PWM ; MAKE THE PWM OUTPUT HIGH LOOP_4 SUBWF TIMER_HIGH,F ; WE USE AN ADJUSTABLE DELAY SKPNC ; GOTO LOOP_4 ; COMF TIMER_HIGH,W ; IORLW B'00001000' ; ADD 8 TO W TO JUMP OVER VERY SHORT DELAY ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT WILL ALWAYS BE RESET TO ZERO ;--------------- ---------------------------------------------------------------------------------------------- HIGH_VERYSHORT ADDWF A0,W ; INVERT W AND THEN INCREMENT W SUBWF A0,W ; ADDWF PCL,F ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; REMEMBER THAT THE 8TH BIT WILL ALWAYS BE RESET TO ZERO NOP ; PCL+0 PWM_UPFLANK_3 BSF GPIO,PWM ; 15, PCL+1, MAKE THE PWM OUTPUT HIGH BSF GPIO,PWM ; 14, PCL+2 BSF GPIO,PWM ; 13 BSF GPIO,PWM ; 12 BSF GPIO,PWM ; 11 BSF GPIO,PWM ; 10 BSF GPIO,PWM ; 9 BSF GPIO,PWM ; 8 BSF GPIO,PWM ; 7 BSF GPIO,PWM ; 6 BSF GPIO,PWM ; 5 BSF GPIO,PWM ; 4 BSF GPIO,PWM ; 3 BSF GPIO,PWM ; 2 BSF GPIO,PWM ; 1 ;--------------- ---------------------------------------------------------------------------------------------- IF $ > H'FF' ; LET THE ASSEMBLER WARN US IF WE PUT THE FOLLOWING INSTRUCTION AT AN ADDRESS > 255 ERROR 'WE CANNOT JUMP TO THIS LOCATION !' ENDIF ; ; REMEMBER THAT ALL SUBROUTINE CALLS OR COMPUTED JUMPS ARE LIMITED TO THE FIRST 256 PROGRAM ; MEMORY LOCATIONS ! WE CAN'T USE "ADDWF PCL,F","CALL","MOVWF PCL,F" OR "BSF PCL,X" ; INSTRUCTIONS TO JUMP TO AN ADDRESS > 255, BUT WE CAN STILL USE 'GOTO' AND 'RETLW'. ;--------------- ---------------------------------------------------------------------------------------------- PWM_DOWNFLANK_4 BCF GPIO,PWM ; 0: MAKE THE PWM OUTPUT LOW MOVLW D'29' ; MAKE CORRECTION SUBWF B0,F ; SKPC ; DECF B1,F ; COMF B0,W ; SET NEW TIME SETPOINT: MOVWF TMR0 ; T = 65535 - B = 65535 - PWM HIGH TIME MOVWF TIMER_LOW ; THE EXACT MOMENT OF WRITING THE NEW VALUE TO TMR0 IS CRITICAL COMF B1,W ; MOVWF TIMER_HIGH ; MOVLW LOW(C1) ; START NEW CALCULATIONS MOVWF CALCPOINTER ; GOTO WAIT4UPFLANK ; ;-------------------------------------------------------------------------------------------------------------------------------------- DELAYED_JUMP GOTO $+1 ; GOTO PWM_UPFLANK_1 ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; MAIN PROGRAM CODE ;-------------------------------------------------------------------------------------------------------------------------------------- C1 ; MAIN PROGRAM CODE GOES HERE (NOT MORE THAN 32 INSTRUCTION CYCLES) RETLW LOW(C2) ; THIS PART OF CALCULATIONS DONE ;-------------------------------------------------------------------------------------------------------------------------------------- C2 ; ..MORE PROGRAM CODE GOES HERE (NOT MORE THAN 32 INSTRUCTION CYCLES) RETLW LOW(C3) ; THIS PART OF CALCULATIONS DONE ;-------------------------------------------------------------------------------------------------------------------------------------- C3 ; ..MORE PROGRAM CODE GOES HERE (NOT MORE THAN 32 INSTRUCTION CYCLES) RETLW LOW(C4) ; THIS PART OF CALCULATIONS DONE ;-------------------------------------------------------------------------------------------------------------------------------------- C4 ; ..MORE PROGRAM CODE GOES HERE (NOT MORE THAN 32 INSTRUCTION CYCLES) RETLW LOW(C5) ; THIS PART OF CALCULATIONS DONE ;-------------------------------------------------------------------------------------------------------------------------------------- C5 ; NOTE: DO NOT CHANGE THE DUTY CYCLE FROM MINIMUM TO MAXIMUM (OR VICE VERSA) INSTANTLY, ; PUT SOME AVERAGING CODE HERE (OR THE PULSE WIDTH MAY BE AFFECTED TEMPORARILY) MOVLW D'208' ; SET A1:A0 = PWM HIGH TIME = 2000 = 7:208 MOVWF A0 ; MOVLW D'7' ; MOVWF A1 ; ; NOW A IS NEW PWM HIGH TIME (TO BE USED IN PWM CODE) MOVLW D'16' ; SET B1:B0 = PWM PERIOD = 10000 = 39:16 MOVWF B0 ; MOVLW D'39' ; MOVWF B1 ; ; NOW CALCULATE B, THE NUMBER OF INSTRUCTIONS THAT PWM OUTPUT IS LOW PER PWM PERIOD MOVF A0,W ; B = B - A SUBWF B0,F ; MOVF A1,W ; SKPC ; INCFSZ A1,W ; SUBWF B1,F ; ; NOW B IS NEW PWM LOW TIME (TO BE USED IN PWM CODE) RETLW LOW(C0) ; ALL CALCULATIONS DONE ! ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- ORG H'100' ; ADDRESS BEYOND THE JUMP RANGE OF A MODIFY PCL INSTRUCTION C6 ; WE CANNOT MODIFY THE PCL REGISTER TO JUMP HERE DIRECTLY, BUT WE CAN PLACE A GOTO POINTING TO ; HERE IN THE LOWER PART OF THE MEMORY AND JUMP TO THE GOTO INSTEAD ; ..MORE PROGRAM CODE GOES HERE (NOT MORE THAN 32 INSTRUCTION CYCLES) RETLW LOW(C0) ; THIS PART OF CALCULATIONS DONE ;-------------------------------------------------------------------------------------------------------------------------------------- END ; TELL THE ASSEMBLER TO STOP ;--------------------------------------------------------------------------------------------------------------------------------------
file: /Techref/member/AT-planet-T9/superpwm.htm, 24KB, , updated: 2010/10/12 23:34, local time: 2024/11/25 17:12,
owner: AT-planet-T9,
18.226.104.30:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/Techref/member/AT-planet-T9/superpwm.htm"> Super Bit-Bang PWM for 12-bit PIC</A> |
Did you find what you needed? |