I'm trying to make PSMC1 in a 16F1782 work as a simple PWM generator. I've been banging my head against the wall for the past few days and figured that I had best ask for help.
I am using both MPLAB 8.92 and MPLAB-X 4.05 with a PICkit3 and either the target processor directly or using a AC244064 Emulation Debug Header attached to the target board.
The problem is that the timer in the module doesn't seem to be continuing to count. I have tried a variety of things to try and nail this down: I can pause the debug session, pre-load either / both the high or low byte of the timer registers with some arbitrary value, then restart the debug session. The timer always shows up as 0x0001 when the debug session is halted again and bit _PSMC1LD always goes LO.
I've tried both clocking from Fosc and the internal 64 MHz clock. Fosc is 4 MHz for this project. Although my board is laid out to use output PSMC1E, I've also tried it with the pin shown in the example code: PSMC1A.
I'm obviously doing something wrong and I'm hoping that some kind soul can point out my error.
The following contains two sections: first are the defines and initial register values that I write into the various PSMC registers during initialization, the second section is the disassembly output as shown in MPLAB-X v4.05. Note that in the disassembly listing, each instruction is shown twice: first: then shown as written in my code, then the disassembled code
;PSMC CONTROL REGISTER
#define _P1MODE0 PSMC1CON,0 ;0000= 1 PWM 0001= same /w Comp o/p
#define _P1MODE1 PSMC1CON,1 ;0010= PushPull 0011= same /w Comp o/p
#define _P1MODE2 PSMC1CON,2 ;0100= P-P /w 4 o/p 0101= same /w Comp o/p
#define _P1MODE3 PSMC1CON,3 ;0110= PulseSkip PWM 0111= same /w Comp o/p
;1000= ECCP Full Br Rev 1001 same /w For
;1010= Fix DC, Var Freq 1011 same /w Comp o/p
;1100= 3ph PWM 1101, 1110, 1111 reserved
#define _P1DBRE PSMC1CON,4 ;Rise Edge Dead Band Enable 1= Enabled
#define _P1DBFE PSMC1CON,5 ;Fall Edge Dead Band Enable 1= Enabled
#define _PSMC1LD PSMC1CON,6 ;0= Buffer Update done 1= Ready to Update
#define _PSMC1EN PSMC1CON,7 ;Enable: 1= Enabled
PSMC1CON_INIT EQU b'11000000' ;enabled, 1 PWM, load steering & timing regs
;PSMC OUTPUT ENABLE CONTROL
#define _P1OEA PSMC1OEN,0 ;o/p Enable A RC0
#define _P1OEB PSMC1OEN,1 ; B RC1
#define _P1OEC PSMC1OEN,2 ; C RC2
#define _P1OED PSMC1OEN,3 ; D RC3
#define _P1OEE PSMC1OEN,4 ; E RC4
#define _P1OEF PSMC1OEN,5 ; F RC5
PSMC1OEN_INIT EQU b'00010000' ;pin RC4
;PSMC STEERING CONTROL Zero in any bit position (A-F) disables that bit
#define _P1STRA PSMC1STR0,0 ;P1MODE= 000x (1ph) o/p
;P1MODE= 1100 (3ph) A,D HI B,C,E,F LO
#define _P1STRB PSMC1STR0,1 ;P1MODE= 0000 (1ph)
;P1MODE= 0001 (1ph) comp o/p
;P1MODE= 1100 (3ph) A,F HI C,C,D,E LO
#define _P1STRC PSMC1STR0,2 ;P1MODE= 000x (1ph) o/p
;P1MODE= 1100 (3ph) C,F HI A,B,D,E LO
#define _P1STRD PSMC1STR0,3 ;P1MODE= 000O (1ph) o/p
;P1MODE= 0001 (1ph) comp o/p
;P1MODE= 1100 (3ph) B,C HI A,D,E,F LO
#define _P1STRE PSMC1STR0,4 ;P1MODE= 000x (1ph) o/p
;P1MODE= 1100 (3ph) B,E HI A,C,D,F LO
#define _P1STRF PSMC1STR0,5 ;P1MODE= 0000 (1ph) o/p
;P1MODE= 0001 (1ph) comp o/p
;P1MODE= 1100 (3ph) D,E HI A,B,C,F LO
;Note: lowest bit takes precedence for 3ph
PSMC1STR0_INIT EQU b'00010000' ;pin rc4
;PSMC POLARITY CONTROL
#define _P1POLA PSMC1POL,0 ;o/p A Polarity 0= Act HI 1= Act LO
#define _P1POLB PSMC1POL,1 ; B
#define _P1POLC PSMC1POL,2 ; C
#define _P1POLD PSMC1POL,3 ; D
#define _P1POLE PSMC1POL,4 ; E
#define _P1POLF PSMC1POL,5 ; F
#define _P1INPOL PSMC1POL,6 ;PSMC1 i/p Polarity 0= Act HI 1= Act LO
PSMC1POL_INIT EQU b'00000000' ;active HI
;PSMC MODULATION CONTROL
#define _P1MSRC0 PSMC1MDL,0 ;Modulation Source: 0000= P1MDLBIT
#define _P1MSRC1 PSMC1MDL,1 ;0001= C1OUT 0010= C2OUT 0011= C3OUT
#define _P1MSRC2 PSMC1MDL,2 ;1000 reserved 0101= CCP1 0110= CCP2
#define _P1MSRC3 PSMC1MDL,3 ;0111 reserved 1000= PSMC1IN pin
#define _P1MDLBIT PSMC1MDL,5 ;
#define _P1MDLPOL PSMC1MDL,6 ;Mod Select Polarity 0= Mod=1 1= Mod=0
#define _P1MDLEN PSMC1MDL,7 ;Mod enable: 0= No Modulation
;1= active when Mod signal
PSMC1MDL_INIT EQU b'00000000' ;no modulation
;PSMC1 SYNCHRONIZATION CONTROL
#define _P1SYNC0 PSMC1SYNC,0 ;00= Sync /w Period Event 01= reserved
#define _P1SYNC1 PSMC1SYNC,1 ;10= Sync /w PSMC2 module 11= reserved
PSMC1SYNC_INIT EQU b'00000000' ;sync /w period event
;PSMC CLOCK CONTROL
#define _P1CSRC0 PSMC1CLK,0 ;00= Fosc 01= 64MHz
#define _P1CSRC1 PSMC1CLK,1 ;10= PSMC1clk pin 11= reserved
#define _P1CPRE0 PSMC1CLK,4 ;00= Clk /1 01= Clk /2
#define _P1CPRE1 PSMC1CLK,5 ;10= Clk /4 11= Clk /8
PSMC1CLK_INIT EQU b'00000000' ;Fosc /1
;PSMC BLANKING CONTROL
#define _P1REBM0 PSMC1BLNK,0 ;Rise Edge Blanking 00= None 01= Immediate
#define _P1REBM1 PSMC1BLNK,1 ; 10= reserved 11= reserved
#define _P1FEBM0 PSMC1BLNK,4 ;Fall Edge Blanking 00= None 01= Immediate
#define _P1FEBM1 PSMC1BLNK,5 ; 10= reserved 11= reserved
PSMC1BLNK_INIT EQU b'00000000' ;no blanking
;PSMC RISING EDGE BLANKED SOURCE 0= not source of blanking 1= source blanks
#define _P1REBSC1 PSMC1REBS,1 ;Blanked from sync_C1OUT
#define _P1REBSC2 PSMC1REBS,2 ;Blanked from sync_C2OUT
#define _P1REBSC3 PSMC1REBS,3 ;Blanked from sync_C3OUT
#define _P1REBSIN PSMC1REBS,7 ;Blanked from PSMC1IN pin
PSMC1REBS_INIT EQU b'00000000' ;no blanking
;PSMC FALLING EDGE BLANKED SOURCE 0= not source of blanking 1= source blanks
#define _P1FEBSC1 PSMC1FEBS,1 ;Blanked from sync_C1OUT
#define _P1FEBSC2 PSMC1FEBS,2 ;Blanked from sync_C2OUT
#define _P1FEBSC3 PSMC1FEBS,3 ;Blanked from sync_C3OUT
#define _P1FEBSIN PSMC1FEBS,7 ;Blanked from PSMC1IN pin
PSMC1FEBS_INIT EQU b'00000000' ;no blanking
;PSMC PHASE SOURCE (Rise Edge Event) 0 means that signal does NOT cause event
#define _P1PHST PSMC1PHS,0 ;1= Rise Edge Event when PSMCxTMR = PSMCxPH
#define _P1PHSC1 PSMC1PHS,1 ;1= Rise Edge Event when sync_C1OUT goes true
#define _P1PHSC2 PSMC1PHS,2 ;1= Rise Edge Event when sync_C2OUT goes true
#define _P1PHSC3 PSMC1PHS,3 ;1= Rise Edge Event when sync_C3OUT goes true
#define _P1PHSIN PSMC1PHS,7 ;1= Rise Edge Event when PSMC1IN pin goes true
PSMC1PHS_INIT EQU b'00000001' ;from timebase
;PSMC DUTY CYCLE SOURCE (Fall Edge Event) 0 means that signal does NOT cause event
#define _P1DCST PSMC1DCS,0 ;1= Fall Edge Event when PSMCxTMR = PSMCxDC
#define _P1DCSC1 PSMC1DCS,1 ;1= Fall Edge Event when sync_C1OUT goes true
#define _P1DCSC2 PSMC1DCS,2 ;1= Fall Edge Event when sync_C2OUT goes true
#define _P1DCSC3 PSMC1DCS,3 ;1= Fall Edge Event when sync_C3OUT goes true
#define _P1DCSIN PSMC1DCS,7 ;1= Fall Edge Event when PSMC1IN pin goes true
PSMC1DCS_INIT EQU b'00000001' ;from timebase
;PSMC PERIOD SOURCE 0 means that signal does NOT cause event
#define _P1PRST PSMC1PRS,0 ;1= Period Event when PSMCxTMR = PSMCxPR
#define _P1PRSC1 PSMC1PRS,1 ;1= Period Event when sync_C1OUT goes true
#define _P1PRSC2 PSMC1PRS,2 ;1= Period Event when sync_C2OUT goes true
#define _P1PRSC3 PSMC1PRS,3 ;1= Period Event when sync_C3OUT goes true
#define _P1PRSIN PSMC1PRS,7 ;1= Period Event when PSMC1IN pin goes true
PSMC1PRS_INIT EQU b'00000001' ;from timebase
;PSMC AUTO-SHUTDOWN CONTROL ("AS")
#define _P1ASDOV PSMC1ASDC,0 ;AS OverRide: 0= No Effect 1=
#define _P1ARSEN PSMC1ASDC,5 ;AS Auto-Restart 1= auto 0= require restart
#define _P1ASDEN PSMC1ASDC,6 ;AS Enable: 0= No AS 1= Enabled
#define _P1ASE PSMC1ASDC,7 ;AS Status: 0= normal 1= Shutdown occurred
PSMC1ASDC_INIT EQU b'00000000' ;no auto shutdown
;PSMC AUTO-SHUTDOWN OUTPUT LEVEL Sets Pin Level when AutoShutdown occurs
#define _P1ASDLA PSMC1ASDD,0 ;Pin A 0= pin goes LO 1= pin goes HI
#define _P1ASDLB PSMC1ASDD,1 ; B
#define _P1ASDLC PSMC1ASDD,2 ; C
#define _P1ASDLD PSMC1ASDD,3 ; D
#define _P1ASDLE PSMC1ASDD,4 ; E
#define _P1ASDLF PSMC1ASDD,5 ; F
PSMC1ASDD_INIT EQU b'00000000' ;non-active (shutdown) levels all LO (0)
;PSMC AUTO-SHUTDOWN SOURCE 0= signal does NOT cause shutdown 1= signal enabled
#define _P1ASDSC1 PSMC1ASDS,1 ;AS occurs when sync_C1OUT output goes true
#define _P1ASDSC2 PSMC1ASDS,2 ;AS occurs when sync_C2OUT output goes true
#define _P1ASDSC3 PSMC1ASDS,3 ;AS occurs when sync_C3OUT output goes true
#define _P1ASDSIN PSMC1ASDS,7 ;AS occurs when PSMC1IN pin goes true
PSMC1ASDS_INIT EQU b'00000000' ;no auto shutdown
;PSMC TIMEBASE INTERRUPT CONTROL
#define _P1TPRIF PSMC1INT,0 ;1= 16-bit PSMC1TMR matched PSMC1PR<15:0>
#define _P1TDCIF PSMC1INT,1 ;1= 16-bit PSMC1TMR matched PSMC1DC<15:0>
#define _P1TPHIF PSMC1INT,2 ;1= 16-bit PSMC1TMR matched PSMCxPH<15:0>
#define _P1TOVIF PSMC1INT,3 ;1= 16-bit PSMC1TMR overflowed 0xFFFF -> 0x0
#define _P1TPRIE PSMC1INT,4 ;1= TimeBase Period match ints enabled
#define _P1TDCIE PSMC1INT,5 ;1= TimeBase Duty Cycle match ints enabled
#define _P1TPHIE PSMC1INT,6 ;1= TimeBase Phase Match ints enabled
#define _P1TOVIE PSMC1INT,7 ;1= TimeBase overflow ints enabled
PSMC1INT_INIT EQU b'00000000' ;no interrupts
!; Single-phase PWM PSMC setup
!; Fully synchronous operation
!; Period =
!; Duty cycle = 50%
! SETBSR PSMC1CON
0x1DE: MOVLB 0x10
! movlw 0x02 ; set period
0x1DF: MOVLW 0x2
! movwf RBS(PSMC1PRH)
0x1E0: MOVWF PSMC1PRH
! movlw 0x7F
0x1E1: MOVLW 0x7F
! movwf RBS(PSMC1PRL)
0x1E2: MOVWF PSMC1PR
! movlw 0x01 ; set duty cycle
0x1E3: MOVLW 0x1
! movwf RBS(PSMC1DCH)
0x1E4: MOVWF PSMC1DCH
! movlw 0x3F
0x1E5: MOVLW 0x3F
! movwf RBS(PSMC1DCL)
0x1E6: MOVWF PSMC1DC
! clrf RBS(PSMC1PHH) ; no phase offset
0x1E7: CLRF PSMC1PHH
! clrf RBS(PSMC1PHL)
0x1E8: CLRF PSMC1PH
! movlw PSMC1CLK_INIT
0x1E9: MOVLW 0x0
! movwf RBS(PSMC1CLK)
0x1EA: MOVWF PSMC1CLK
!; output on E, normal polarity
! bcf BBS(_P1STRA) ;chip pwr-up default is HI
0x1EB: BCF PSMC1STR0, 0x0
! bsf BBS(_P1STRE)
0x1EC: BSF PSMC1STR0, 0x4
! bcf BBS(_P1POLE)
0x1ED: BCF PSMC1POL, 0x4
! bsf BBS(_P1OEE)
0x1EE: BSF PSMC1OEN, 0x4
!; set time base as source for all events
! bsf BBS(_P1PRST)
0x1EF: BSF PSMC1PRS, 0x0
! bsf BBS(_P1PHST)
0x1F0: BSF PSMC1PHS, 0x0
! bsf BBS(_P1DCST)
0x1F1: BSF PSMC1DCS, 0x0
!; enable PSMC in Single-Phase Mode
!; this also loads steering and time buffers
! movlw PSMC1CON_INIT
0x1F2: MOVLW 0xC0
! movwf RBS(PSMC1CON)
0x1F3: MOVWF PSMC1CON
! SETBSR TRISC
0x1F4: MOVLB 0x1
! bcf BBS(TRISC,4) ; enable pin driver
0x1F5: BCF TRISC, 0x4
!
! rampg0
0x1F6: MOVLB 0x0