Sinewaves using interrupts.


Results 1 to 26 of 26

Threaded View

  1. #13
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Hi Hank (and gang),

    I know I'm the assembly language "outsider" here but I agree that interrupt 'overhead' may be a problem. If you were writing the application in assembler I would make a couple suggestions like these;

    <1>
    Consider upgrading to one of the 'enhanced' 16F1x devices which can run at 32-MHz (125-nsec Tcy) with full interrupt context save and restore built-in (= very low interrupt overhead).

    <2>
    Research DDS (Direct Digital Synthesis) and consider using a DDS-PWM or a DDS-R2R method for generating your sine waves. It may not be a good fit for your particular application but it is relatively easy to characterize frequency parameters and performance. For example, here's the characterization for an ISR "engine" for a 10-KHz 12F1822 Sine/Square/Sawtooth/Triangle wave DDS-PWM Signal Generator (using a 32-MHz clock);

    Code:
    ;
    ;  Fdds (DDS frequency) is the reciprocal of the 8-usec PWM period...
    ;
    ;    Fdds (Freq DDS) = 1 / 0.000008 = 125000-Hz
    ;
    ;  frequency resolution is Fdds (DDS frequency) divided by
    ;  the phase accumulator bit width (2^24)...
    ;
    ;    Fres (Freq Resolution) = Fdds / 2^24 = 0.007450580596923828125 Hz
    ;
    ;  to calculate the phase offset for a 10-KHz Fout signal...
    ;
    ;    Phase = INT((Fout / Fres) + 0.5)
    ;    Phase = INT((10000 / 0.007450580596923828125) + 0.5) = 1342177
    ;
    ;    --< or >--
    ;    Phase = INT(Fout / (Fdds / 2^24) + 0.5) = 1342177
    ;    Phase = INT(2^24 / (Fdds / Fout) + 0.5) = 1342177
    ;
    ;  to calculate the actual frequency output (Fout)...
    ;
    ;    Fout = Phase * Fres
    ;    Fout = 1342177 * .007450580596923828125 = ~9999.998 Hz
    ;
    ;    --< or >--
    ;    Fout = Fdds / (2^24 / Phase) = ~9999.998 Hz
    ;    Fout = Phase / (2^24 / Fdds) = ~9999.998 Hz
    ;
            org     0x004
    v_int
            banksel PIR1            ; bank 0                          |B0
            bcf     PIR1,TMR2IF     ; clear TMR2 interrupt flag       |B0
            movf    Phase+0,W       ; Accum = Accum + Phase           |B0
            addwf   Accum+0,F       ;                                 |B0
            movf    Phase+1,W       ;                                 |B0
            addwfc  Accum+1,F       ;                                 |B0
            movf    Phase+2,W       ;                                 |B0
            addwfc  Accum+2,F       ;                                 |B0
            movf    Accum+2,W       ; use 8 most significant bits     |B0
            addwf   FSR1L           ; as pwm table (array) address    |B0
            movf    INDF1,W         ; WREG = duty cycle, 0..255       |B0
            banksel CCP1CON         ; bank 5                          |B5
            bcf     CCP1CON,DC1B0   ; clr duty cycle bit 0            |B5
            bcf     CCP1CON,DC1B1   ; clr duty cycle bit 1            |B5
            lsrf    WREG,W          ; shift duty cycle bit 0 into C   |B5
            skpnc                   ; bit 0 = 1? no, skip, else       |B5
            bsf     CCP1CON,DC1B0   ; set duty cycle bit 0            |B5
            lsrf    WREG,W          ; shift duty cycle bit 1 into C   |B5
            skpnc                   ; bit 1 = 1? no, skip, else       |B5
            bsf     CCP1CON,DC1B1   ; set duty cycle bit 1            |B5
            movwf   CCPR1L          ; set duty cycle bits 7..2        |B5
            retfie                  ;                                 |B?
    ;
    The ISR "engine" for the little 12F1822 USB Signal Generator uses 26 cycles (3.25-usecs) or about 40% of the 64 cycles between interrupts. That leaves plenty of time in the main program to poll the serial port and collect a new signal "type" character and/or a new 24-bit frequency phase offset data from the PC host application.

    One problem I see trying to use DDS to generate sine waves for your application is the number of samples you might need to generate a phase shift. If you need 5° shifts it would require at least 72 samples per cycle. That means your upper frequency limit with a 125-KHz DDS would be only 1736 Hz. If you needed 2° resolution with a 5000 Hz upper frequency limit then you would need an Fdds of 900-KHz. That might be difficult even for the much faster DDS-R2R method.

    Cheerful regards, Mike
    Last edited by Mike, K8LH; - 1st October 2010 at 15:27.

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts