; TITLE 'Serial PWM Controller-8/1/99' ; ;Copyright Dennis Clark and TTT Enterprises. This code is free to use and ;distribute according to the Free Software Copyleft rules and conventions. ;You may not publish or sell it without written permission from me, the ;author. ; ; I included the "include" file for the 508 for reference and changed it a bit ; LIST P = 12C508, F = INHX8M ; P12C508.INC Standard Header File, Version 1.02 Microchip Technology, Inc. ;========================================================================== ; Verify Processor ;========================================================================== IFNDEF __12C508 MESSG "Processor-header file mismatch. Verify selected processor." ENDIF ;========================================================================== ; Register Definitions ;========================================================================== W EQU H'0000' F EQU H'0001' ;----- Register Files ----------------------------------------------------- INDF EQU H'0000' ; Uses FSR to address data mem. TMR0 EQU H'0001' ; 8 bit real time clock/counter PCL EQU H'0002' ; Low order 8 bits of PC STATUS EQU H'0003' ; STATUS FSR EQU H'0004' ; Indirect data memory addr pointer OSCCAL EQU H'0005' ; Calibration data for osc. GPIO EQU H'0006' ; General Purpose I/O ;----- STATUS Bits -----------Page 14-------------------------------------- GPWUF EQU H'0007' ; GPIO reset bit PA0 EQU H'0005' ; Program Page preselect NOT_TO EQU H'0004' ; Time Out bit NOT_PD EQU H'0003' ; Power Down bit Z EQU H'0002' ; Zero bit DC EQU H'0001' ; Digit carry/*borrow bit C EQU H'0000' ; carry/*borrow bit ;----- OPTION Bits -----------Page 15-------------------------------------- NOT_GPWU EQU H'0007' ; Enable wake-up on pin change NOT_GPPU EQU H'0006' ; Enable weak pull-ups T0CS EQU H'0005' ; Timer0 clock source select T0SE EQU H'0004' ; Timer0 sources edge select PSA EQU H'0003' ; Prescalar assignment bit PS2 EQU H'0002' ;\ PS1 EQU H'0001' ; > Prescalar rate select bits PS0 EQU H'0000' ;/ ;========================================================================== ; RAM Definition ;========================================================================== __MAXRAM H'3F' ;========================================================================== ; Configuration Bits ;========================================================================== _MCLRE_ON EQU H'0FFF' _MCLRE_OFF EQU H'0FEF' _CP_ON EQU H'0FF7' _CP_OFF EQU H'0FFF' _WDT_ON EQU H'0FFF' _WDT_OFF EQU H'0FFB' _LP_OSC EQU H'0FFC' _XT_OSC EQU H'0FFD' _IntRC_OSC EQU H'0FFE' _ExtRC_OSC EQU H'0FFF' __CONFIG ( _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC ) ;========================================================================== ; Program Variables ;========================================================================== ;Port definitions and other constants or macros #define FWDout GPIO,5 ; Pin 2 = GP5 = bit 5 O #define REVout GPIO,4 ; Pin 3 = GP4 = Bit 4 O #define RESET GPIO,3 ; Pin 4 =/MCLR= Bit 3 I #define PWMout GPIO,2 ; Pin 5 = GP2 = Bit 2 O #define DATAIN GPIO,1 ; Pin 6 = GP1 = Bit 1 I #define UNUSED GPIO,0 ; Pin 7 = GP0 = Bit 0 O #define SCONFIG B'11001010' ; inputs= 1 & 3, 0,2,4,5 outputs #define DELAY1 D'8' ; 9600 BAUD delay amount (~108us) #define DELAY2 D'8' ; 1.2 bit times (start bit) #define FTEST sdata,1 ; first bit forward test #define RTEST sdata,2 ; second bit reverse test LIST ;Register locations for important stuff,only 9-15 are available before table rcount EQU D'8' ; bit count rcvreg EQU D'9' ; incoming byte storage delay EQU D'10' ; delay storage register scratch EQU D'11' ; math scratch pad register otmr EQU D'13' ; last stored TMR0 reading PWMval EQU D'14' sdata EQU D'15' ; data register sfun EQU D'16' ; function register ;================================ ; Main Code = ;================================ ORG 0x1FF ; MOVLW 0x50 ; My EPROM calibration value,remove for OTPs start ORG 0x000 MOVWF OSCCAL ; Store the factory osc. calibration value MOVLW SCONFIG ; Set GPIO 3 and 5 as input, rest outputs TRIS GPIO ; Configure pins MOVLW B'10000001' ; Set OPTION bits Prescaler divide by 4 OPTION ; Implement OPTION bits MOVLW 0 ; preset PWM to zero MOVWF PWMval BCF PWMout ; clear PWM output CLRF otmr ; initial setup, whatever... CLRF TMR0 main ;=========================================================================== ; This program will take a single byte of serial data at 9600 baud and ;control a 1KHz PWM output with one of 128 possible settings X 2, max 254. ;The MS bit chooses either direction bits (1) or PWM value (0). ;Hopefully in real-time. It is never completely on or completely off. ;With a '0' setting it is still on for 4us, a 127(254) is still off for ;4us. Darn close though for a 4MHz chip! The two direction bits ;correspond to the 'Forward' and 'Reverse' lines of an L298 or L293 chip. ;Copyright Dennis Clark and TTT Enterprises Revision A.2 8/1/99 ;=========================================================================== mloop BTFSS DATAIN ; Look for a start bit CALL getbyte ; Start bit detected, get the input byte now MOVF PWMval,W SUBWF TMR0,W ; ntmr - W -> W BTFSC STATUS,C ; C = 1 then W is less than TMR0 BCF PWMout ; bit now = 0 MOVF TMR0,W ; get THE most recent timer value SUBWF otmr,F ; subtract from the last saved value BTFSC STATUS,C ; if c = 1 then we rolled over BSF PWMout ; set PWM bit mdone ; Get recent TMR0 value MOVWF otmr ; make TMR0 the last saved value GOTO mloop ; and do it again ;================================ ; ; Subroutines Follow ; ;================================ getbyte ;--------------------------------- ; This is the routine that will ;get the data byte from the serial ;line. We do LOTS of in-between ;PWM value checking while doing ;math here, to stop jitter. ;--------------------------------- MOVLW 7 ; only getting first 7 bits of positional data here MOVWF rcount ; save bit count here CLRF sdata ; clear out the receive register CLRF sfun ; clear out the function register MOVLW DELAY2 ; 1.3 bit times to move well into the next bit MOVWF delay ; delay counter r_next CALL bdelay ; do the delay, which checks all servo timers too BCF STATUS,C ; default to zero for incoming bit RRF sdata,F ; and rotate it into the receive buffer BTFSC DATAIN ; check the incoming bit now BSF sdata,7 ; nope, its a one really MOVLW DELAY1 ; normal delay time MOVWF delay DECFSZ rcount,F ; and loop to get the rest GOTO r_next BCF STATUS,C ; leave data rotated one place (mult by 2) MOVLW DELAY1 ; 1 bit time to first servo bit MOVWF delay CALL bdelay ; do the delay, which checks all servo timers too BTFSC DATAIN ; check the incoming bit now BSF sfun,0 ; nope, its a one really MOVLW DELAY1 ; delay time for stop bit MOVWF delay CALL bdelay BTFSS DATAIN ; check stop bit, must = 1 or its a nogo GOTO freturn ; its 0, framing error, don't use this cfor0 MOVF sfun,F ; check for zero value, here no settings change BTFSC STATUS,Z ; GOTO gotall ; it is zero, this is a PWM value BCF FWDout ; clear forward bit BTFSC FTEST ; Correct directional data (bits 0 and 1) BSF FWDout ; set forward bit BCF REVout ; clear reverse bit BTFSC RTEST ; test reverse bit BSF REVout ; set reverse bit GOTO freturn ; new direction set, all done. gotall ; now have the data, we need to decode and use it MOVF sdata,W ; get speed data MOVWF PWMval ; and set its value freturn RETLW 0 ; We are done with data and check, return bdelay ;--------------------------------- ; This will do the usual 104us ; delay, but it will do useful ; stuff during the delay, it will ; check each servo for proper '0' ; settings. It will also check ; for rollover to reset all servos ;--------------------------------- bloop ; Just service the servos here then MOVF PWMval,W SUBWF TMR0,W ; ntmr - W -> W BTFSC STATUS,C ; C = 1 then W is less than TMR0 BCF PWMout ; bit now = 0 MOVF TMR0,W ; get THE most recent timer value SUBWF otmr,F ; subtract from the last saved value BTFSC STATUS,C ; if c = 1 then we rolled over BSF PWMout ; set PWM bit bdone ; Get most recent TMR0 value MOVWF otmr ; make TMR0 the last saved value DECFSZ delay,F ; decrement loop count GOTO bloop ; and do it again RETLW 0 ; all done now END ; directive 'end of program'