📄 penasm.asm
字号:
;******************************************************************************
;
; Software License Agreement
;
; The software supplied herewith by Microchip Technology
; Incorporated (the "Company") is intended and supplied to you, the
; Company抯 customer, for use solely and exclusively on Microchip
; products. The software is owned by the Company and/or its supplier,
; and is protected under applicable copyright laws. All rights are
; reserved. Any use in violation of the foregoing restrictions may
; subject the user to criminal sanctions under applicable laws, as
; well as to civil liability for the breach of the terms and
; conditions of this license.
;
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
; WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
; TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
; PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
; IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;
;*********************************************************************************
;
; File: PenASM.asm
; Date: 14 October, 2004 Original code
; Version: 1.00
;
;*********************************************************************************
list p=16f684 ; list directive to define processor
#include <p16F684.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BOD_OFF & _MCLRE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _FCMEN_ON
#DEFINE WORK_TEMP 20H ;CAN BE 20H OR 80H NEED TO RESERVE BOTH LOCATIONS
#DEFINE STATUS_TEMP 21H ;FOR STORING THE TEMP DIRECTORY WHILE IN THE INTERRUPT SERVICE ROUTINE
#DEFINE EN0 22H ;CURRENT ERROR TERM
#DEFINE EN1 23H ;PREVIOUS ERROR TERM
#DEFINE EN2 24H ;TWO ERROR TERMS AGO
#DEFINE EN3 25H ;THREE ERROR TERMS AGO
#DEFINE KP 26H ;PROPORTIONAL CONSTANT
#DEFINE KI 27H ;INTERGRAL CONSTANT
#DEFINE KD 28H ;DERIVATIVE CONSTANT
#DEFINE AARGB0 29H ;USED IN THE MULTIPLY ROUTINE 8 BIT MULTIPLICAND AND HIGH BYTE OF 16 BIT RESULT
#DEFINE AARGB1 2AH ;LOWER BYTE OF THE 16 BIT RESULT FOR THE MULTIPY ROUTINE
#DEFINE BARGB0 2BH ;8 BIT MULTIPLIER FOR THE MULTIPLY ROUTINE
#DEFINE SIGN 2CH ;ONLY USED IN THE MULTIPLY ROUTINE
#DEFINE TEMPB3 2DH ;ONLY USED IN THE MULTIPLY ROUTINE
#DEFINE LOOPCOUNT 2EH ;ONLY USED IN THE MULTIPLY ROUTINE
#DEFINE INT_TERM_H 2FH ;INTEGRAL TERM UPPER BYTE
#DEFINE INT_TERM_L 30H ;INTEGRAL TERM LOWER BYTE
#DEFINE DER_TERM_H 31H ;DERIVATIVE TERM HIGH BYTE
#DEFINE DER_TERM_L 32H ;DERIVATIVE TERM LOW BYTE
#DEFINE TEMP 33H ;TEMP REGISTER ONLY USED IN THE INTERRUPT ROUTINE
#DEFINE TEMP2 34H ;ONLY USED OUTSIDE OF THE INTERRUPT
#DEFINE DO_PID 35H ;STATUS FLAG SET IN THE INTERRUPT ROUTINE AND CLEARED AT THE END OF THE PID LOOP
;WHEN SET THE PID LOOP NEEDS TO BE RUN
BANK1 MACRO
BSF STATUS, RP0 ;MACRO TO SELECT BANK 1
ENDM
BANK0 MACRO
BCF STATUS, RP0 ;MACRO TO SELECT BANK 0
ENDM
DELAY MACRO A
MOVLW A ;MACRO USED FOR GENERATING A DELAY
MOVWF TEMP2
CALL DELAY_SUB
ENDM
ORG 0x000 ;RESET VECTOR
BANK0
GOTO INIT ;GO TO BEGINING OF THE PROGRAM
;INTERRUPT SERVICE ROUTINE
;INTERRUPT WILL RUN THE PID LOOP BASED OFF THE TMR0 INTERRUPT
;IT IS DESIRED THAT THIS LOOP WILL HAPPEN AT 256Hz OR 3.9mSECONDS
;WITH THE 8MHz OSCILLATOR WE HAVE AN INSTRUCTION TIME OF 0.5uSECONDS
;WITH THE TMR0 PRESCALER SET TO 32 TMR0 WILL INCREMENT EVERY 16uSECONDS
;THE TMR0 INTERRUPT FLAG IS SET EVERY TIME THE COUNTER OVERFLOWS
;SO WE NEED TO PRELOAD THE TMR0 TO 256 - (3.9mSECONDS/16uSENCONDS) = 11
ORG 0x004 ;INTERRUPT VECTOR LOCATION
MOVWF WORK_TEMP ;SAVE MY WORKING DIRECTORY, CAN BE BANK 0 OR 1
MOVF STATUS, W ;GET A COPY OF MY STATUS REGISTER
BANK0
MOVWF STATUS_TEMP ;STORE THE IN BANK 0
MOVLW .11 ;RESET THE TMRO INTERRUPT TO HAPPEN IN 3.9mSECONDS 256Hz
;
MOVWF TMR0
BSF PORTA, 4
BSF ADCON0, GO ;DO AN A/D CONVERSION
AD_CONVERSION
BTFSC ADCON0, NOT_DONE
GOTO AD_CONVERSION ;STAY IN THIS LOOP UNTIL THE A/D CONVERSION IS FINISHED
MOVF ADRESH, W ;TAKE THE A/D'S 8 MSB AND SET THEM AS THE CURRENT ERROR
MOVWF EN0
MOVLW B'10000000' ;SUBTRACK THE DC OFFSET (128 DECIMAL) FROM EN0
;2'S COMPLEMENT OF 128 DECIMAL IS B'10000000' OR -128 DECIMAL
ADDWF EN0, F ;EN0 IS NOW SIGNED AN EN0=127 CORRESPONDS TO AN ANGLE OF 30 DEGREES
;EN0=-128 EQUALS AN ANGLE OF -30 DEGREES
INCF DO_PID, F ;ENABLE THE PID UPDATE
BTFSC EN0, 7
GOTO CHECK_NEG
CHECK_POS ;TEST TO SEE IF THE ERROR VALUE IS TOO HIGH TO TRY AND COMPENSATE FOR
; MOVLW B'11101011' ;5 DEGREES = 21 DECIMAL = B'00010101' 2'S COMP IS B'11101011'
; MOVLW B'11010110' ;10 DEGREES = 42 DECIMAL = B'00101010' 2'S COMP IS B'11010110'
MOVLW B'10101100' ;20 DEGREES = 84 DECIMAL = B'01010100' 2'S COMP IS B'10101100'
ADDWF EN0, W ;
MOVWF TEMP
BTFSS TEMP, 7 ;IF BIT 7 IS SET THE RESULT OF THE ADD IS NEGATIVE WHICH IS OK
GOTO STOP_CONTROL ;POSITIVE ERROR IS TOO BIG
GOTO LEAVE_INT ;POSITIVE ERROR IS OK
CHECK_NEG ;TEST TO SEE IF THE ERROR VALUE IS TOO LOW TO TRY AND COMPENSATE FOR
; MOVLW B'00010101' ;-5 DEGREES = -21 DECIMAL = B'11101011' 2'S COMP IS B'00010101'
; MOVLW B'00101010' ;-10 DEGREES = -42 DECIMAL = B'11101011' 2'S COMP IS B'00101010'
MOVLW B'01010100' ;-20 DEGREES = -84 DECIMAL = B'10101100' 2'S COMP IS B'01010100'
ADDWF EN0, W ;
MOVWF TEMP
BTFSS TEMP, 7 ;IF BIT 7 IS SET THE RESULT OF THE ADD IS NEGATIVE WHICH NOT OK
GOTO LEAVE_INT ;POSITIVE ERROR IS OK
STOP_CONTROL
CLRF DO_PID ;ERROR IS TOO BIG STOP ALL CONTROL DON'T UPDATE PID CONSTANTS
CLRF CCPR1L ;TURN THE PWM OFF
BCF CCP1CON, 5
BCF CCP1CON, 4
CLRF INT_TERM_H ;CLEAR ALL VARIABLES THAT ARE ALREADY SET
CLRF INT_TERM_L
CLRF EN0
CLRF EN1
CLRF EN2
CLRF EN3
CLRF DER_TERM_L
CLRF DER_TERM_H
LEAVE_INT
BCF INTCON, T0IF ;CLEAR MY INTERRUPT FLAG
MOVF STATUS_TEMP, W ;REPLACE THE STATUS REGISTER
MOVWF STATUS ;
MOVF WORK_TEMP, W ;REPLACE THE WORKING REGISTER
BCF INTCON, T0IF ;CLEAR THE TMR0 INTERRUPT FLAG
RETFIE ;RETURN FROM INTERRUPT
INIT
BANK0
CLRF PORTA
CLRF PORTC
MOVLW B'00000001' ;A/D LEFT JUSTIFIED, VDD IS VOLTAGE REFERENCE
MOVWF ADCON0 ;A/D IS ON
CLRF CCPR1L ;SET PWM DUTY CYCLE TO ZERO
BCF CCPR1H, 5 ;
BCF CCPR1H, 4 ;
MOVLW B'01001100' ;FULL BRIDGE FORWARD
MOVWF CCP1CON ;PWM MODE P1A, P1B, P1C AND P1D ACTIVE HIGH
CLRF ECCPAS ;DISABLE THE AUTO-SHUTDOWN
MOVLW B'00000100' ;TMR2 POSTSCALER=1 TMR2 ON PRESCALER=1
MOVWF T2CON
MOVLW B'00000111' ;COMPARATORS ARE OFF
MOVWF CMCON0
BANK1
MOVLW B'00101101' ;SET RA4 AND RA1 AS OUTPUTS
MOVWF TRISA
MOVLW B'00000011' ;SET RC0 AND RC1 AS INPUTS
MOVWF TRISC
MOVLW B'11000100' ;PORTA PULL-UP DISABLED, INT EDGE, TOCS INT, T0SE LOW-HIGH
MOVWF OPTION_REG ;PSA TMR0, RATE 1:32
MOVLW B'10100000' ;ENABLE GLOBAL INTERRUPTS
MOVWF INTCON ;ENABLE TMR0 INTERRPUT
CLRF PIE1 ;DISABLE ALL PERIPHERAL INTERRUPTS
CLRF PCON ;DISABLE ULPWUE AND SBODEN
MOVLW B'01111111' ;SELECT 8MHz
MOVWF OSCCON
CLRF IOCA ;DISABLE ALL INTERRUPT ON CHANGE FOR PORT A
MOVLW B'00110101' ;4 ANALOG INPUTS AN0,AN2,AN4 AND AN5
MOVWF ANSEL
MOVLW B'01010000' ;SELECT A/D CONVERSION CLOCK FOSC/16
MOVWF ADCON1 ;CONVERSION TIME IS 2uSECS
MOVWF B'00111111' ;SETS THE PWM FREQ TO 32kHz IF TRM2 PS=1
MOVWF PR2
BANK0
CLRF INT_TERM_H ;CLEAR THE INTEGRAL TERM AND RESET ALL PREVIOUS ERRORS
CLRF INT_TERM_L
CLRF EN0
CLRF EN1
CLRF EN2
CLRF EN3
READ_CONSTANTS ;USING THE 10 BIT A/D IGNORE ADRESHL GIVING AN 8 BIT a/d
MOVLW B'00010001' ;SELECT AN4(KI)LEFT JUSTIFIED
MOVWF ADCON0
DELAY .40 ;WAIT A MINIMUM OF 20 uSECONDS BEFORE STARTING AN A/D CONVERSION
BSF ADCON0, GO ;START THE CONVERSION
WAIT_FOR_KI
BTFSC ADCON0, NOT_DONE
GOTO WAIT_FOR_KI
MOVF ADRESH, W
MOVWF KI ;TAKE THE 8BIT RESULT AND SAVE IT IGNORE THE 2 LSB
RRF KI, F ;NEED TO CONVERT KI INTO A SIGNED MULTIPLIER
BCF KI, 7 ;MAKE SURE ITS A POSITIVE NUMBER
MOVLW B'00010101' ;SELECT AN5(KD)LEFT JUSTIFIED
MOVWF ADCON0
DELAY .40 ;WAIT A MINIMUM OF 20 uSECONDS BEFORE STARTING AN A/D CONVERSION
BSF ADCON0, GO ;START THE CONVERSION
WAIT_FOR_KD
BTFSC ADCON0, NOT_DONE
GOTO WAIT_FOR_KD
MOVF ADRESH, W
MOVWF KD ;TAKE THE 8BIT RESULT AND SAVE IT IGNORE THE 2 LSB
RRF KD, F ;NEED TO CONVERT KD INTO A SIGNED MULTIPLIER
BCF KD, 7 ;MAKE SURE ITS A POSITIVE NUMBER
MOVLW B'00001001' ;SELECT AN2(KP)LEFT JUSTIFIED
MOVWF ADCON0
DELAY .40 ;WAIT A MINIMUM OF 20 uSECONDS BEFORE STARTING AN A/D CONVERSION
BSF ADCON0, GO ;START THE CONVERSION
WAIT_FOR_KP
BTFSC ADCON0, NOT_DONE
GOTO WAIT_FOR_KP
MOVF ADRESH, W
MOVWF KP ;TAKE THE 8BIT RESULT AND SAVE IT IGNORE THE 2 LSB
RRF KP, F ;NEED TO CONVERT KP INTO A SIGNED MULTIPLIER
BCF KP, 7 ;MAKE SURE ITS A POSITIVE NUMBER
MOVLW B'00000001' ;DONE READING THE CONSTANTS SET THE A/D UP FOR
MOVWF ADCON0 ;AN0(THE ANGLE POTENTIOMETER)
MAIN
MOVF DO_PID, W ;TEST TO SEE IF A PID TERMS NEED TO BE UPDATED
BTFSC STATUS, Z
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -