Great suggestions by some of the most knowledgable contributors to the list.
I elected to go with a simple software approach using PWM, without lookup tables. Most of the code is to provide DT's Instant Interrupt.
I initialize the 16F690 HPWM at 32kHz, zero duty. With each TMR1 interrupt I increment the duty register until I reach the desired maximum voltage on the sawtooth, then start over at zero. A low-pass RC filter smooths the output. Peak voltage and frequency are easily modified. I retained the oscope interrupt timing signal on RC.4; you will have to change some parameters if this is omitted.
Other ways to tackle this include a 555-based generator, R2R ladder network or dedicated parallel-interface DACs. Microchip has an application note http://www.microchip.com/stellent/id...pnote=en011071 that may be helpful.
Gary
Code:'**************************************************************** '* Name : oscope clock 16F690 sawtooth generator '* Author : gmg Copyright (c) 2010 (yeah, right...) '* Date : 7/28/2010 '* Notes : generates sawtooth wave for CRT time base ' Horiz: 1.5v=10 div, Vert: 2.0v=8 div max on CRT passive low pass RC filter on PWM output RC.5 '************************************************************ @ __config _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CP_OFF & _WDT_OFF ADCON1=$0F 'disable A/D VRCON=0 'volt ref off CM1CON0.0=0 : CM2CON0.0=0 'comparators off ANSEL=0 : ANSELH=0 OSCCON=%01110000 ;8MHz intosc DEFINE OSC 8 '-------------- pins 'PWM_out var portc.5 TRISC=0:TRISB=0 PORTC=0: PORTB=0 '-------------- variables version con 107 i var byte j var byte temp var BYTE tempword var word duty_reg var word HLevel var byte VLevel var byte HOrigin var byte CLEAR read 0, temp if temp<>version then write 0, version 'store sw version in EEPROM 0 '---- setup HPWM on PORTC.5 hpwm 1, 0, 32000 '32kHz PWMN out on PORTC.5 '----- setup DT instant interrupt TMR1 INCLUDE "DT_INTS-14.bas" ; Base Interrupt System INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts (cf. asm interrupts) ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler TMR1_INT, ReloadTMR1, ASM, no ; MUST be first INT_Handler TMR1_INT, _T1handler, PBP, yes endm . INT_CREATE ; Creates the interrupt processor ENDASM @Freq = 6000 ; interrupt frequency, 1.7msec period gives 600Hz screen sweep @Prescaler = 1 ; Timers Prescaler setting T1CON = $00 ; $30 = Prescaler 1:8, TMR1 OFF ; $00=1:1, $10=1:2, $20=1:4, $30=1:8 -- NB: T1CON Must match @Prescaler value @ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts GOSUB StartTimer ; Start the Timer '------- Main while 1=1 'loop forever wend ;____This routine is Called on each TMR1 Interrupt____________________________ T1handler: ISR: duty_reg=duty_reg+1 if duty_reg>140 then duty_reg=0 'increment duty_reg each interrupt for ramp function trisc.5=1 CCP1CON.4=duty_reg.0 '10bit PWM CCP1CON.5=duty_reg.1 tempword=duty_reg & %1111111100 CCPR1L=tempword>>2 trisc.5=0 HIGH PORTC.4 'TEMP oscope timing pulse, retained to preserve timing PAUSEUS 10 LOW PORTC.4 @ INT_RETURN ;---[TMR1 reload - interrupt handler]----------------------------------------- ASM ; Calculate Timer Reload Constant ReloadInst = 8 ; # of Intructions used to reload timer if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8)) MaxCount = 65536 + (ReloadInst / Prescaler) TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq) if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst))) error Invalid Timer Values - check"OSC", "Freq" and "Prescaler" endif else error Invalid Prescaler endif ENDASM @Timer1 = TMR1L ; map timer registers to a word variable Timer1 VAR WORD EXT TimerReload CON EXT ; Get the External Constant TMR1ON VAR T1CON.0 ; Alias the Timers ON/OFF bit ;---Reload Timer1------ ASM ReloadTMR1 MOVE?CT 0, T1CON, TMR1ON ; 1 stop timer MOVLW LOW(TimerReload) ; 1 Add TimerReload to the ADDWF TMR1L,F ; 1 value in Timer1 BTFSC STATUS,C ; 1/2 INCF TMR1H,F ; 1 MOVLW HIGH(TimerReload) ; 1 ADDWF TMR1H,F ; 1 MOVE?CT 1, T1CON, TMR1ON ; 1 start timer INT_RETURN ENDASM ;---Start/Stop controls ----- StartTimer: Timer1 = TimerReload ; Load Timer TMR1ON = 1 ; start timer RETURN StopTimer: TMR1ON = 0 ; stop timer RETURN END







Bookmarks