1 2 list p=18f26k22 3 include <p18f26k22.inc> 4 include <coff.inc> 5 6 CONFIG WDTEN=OFF, PBADEN = OFF 7 8 ;; The purpose of this program is to test gpsim's ability to simulate a 9 ;; pic with more than two PWM channels. The 18F26k22 is such a device. 10 11 ;; CCP1 is set with a 50% duty cycle and used to test timing 12 ;; CCP2 is set with a 25% duty cycle and used to test order 13 ;; CCP3 is set with a 75% duty cycle 14 ;; CCP4 is set beyond the period and tied to INT0 to test 100% duty 15 ;; CCP5 is set with a 75% duty cycle to test two simultaneous PWM edges 16 17 errorlevel -302 18 19; Printf Command 20.command macro x 21 .direct "C", x 22 endm 23 24;---------------------------------------------------------------------- 25;---------------------------------------------------------------------- 26;GPR_DATA UDATA 27GPR_DATA UDATA 0 28 29t0_1 RES 1 30t0_2 RES 1 31x RES 1 32t1 RES 1 33t2 RES 1 34avg_lo RES 1 35avg_hi RES 1 36w_temp RES 1 37status_temp RES 1 38 39 40;---------------------------------------------------------------------- 41; ********************* RESET VECTOR LOCATION ******************** 42;---------------------------------------------------------------------- 43RESET_VECTOR CODE 0x000 ; processor reset vector 44 goto start ; go to beginning of program 45 46INTERRUPT CODE 0x008 47 ;; 48 ;; Interrupt 49 ;; 50 movwf w_temp 51 swapf STATUS,W 52 movwf status_temp 53 54 .assert "'*** FAILED 18f26k22 unexpected interrupt'" 55 nop 56 57check: 58 swapf status_temp,w 59 movwf STATUS 60 swapf w_temp,F 61 swapf w_temp,W 62 retfie 63 64 65 66 67 .sim "node pwm3" 68 .sim "attach pwm3 portb5 portb1" 69 .sim "scope.ch0 = 'portc2'" 70 .sim "scope.ch1 = 'portc1'" 71 .sim "scope.ch2 = 'portb5'" 72 .sim "scope.ch3 = 'portb0'" 73 74;---------------------------------------------------------------------- 75; ******************* MAIN CODE START LOCATION ****************** 76;---------------------------------------------------------------------- 77MAIN CODE 78start: 79 BANKSEL CCP1CON 80 clrf ANSELA 81 clrf ANSELC 82 clrf CCP1CON ; CCP Module is off 83 clrf CCP2CON ; CCP Module is off 84 clrf CCP3CON ; CCP Module is off 85 clrf CCP4CON ; CCP Module is off 86 clrf CCP5CON ; CCP Module is off 87 clrf TMR2 ; Clear Timer2 88 clrf TMR0L ; Clear Timer0 89 movlw 0x1F ; 90 movwf CCPR1L ; CCP1 Duty Cycle is 50% of PWM Period 91 movlw 0x0F ; 92 movwf CCPR2L ; CCP2 Duty Cycle is 25% of PWM Period 93 movlw 0x4F ; 94 movwf CCPR3L ; CCP3 Duty Cycle is 125% of PWM Period 95 movlw 0x2F ; 96 movwf CCPR4L ; CCP4 Duty Cycle is 75% of PWM Period 97 movlw 0x2F ; 98 movwf CCPR5L ; CCP5 Duty Cycle is 75% of PWM Period 99 clrf INTCON ; Disable interrupts and clear T0IF 100 clrf INTCON2 ; external interrupt pins trigger on falling edge 101 movlw 0x3F ; 102 movwf PR2 ; 103 bcf TRISC, 2 ; Make pin output CCP1 104 bcf TRISC, 1 ; Make pin output CCP2 105 bcf TRISB, 5 ; Make pin output CCP3 106 bcf TRISB, 0 ; Make pin output CCP4 107 bcf TRISA, 4 ; Make pin output CCP5 108 clrf PIE1 ; Disable peripheral interrupts 109 movlw 0x83 ; Tmr0 internal clock prescaler 16 110 movwf T0CON 111 clrf PIR1 ; Clear peripheral interrupts Flags 112 movlw 0x2C ; PWM mode, 2 LSbs of Duty cycle = 10 113 movwf CCP1CON ; 114 movlw 0x2C ; PWM mode, 2 LSbs of Duty cycle = 10 115 movwf CCP2CON ; 116 movwf CCP3CON ; 117 movwf CCP4CON ; 118 movwf CCP5CON ; 119 .assert "ccpr1l != ccpr1h, '*** FAILED pwm_26k22 CCPR1H before TMR2 reset'" 120 nop 121 movlw 0x06 ; Start Timer2 prescaler is 16 (to match TMR0) 122 movwf T2CON 123; 124; The CCP1 interrupt is disabled, 125; do polling on the TMR2 Interrupt flag bit 126; 127PWM_Period_Match 128 btfss PIR1, TMR2IF 129 goto PWM_Period_Match 130 clrf TMR0L 131 132 .assert "ccpr1l == ccpr1h, '*** FAILED pwm_26k22 CCPR1H loaded from CCPR1H'" 133 nop 134 135 bcf INTCON3,INT1IF ; INT1 is tied to CCP3, which should remain always high 136 137 .assert "(portc & 0x6) == 0x6, '*** FAILED pwm_26k22 CCP1, CCP2 are high'" 138 nop 139 ; loop until CCP2 goes low 140 btfsc PORTC,1 141 goto $-1 142 .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP2 duty cycle'" 143 nop 144 ; loop until CCP1 goes low 145 btfsc PORTC,2 146 goto $-1 147 .assert "tmr0 == 0x1f, '*** FAILED pwm_26k22 CCP1 duty cycle'" 148 nop 149 ; loop until CCP4 goes low 150 btfsc PORTB,0 151 goto $-1 152 .assert "tmr0 == 0x2f, '*** FAILED pwm_26k22 CCP3 duty cycle'" 153 nop 154; 155; Wait for end of PWM cycle 156; 157 bcf PIR1, TMR2IF 158 btfss PIR1, TMR2IF 159 goto $-1 160 161 .assert "(intcon3 & 0x01) == 0, '*** FAILED pwm_26k22 PWM duty > PR2 : pin goes low'" 162 nop 163 .assert "tmr0 == 0x3f, '*** FAILED pwm_26k22 TMR2 period'" 164 nop 165; 166; Increase TMR2 but less than first duty cycle 167; 168 movlw 0x0D 169 movwf TMR2 ; update timer 170 clrf TMR0L 171 172 ; loop until CCP1 goes low 173 btfsc PORTC,2 174 goto $-1 175 176 .assert "(portc & 0x6) == 0x0, '*** FAILED pwm_26k22 TMR2 put, only change period'" 177 nop 178 179 ; loop until CCP5 goes low 180 btfsc PORTA,4 181 goto $-1 182 183 .assert "tmr0 == 0x22, '*** FAILED pwm_26k22 TMR2 put, only change period'" 184 nop 185 186 bcf PIR1, TMR2IF 187 btfss PIR1, TMR2IF 188 goto $-1 189 .assert "tmr0 == 0x33, '*** FAILED pwm_26k22 TMR2 put, only change period'" 190 nop 191; 192; Increase TMR2 between first and second duty cycle 193; 194 clrf TMR0L 195 196 movlw 0x1D 197 movwf TMR2 ; update timer 198 199 ; loop until CCP1 goes low 200 btfsc PORTC,2 201 goto $-1 202 203 .assert "(portc & 0x6) == 0x2, '*** FAILED pwm_26k22 TMR2 put, between duty cycles'" 204 nop 205 206 bcf PIR1, TMR2IF 207 btfss PIR1, TMR2IF 208 goto $-1 209 .assert "tmr0 == 0x23, '*** FAILED pwm_26k22 TMR2 put, between duty cycles'" 210 nop 211; 212; in this test TMR2 > PR2, expect TMR2 to wrap around 213; 214 movlw 0x84 ; Tmr0 internal clock prescaler 32 215 movwf T0CON 216 clrf TMR0L 217 218 movlw 0x40 219 movwf TMR2 ; update timer 220 221 ; loop until CCP1 goes low 222 btfsc PORTC,2 223 goto $-1 224 .assert "tmr0 == 0x6F, '*** FAILED pwm_26k22 CCP1 duty cycle after wrap'" 225 nop 226 227 bcf PIR1, TMR2IF 228 btfss PIR1, TMR2IF 229 goto $-1 230 231 .assert "tmr0 == 0x80, '*** FAILED pwm_26k22 TMR2 > PR2 causes wrap'" 232 nop 233 234; 235; write reduced PR2 236; 237 clrf TMR0L 238 239 ; loop until CCP2 goes low 240 btfsc PORTC,1 241 goto $-1 242 .assert "tmr0 == 0x07, '*** FAILED pwm_26k22 CCP2 duty cycle PR2 to 0x20'" 243 nop 244 ; loop until CCP1 goes low 245 btfsc PORTC,2 246 goto $-1 247 .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP1 duty cycle PR2 to 0x20'" 248 nop 249 movlw 0x20 250 movwf PR2 251; 252; Wait for end of PWM cycle 253; 254 bcf PIR1, TMR2IF 255 btfss PIR1, TMR2IF 256 goto $-1 257 .assert "tmr0 == 0x10, '*** FAILED pwm_26k22 TMR2 period PR2 to 0x20'" 258 nop 259 260; 261; write reduced PR2 < TRM2 262; 263 clrf TMR0L 264 265 ; loop until CCP2 goes low 266 btfsc PORTC,1 267 goto $-1 268 .assert "tmr0 == 0x07, '*** FAILED pwm_26k22 CCP2 duty cycle PR2 to 0x10'" 269 nop 270 ; loop until CCP1 goes low 271 btfsc PORTC,2 272 goto $-1 273 .assert "tmr0 == 0x0f, '*** FAILED pwm_26k22 CCP1 duty cycle PR2 to 0x10'" 274 nop 275 movlw 0x10 276 movwf PR2 277; 278; Wait for end of PWM cycle 279; 280 bcf PIR1, TMR2IF 281 btfss PIR1, TMR2IF 282 goto $-1 283 .assert "tmr0 == 0x88, '*** FAILED pwm_26k22 TMR2 period PR2 to 0x10 wraps'" 284 nop 285 286 clrf CCP1CON ; turn off PWM 287 clrf CCP2CON ; turn off PWM 288 clrf CCP3CON ; turn off PWM 289 clrf CCP4CON ; turn off PWM 290 clrf CCP5CON ; turn off PWM 291 292 call use_t4 293 294 295 .assert "'*** PASSED pwm_26k22 PWM test'" 296 goto $-1 297 298use_t4: 299 movlw 0x0f ; set CCP2 outputs to all pins 300 movwf PSTR2CON 301 bsf CCPTMRS0,C2TSEL0 ; select T4 for CCP2 302 movlw 0x3F ; 303 movwf PR4 ; 304 movlw 0x1F ; 305 movwf CCPR2L ; Duty Cycle is 50% of PWM Period 306 movlw 0x06 ; Start Timer4 prescaler is 16 (to match TMR0, of course!) 307 clrf T2CON ; turn off T2 308 movwf T4CON 309 movlw 0x2C ; PWM mode, 2 LSbs of Duty cycle = 10 310 movwf CCP2CON ; 311 ; loop until CCP2 goes low 312 btfsc PORTC,1 313 goto $-1 314 315 return 316 end 317