DDS (generating sine waves) with onboard DAC using latest PIC 16F chips?


Results 1 to 40 of 77

Threaded View

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


    Did you find this post helpful? Yes | No

    Default

    Hi Hank,

    Not exactly what you asked for, but... have you considered using the PWM module with a low pass filter on the CCP1 output? You may need to amplify the signal as well.

    I was toying with this idea a while back for a CTCSS Access Tone Generator but I never got around to building and testing it.

    This example (free/lite version of BoostC) uses a 12F683 and an 8.388608-MHz crystal to generate CTCSS sine wave tones spanning 100 to 250-Hz with 0.000625-Hz frequency resolution. If you were to use a 12F1822 with that crystal and 4xPLL, or any other device with 4xPLL, you could bump the upper frequency range to about 1000-Hz with 0.0025-Hz frequency resolution.

    Food for thought.

    Cheerful regards, Mike McLaren, K8LH


    PS: A quick search came up with this interesting old thread; Generating tones with decimals using PWM

    Code:
    /********************************************************************
     *                                                                  *
     *  Project: CTCSS 12F683                                           *
     *   Source: CTCSS_12F683.c                                         *
     *   Author: Mike McLaren, K8LH                                     *
     *     Date: 26-Nov-10                                              *
     *  Revised: 26-Nov-10                                              *
     *                                                                  *
     *  untested 12F683 DDS(PWM) CTCSS Tone Generator with 24-bit       *
     *  Phase Accumulator (Fosc = 8.388608-MHz)                         *
     *                                                                  *
     *      IDE: MPLAB 8.56 (tabs = 4)                                  *
     *     Lang: SourceBoost BoostC v7.01, Lite/Free version            *
     *                                                                  *
     ********************************************************************
     *
     *    CTCSS tone frequencies
     *
     *     67.0 Hz    69.3 Hz    71.9 Hz    74.4 Hz    77.0 Hz
     *     79.7 Hz    82.5 Hz    85.4 Hz    88.5 Hz    91.5 Hz
     *     94.8 Hz    97.4 Hz   100.0 Hz   103.5 Hz   107.2 Hz
     *    110.9 Hz   114.8 Hz   118.8 Hz   123.0 Hz   127.3 Hz
     *    131.8 Hz   136.5 Hz   141.3 Hz   146.2 Hz   151.4 Hz
     *    156.7 Hz   159.8 Hz   162.2 Hz   165.5 Hz   167.9 Hz
     *    171.3 Hz   173.8 Hz   177.3 Hz   179.9 Hz   183.5 Hz
     *    186.2 Hz   189.9 Hz   192.8 Hz   196.6 Hz   199.5 Hz
     *    203.5 Hz   206.5 Hz   210.7 Hz   218.1 Hz   225.7 Hz
     *    229.1 Hz   233.6 Hz   241.8 Hz   250.3 Hz   254.1 Hz
     *
     */
    
    #include system.h
    
    #pragma DATA _CONFIG, _MCLRE_OFF, _WDT_OFF, _HS_OSC
    
    #pragma CLOCK_FREQ 8388608      // using an 8.388608-MHz crystal
    
    //--< function prototypes >------------------------------------------
    //--< type definitions >---------------------------------------------
    
    typedef unsigned char u08;
    typedef unsigned int u16;
    typedef unsigned long u32;
    
    #define r08 rom char*
    
    //--< variables >----------------------------------------------------
    
    u32 accum;                  // phase accumulator
    u32 phase;                  // phase offset (DDS tuning word)
    
    r08 sinetbl =   { 100,102,104,107,109,112,114,117,119,121,
                      124,126,129,131,133,135,138,140,142,144,
                      147,149,151,153,155,157,159,161,163,165,
                      167,168,170,172,174,175,177,178,180,181,
                      183,184,185,187,188,189,190,191,192,193,
                      194,194,195,196,197,197,198,198,198,199,
                      199,199,199,199,200,199,199,199,199,199,
                      198,198,198,197,197,196,195,194,194,193,
                      192,191,190,189,188,187,185,184,183,181,
                      180,178,177,175,174,172,170,168,167,165,
                      163,161,159,157,155,153,151,149,147,144,
                      142,140,138,135,133,131,129,126,124,121,
                      119,117,114,112,109,107,104,102, 99, 97,
                       95, 92, 90, 87, 85, 82, 80, 78, 75, 73,
                       70, 68, 66, 64, 61, 59, 57, 55, 52, 50,
                       48, 46, 44, 42, 40, 38, 36, 34, 32, 31,
                       29, 27, 25, 24, 22, 21, 19, 18, 16, 15,
                       14, 12, 11, 10,  9,  8,  7,  6,  5,  5,
                        4,  3,  2,  2,  1,  1,  1,  0,  0,  0,
                        0,  0,  0,  0,  0,  0,  0,  0,  1,  1,
                        1,  2,  2,  3,  4,  5,  5,  6,  7,  8,
                        9, 10, 11, 12, 14, 15, 16, 18, 19, 21,
                       22, 24, 25, 27, 29, 31, 32, 34, 36, 38,
                       40, 42, 44, 46, 48, 50, 52, 55, 57, 59,
                       61, 64, 66, 68, 70, 73, 75, 78, 80, 82,
                       85, 87, 90, 92, 95, 97 };
    
    //--< defines >------------------------------------------------------
    
    //--< isr >----------------------------------------------------------
    
    /*
     *  12F/16F1xxx DDS-PWM CTCSS "Access Tone Generator" Notes
     *  =======================================================
     *
     *  using an 8.388608 MHz crystal
     *
     *    Tcy = 1 / 8388608 * 4 = 476.837158203125 nsecs
     *
     *  using a 200 cycle PWM period provides a DDS frequency of
     *
     *    Fdds = 1 / (200 Tcy) = 10,485.76 Hz
     *
     *  frequency resolution using a 24 bit phase accumulator is
     *
     *    Fres = Fdds / 2^24
     *    Fres = 10485.76 / 16777216 = 0.000625 Hz
     *
     *  dds tuning word (phase offset) can be calculated a couple
     *  different ways.  since the dds frequency resolution (Fres)
     *  is basically 0.01-Hz divided by 16, you can calculate the
     *  phase offset by mulitplying desired Fout output frequency
     *  by 1600.  the phase offset for an Fout of 254.1-Hz is;
     *
     *    phase = (Fout  * 100) * 16
     *          = (254.1 * 100) * 16 = 406560
     *
     *    phase =  25410 << 4 = 406560
     *
     *  or you can also calculate phase offset like this (yuch!);
     *
     *    phase = Fout / Fres
     *          = 254.1 / 0.000625 = 406560
     *
     *    phase = Fout * 2^24 / Fdds
     *          = 254.1 * 16777216 / 10485.76 = 406560
     *
     *  the highest CTCSS frequency (254.1 Hz) will produce the
     *  smallest number of sine wave D/A output points per cycle;
     *
     *    INT(10485.76 / 254.1) = 41 output points per cycle
     *
     *  use the most significant 8 bits of the 24-bit phase
     *  accumulator as the sine table index.
     *
     */
    
    void interrupt()                // 200-cycles (10485.76-Hz)
    { pir1.TMR2IF = 0;              // clear TMR2 interrupt flag
      accum += phase;               // add phase offset to accum
      ccpr1l = sinetbl[accum>>16];  // sine duty cycle value for
    }                               // next PWM period
    
    //--< main >---------------------------------------------------------
    
    void main()
    {
      cmcon0 = 7;                   // comparator off, digital I/O
      ansel = 0;                    // a2d module off, digital I/O
      trisio = 0b00111011;          // GP2 output, all others input
     /*
      *  setup PWM module for 200 cycle interrupts (10485.76-Hz using
      *  an 8.388608-MHz clock)
      *
      */
      ccp1con = 0b00001100;         // 00001100
                                    // --00---- DC1B<1:0>, duty cycle b1:b0
                                    // ----1100 CCP1M<3:0>, pwm mode
      t2con = 0b00000000;           // 00000000
                                    // -0000--- TOUTPS<3:0>, postscale 1
                                    // -----0-- TMR2ON, timer off
                                    // ------00 T2CKPS<1:0>, prescale 1
                                    // for 476.837158203125 nsec 'ticks'
      pr2 = 200-1;                  // for 95.367431640625 usec interrupts
      ccpr1l = 0;                   // 0% duty cycle
      pie1.TMR2IE = 1;              // enable Timer 2 interrupts
      pir1 = 0;                     // clear all peripheral interrupt flags
      intcon.PEIE = 1;              // enable peripheral interrupts
      intcon.GIE = 1;               // enable global interrupts
      t2con.TMR2ON = 1;             // turn TMR2 on
    
      phase = 25410 << 4;           // phase offset for 254.1-Hz tone
    
      while(1);                     // loop forever
    }
    Last edited by Mike, K8LH; - 15th January 2011 at 18:36.

Members who have read this thread : 1

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