Обсуждаем цифровые устройства...
Ответить

Re: 3-канальный DDS на STM32F303

Сб ноя 25, 2017 23:24:49

Исключительно с целю экономии компонентов. У меня всего два 303-х. Применение 2-го МК не связано с измерениями, так что то устройство будет на отдельной плате.
А вот названные 2 проекта - из одной сферы. И я не имел в виду совмещение функционала в одной прошивке, а что-то вроде переключения между двумя программами.

Добавлено after 2 hours 21 minute 23 seconds:
...и что на счёт ГКЧ?

Re: 3-канальный DDS на STM32F303

Вс ноя 26, 2017 14:30:42

не вижу препятствий, можно и объединить ГКЧ+RLC.
и софт общий на ПК+Android.
в дальнейшем можно заменить фронт-энд более высокочастотным на AD98xx для измерения малых индуктивностей/емкостей и для VNA

Re: 3-канальный DDS на STM32F303

Вс ноя 26, 2017 16:53:55

Но я только что заметил, что код, видимо, закрыт...

Re: 3-канальный DDS на STM32F303

Вс ноя 26, 2017 17:10:00

пока закрыт.
вот DDS часть, если поможет, в принципе ничего сложного - в прерывании половины DMA обновляются буферы семплов: https://pastebin.com/uG6yUNKX

Спойлер
Код:
#define F_DDS            3200000uL            // DDS base frequency
#define DDS_CHANNELS     3                    // number of DDS channels
#define DDS_WAVE_BITS    10                   // number of bits in waveform buffer
#define DDS_WAVE_SAMPLES (1 << DDS_WAVE_BITS) // number of waveform samples
#define DDS_OUT_BITS     9                    // number of bits in waveform buffer
#define DDS_OUT_SAMPLES  (1 << DDS_OUT_BITS)  // number of samples in output buffer
#define DDS_SHIFT        (32 - DDS_WAVE_BITS)
#define DAC_OUT_MAX      4095                 // DAC maximum level

enum { DDS_FORM_SINE, DDS_FORM_SQR, DDS_FORM_PWM, DDS_FORM_TRI, DDS_FORM_SAW1, DDS_FORM_SAW2, DDS_FORM_DC, DDS_FORM_USER1, DDS_FORM_USER2, DDS_FORM_USER3, DDS_FORM_USER4, DDS_FORM_LAST };

struct dds_struct {
   // current table pointer, user wave table, output samples
   u16 *wave, table[DDS_WAVE_SAMPLES], out[DDS_OUT_SAMPLES];
   struct {
      u32 acc, inc, add;
   } phase;
   u32 form, pwm, amp;   // current wave form, PWM duty, amplitude
   u64 f,ph;             // real frequency, phase
   struct {
      u8 chn, form, f, ph, pwm;
   } update;
} __attribute__((aligned(2),packed));

inline u32 dds_sync(){ return gpio_get(GPIOA,3); }

struct dds_struct dds[DDS_CHANNELS];

const u16 table_sine[DDS_WAVE_SAMPLES] = {
   2048, 2061, 2073, 2086, 2098, 2111, 2123, 2136, 2148, 2161, 2174, 2186, 2199, 2211, 2224, 2236, 2249, 2261, 2274, 2286, 2299, 2311, 2323, 2336, 2348, 2361, 2373, 2386, 2398, 2410, 2423, 2435,
   2447, 2460, 2472, 2484, 2497, 2509, 2521, 2533, 2545, 2558, 2570, 2582, 2594, 2606, 2618, 2630, 2642, 2654, 2666, 2678, 2690, 2702, 2714, 2726, 2738, 2749, 2761, 2773, 2785, 2796, 2808, 2820,
   2831, 2843, 2855, 2866, 2878, 2889, 2900, 2912, 2923, 2935, 2946, 2957, 2968, 2980, 2991, 3002, 3013, 3024, 3035, 3046, 3057, 3068, 3079, 3090, 3100, 3111, 3122, 3133, 3143, 3154, 3164, 3175,
   3185, 3196, 3206, 3216, 3227, 3237, 3247, 3257, 3267, 3277, 3287, 3297, 3307, 3317, 3327, 3337, 3347, 3356, 3366, 3376, 3385, 3395, 3404, 3413, 3423, 3432, 3441, 3450, 3459, 3469, 3478, 3487,
   3495, 3504, 3513, 3522, 3531, 3539, 3548, 3556, 3565, 3573, 3581, 3590, 3598, 3606, 3614, 3622, 3630, 3638, 3646, 3654, 3662, 3669, 3677, 3685, 3692, 3700, 3707, 3714, 3722, 3729, 3736, 3743,
   3750, 3757, 3764, 3771, 3777, 3784, 3791, 3797, 3804, 3810, 3817, 3823, 3829, 3835, 3841, 3847, 3853, 3859, 3865, 3871, 3876, 3882, 3888, 3893, 3898, 3904, 3909, 3914, 3919, 3924, 3929, 3934,
   3939, 3944, 3949, 3953, 3958, 3962, 3967, 3971, 3975, 3980, 3984, 3988, 3992, 3996, 3999, 4003, 4007, 4010, 4014, 4017, 4021, 4024, 4027, 4031, 4034, 4037, 4040, 4042, 4045, 4048, 4051, 4053,
   4056, 4058, 4060, 4063, 4065, 4067, 4069, 4071, 4073, 4075, 4076, 4078, 4080, 4081, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4093, 4094, 4094, 4094, 4095, 4095, 4095,
   4095, 4095, 4095, 4095, 4094, 4094, 4094, 4093, 4093, 4092, 4091, 4090, 4089, 4088, 4087, 4086, 4085, 4084, 4083, 4081, 4080, 4078, 4076, 4075, 4073, 4071, 4069, 4067, 4065, 4063, 4060, 4058,
   4056, 4053, 4051, 4048, 4045, 4042, 4040, 4037, 4034, 4031, 4027, 4024, 4021, 4017, 4014, 4010, 4007, 4003, 3999, 3996, 3992, 3988, 3984, 3980, 3975, 3971, 3967, 3962, 3958, 3953, 3949, 3944,
   3939, 3934, 3929, 3924, 3919, 3914, 3909, 3904, 3898, 3893, 3888, 3882, 3876, 3871, 3865, 3859, 3853, 3847, 3841, 3835, 3829, 3823, 3817, 3810, 3804, 3797, 3791, 3784, 3777, 3771, 3764, 3757,
   3750, 3743, 3736, 3729, 3722, 3714, 3707, 3700, 3692, 3685, 3677, 3669, 3662, 3654, 3646, 3638, 3630, 3622, 3614, 3606, 3598, 3590, 3581, 3573, 3565, 3556, 3548, 3539, 3531, 3522, 3513, 3504,
   3495, 3487, 3478, 3469, 3459, 3450, 3441, 3432, 3423, 3413, 3404, 3395, 3385, 3376, 3366, 3356, 3347, 3337, 3327, 3317, 3307, 3297, 3287, 3277, 3267, 3257, 3247, 3237, 3227, 3216, 3206, 3196,
   3185, 3175, 3164, 3154, 3143, 3133, 3122, 3111, 3100, 3090, 3079, 3068, 3057, 3046, 3035, 3024, 3013, 3002, 2991, 2980, 2968, 2957, 2946, 2935, 2923, 2912, 2900, 2889, 2878, 2866, 2855, 2843,
   2831, 2820, 2808, 2796, 2785, 2773, 2761, 2749, 2738, 2726, 2714, 2702, 2690, 2678, 2666, 2654, 2642, 2630, 2618, 2606, 2594, 2582, 2570, 2558, 2545, 2533, 2521, 2509, 2497, 2484, 2472, 2460,
   2447, 2435, 2423, 2410, 2398, 2386, 2373, 2361, 2348, 2336, 2323, 2311, 2299, 2286, 2274, 2261, 2249, 2236, 2224, 2211, 2199, 2186, 2174, 2161, 2148, 2136, 2123, 2111, 2098, 2086, 2073, 2061,
   2048, 2035, 2023, 2010, 1998, 1985, 1973, 1960, 1948, 1935, 1922, 1910, 1897, 1885, 1872, 1860, 1847, 1835, 1822, 1810, 1797, 1785, 1773, 1760, 1748, 1735, 1723, 1710, 1698, 1686, 1673, 1661,
   1649, 1636, 1624, 1612, 1599, 1587, 1575, 1563, 1551, 1538, 1526, 1514, 1502, 1490, 1478, 1466, 1454, 1442, 1430, 1418, 1406, 1394, 1382, 1370, 1358, 1347, 1335, 1323, 1311, 1300, 1288, 1276,
   1265, 1253, 1241, 1230, 1218, 1207, 1196, 1184, 1173, 1161, 1150, 1139, 1128, 1116, 1105, 1094, 1083, 1072, 1061, 1050, 1039, 1028, 1017, 1006,  996,  985,  974,  963,  953,  942,  932,  921,
    911,  900,  890,  880,  869,  859,  849,  839,  829,  819,  809,  799,  789,  779,  769,  759,  749,  740,  730,  720,  711,  701,  692,  683,  673,  664,  655,  646,  637,  627,  618,  609,
    601,  592,  583,  574,  565,  557,  548,  540,  531,  523,  515,  506,  498,  490,  482,  474,  466,  458,  450,  442,  434,  427,  419,  411,  404,  396,  389,  382,  374,  367,  360,  353,
    346,  339,  332,  325,  319,  312,  305,  299,  292,  286,  279,  273,  267,  261,  255,  249,  243,  237,  231,  225,  220,  214,  208,  203,  198,  192,  187,  182,  177,  172,  167,  162,
    157,  152,  147,  143,  138,  134,  129,  125,  121,  116,  112,  108,  104,  100,   97,   93,   89,   86,   82,   79,   75,   72,   69,   65,   62,   59,   56,   54,   51,   48,   45,   43,
     40,   38,   36,   33,   31,   29,   27,   25,   23,   21,   20,   18,   16,   15,   13,   12,   11,   10,    9,    8,    7,    6,    5,    4,    3,    3,    2,    2,    2,    1,    1,    1,
      1,    1,    1,    1,    2,    2,    2,    3,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   15,   16,   18,   20,   21,   23,   25,   27,   29,   31,   33,   36,   38,
     40,   43,   45,   48,   51,   54,   56,   59,   62,   65,   69,   72,   75,   79,   82,   86,   89,   93,   97,  100,  104,  108,  112,  116,  121,  125,  129,  134,  138,  143,  147,  152,
    157,  162,  167,  172,  177,  182,  187,  192,  198,  203,  208,  214,  220,  225,  231,  237,  243,  249,  255,  261,  267,  273,  279,  286,  292,  299,  305,  312,  319,  325,  332,  339,
    346,  353,  360,  367,  374,  382,  389,  396,  404,  411,  419,  427,  434,  442,  450,  458,  466,  474,  482,  490,  498,  506,  515,  523,  531,  540,  548,  557,  565,  574,  583,  592,
    601,  609,  618,  627,  637,  646,  655,  664,  673,  683,  692,  701,  711,  720,  730,  740,  749,  759,  769,  779,  789,  799,  809,  819,  829,  839,  849,  859,  869,  880,  890,  900,
    911,  921,  932,  942,  953,  963,  974,  985,  996, 1006, 1017, 1028, 1039, 1050, 1061, 1072, 1083, 1094, 1105, 1116, 1128, 1139, 1150, 1161, 1173, 1184, 1196, 1207, 1218, 1230, 1241, 1253,
   1265, 1276, 1288, 1300, 1311, 1323, 1335, 1347, 1358, 1370, 1382, 1394, 1406, 1418, 1430, 1442, 1454, 1466, 1478, 1490, 1502, 1514, 1526, 1538, 1551, 1563, 1575, 1587, 1599, 1612, 1624, 1636,
   1649, 1661, 1673, 1686, 1698, 1710, 1723, 1735, 1748, 1760, 1773, 1785, 1797, 1810, 1822, 1835, 1847, 1860, 1872, 1885, 1897, 1910, 1922, 1935, 1948, 1960, 1973, 1985, 1998, 2010, 2023, 2035,
};

void dds_setup(){
   // PA3 - Sync
   gpio_mode1(GPIOA, GPIO_MODE_INPUT,  3);
   gpio_pupd1(GPIOA, GPIO_PULLUP,      3);
   // PA4-6 - DACs
   gpio_mode3(GPIOA, GPIO_MODE_ANALOG, 4,5,6);
   gpio_pupd3(GPIOA, GPIO_NOPULL,      4,5,6);

   // DACs
   __DAC1_CLK_ENABLE(); __DAC2_CLK_ENABLE();
   DAC1->CR = DAC_CR_TSEL1 | DAC_CR_TSEL2 | DAC_CR_EN1 | DAC_CR_EN2 | DAC_CR_BOFF2 | (config.params.s.buf ? 0 : DAC_CR_BOFF1);
   DAC2->CR = DAC_CR_TSEL1 | DAC_CR_TSEL2 | DAC_CR_EN1 | DAC_CR_EN2 | DAC_CR_BOFF1 | DAC_CR_BOFF2;

   // Timer
   __TIM1_CLK_ENABLE();
   TIM_HandleTypeDef timh;
   timh.Instance               = TIM1;
    timh.Init.Prescaler         = 0;
    timh.Init.Period            = F_CPU / F_DDS - 1;
    timh.Init.ClockDivision     = 1; //TIM_CLOCKDIVISION_DIV1;
    timh.Init.CounterMode       = TIM_COUNTERMODE_UP;
    timh.Init.RepetitionCounter = 0;
    HAL_TIM_Base_Init(&timh);
    TIM1->CR1  &= ~TIM_CR1_CEN;
    TIM1->CCR1  = TIM1->CCR2 = TIM1->CCR3 = F_CPU / F_DDS - 1;
    TIM1->DIER |= TIM_DIER_CC1DE | TIM_DIER_CC2DE | TIM_DIER_CC3DE;

    // DMA
    __DMA1_CLK_ENABLE();

    DMA_HandleTypeDef dmah12;
    dmah12.Instance                 = DMA1_Channel2;
    dmah12.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    dmah12.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
    dmah12.Init.MemInc              = DMA_MINC_ENABLE;
    dmah12.Init.Mode                = DMA_CIRCULAR;
    dmah12.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    dmah12.Init.PeriphInc           = DMA_PINC_DISABLE;
    dmah12.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
    HAL_DMA_Init(&dmah12);
    HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
    HAL_DMA_Start_IT(&dmah12, (u32)&dds[0].out, (u32)&DAC1->DHR12R1, DDS_OUT_SAMPLES);

    DMA_HandleTypeDef dmah13;
    dmah13.Instance                 = DMA1_Channel3;
    dmah13.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    dmah13.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
    dmah13.Init.MemInc              = DMA_MINC_ENABLE;
    dmah13.Init.Mode                = DMA_CIRCULAR;
    dmah13.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    dmah13.Init.PeriphInc           = DMA_PINC_DISABLE;
    dmah13.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
    HAL_DMA_Init(&dmah13);
    HAL_DMA_Start(&dmah13, (u32)&dds[1].out, (u32)&DAC1->DHR12R2, DDS_OUT_SAMPLES);

    DMA_HandleTypeDef dmah16;
    dmah16.Instance                 = DMA1_Channel6;
    dmah16.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    dmah16.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
    dmah16.Init.MemInc              = DMA_MINC_ENABLE;
    dmah16.Init.Mode                = DMA_CIRCULAR;
    dmah16.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    dmah16.Init.PeriphInc           = DMA_PINC_DISABLE;
    dmah16.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
    HAL_DMA_Init(&dmah16);
    HAL_DMA_Start(&dmah16, (u32)&dds[2].out, (u32)&DAC2->DHR12R1, DDS_OUT_SAMPLES);

    // update all channels
    for (u8 i=0; i<DDS_CHANNELS; i++){
       dds[i].wave = &dds[i].table[0];
       dds[i].update.form = dds[i].update.f = dds[i].update.ph = dds[i].update.pwm = 1;
    }

    // start main timer
    TIM1->CR1 |= TIM_CR1_CEN;

   ptx_add(dds_thread, NULL, PTX_RUN);
}

void handler_IRQ_DMA1_Channel2(){
   u16 *out1,*out2,*out3, *wave1,*wave2,*wave3;

   // load pointers to out buffers
   if (DMA1->ISR & DMA_FLAG_HT2){ out1 = &dds[0].out[0]; out2 = &dds[1].out[0]; out3 = &dds[2].out[0];
   } else if (DMA1->ISR & DMA_FLAG_TC2){ out1 = &dds[0].out[DDS_OUT_SAMPLES / 2]; out2 = &dds[1].out[DDS_OUT_SAMPLES / 2]; out3 = &dds[2].out[DDS_OUT_SAMPLES / 2]; }

   // clear DMA flags
   DMA1->IFCR = DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2;// | DMA_IFCR_CTEIF2;

   // synchronize accumulators
   if (config.params.s.sync) config.params.s.sync = dds[0].phase.acc = dds[1].phase.acc = dds[2].phase.acc = 0;

   // cache phase/increment
   u32 acc1 = dds[0].phase.acc + dds[0].phase.add; u32 inc1 = dds[0].phase.inc;
   u32 acc2 = dds[1].phase.acc + dds[1].phase.add; u32 inc2 = config.params.s.all_freq1 ? dds[0].phase.inc : dds[1].phase.inc;
   u32 acc3 = dds[2].phase.acc + dds[2].phase.add; u32 inc3 = config.params.s.all_freq1 ? dds[0].phase.inc : dds[2].phase.inc;

   // load pointers to wavetables
   if (config.params.s.all_form1) wave1 = wave2 = wave3 = dds[0].wave;
   else { wave1 = dds[0].wave; wave2 = dds[1].wave; wave3 = dds[2].wave; }

   // update out buffers
   for (u32 i=(DDS_OUT_SAMPLES / 64); i--; ){
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
      *out1++ = wave1[acc1 >> DDS_SHIFT]; *out2++ = wave2[acc2 >> DDS_SHIFT];
      *out3++ = wave3[acc3 >> DDS_SHIFT]; acc1 += inc1; acc2 += inc2; acc3 += inc3;
   }

   // store current accumulators
   dds[0].phase.acc = acc1 - dds[0].phase.add;
   dds[1].phase.acc = acc2 - dds[1].phase.add;
   dds[2].phase.acc = acc3 - dds[2].phase.add;
}

u8 dds_chn, sync_prev;
PT_THREAD( dds_thread( struct pt *pt, struct ptx *ptx ) ) {
   PT_BEGIN(pt);

   while (1) {
      PT_YIELD(pt);

      // update Sync input
      u32 sync = !!dds_sync();
      if (!sync && sync_prev){
         cli();
         dds[0].phase.acc = dds[1].phase.acc = dds[2].phase.acc = 0;
         sei();
      }
      sync_prev = sync;

      // update DDS parameters
      for (dds_chn=0; dds_chn<DDS_CHANNELS; dds_chn++){
         // update waveform
         if (dds[dds_chn].update.form){
            if (config.params.s.dc[dds_chn] >= 0){
               u16 dac = config.params.s.dc[dds_chn] * (u32)DAC_OUT_MAX / 100;
               for (u32 i=0; i<DDS_WAVE_SAMPLES; i++) dds[dds_chn].table[i] = dac;
            } else {
               switch (config.params.s.form[dds_chn]){
                  case DDS_FORM_SINE:
                     for (u32 i=0; i<DDS_WAVE_SAMPLES; i++)
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - table_sine[i]) : table_sine[i];
                     break;
                  case DDS_FORM_SQR:
                     for (u32 i=0; i<DDS_WAVE_SAMPLES; i++){
                        u16 s = (i < DDS_WAVE_SAMPLES/2) ? 0 : DAC_OUT_MAX;
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - s) : s;
                     }
                     break;
                  case DDS_FORM_PWM:
                     dds[dds_chn].update.pwm = 1;
                     break;
                  case DDS_FORM_TRI: {
                     u16 w = 0;
                     for (u32 i=0; i<DDS_WAVE_SAMPLES/2; i++,w+=((DAC_OUT_MAX+1)/(DDS_WAVE_SAMPLES/2)))
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - w) : w;
                     for (u32 i=DDS_WAVE_SAMPLES/2; i<DDS_WAVE_SAMPLES; i++,w-=((DAC_OUT_MAX+1)/(DDS_WAVE_SAMPLES/2)))
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - w) : w;
                     break;
                  }
                  case DDS_FORM_SAW1: {
                     u16 w = 0;
                     for (u32 i=0; i<DDS_WAVE_SAMPLES; i++,w+=((DAC_OUT_MAX+1)/DDS_WAVE_SAMPLES))
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - w) : w;
                     break;
                  }
                  case DDS_FORM_SAW2: {
                     u16 w = DAC_OUT_MAX;
                     for (u32 i=0; i<DDS_WAVE_SAMPLES; i++,w-=((DAC_OUT_MAX+1)/DDS_WAVE_SAMPLES))
                        dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - w) : w;
                     break;
                  }
                  case DDS_FORM_DC:
                     dds[dds_chn].update.pwm = 1;
                     break;
                  case DDS_FORM_USER1:
                     break;
                  case DDS_FORM_USER2:
                     break;
                  case DDS_FORM_USER3:
                     break;
                  case DDS_FORM_USER4:
                     break;
               }
            }
            dds[dds_chn].update.form = 0;
            PT_YIELD(pt);
         }

         // update frequency
         if (dds[dds_chn].update.f){
            dds[dds_chn].phase.inc = 0x100000000uLL * config.set.s.f[dds_chn] / F_DDS / 1000uLL;
            dds[dds_chn].update.f = 0;
            PT_YIELD(pt);
         }

         // update phase
         if (dds[dds_chn].update.ph){
            dds[dds_chn].phase.add = config.set.s.ph[dds_chn] * 0xFFFFFFFFuLL / 359999uLL;
            dds[dds_chn].update.ph = 0;
            PT_YIELD(pt);
         }

         // update PWM
         if (dds[dds_chn].update.pwm){
            if (config.params.s.form[dds_chn] == DDS_FORM_PWM){
               u16 pwm = config.set.s.pwm[dds_chn] * DDS_WAVE_SAMPLES / 100000uL;
               for (u32 i=0; i<DDS_WAVE_SAMPLES; i++){
                  u16 s = (i < pwm) ? DAC_OUT_MAX : 0;
                  dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - s) : s;
               }
               dds[dds_chn].update.pwm = 0;
               PT_YIELD(pt);
            }
            else if (config.params.s.form[dds_chn] == DDS_FORM_DC){
               u16 dc = config.set.s.pwm[dds_chn] * DAC_OUT_MAX / 100000uL;
               for (u32 i=0; i<DDS_WAVE_SAMPLES; i++) dds[dds_chn].table[i] = config.params.s.inv[dds_chn] ? (DAC_OUT_MAX - dc) : dc;
            }
         }

      }
   }

   PT_END(pt);
   return PT_ENDED;
}

Re: 3-канальный DDS на STM32F303

Чт окт 03, 2019 15:12:24

ncp1400, а чем разработка закончилась, версией 0.1?

Re: 3-канальный DDS на STM32F303

Пт ноя 01, 2019 15:41:54

а чем должно закончиться ?... мне всего несколько раз был нужен 2/3-фазный синус/ШИМ с программируемой частотой/фазой.
в прошивке это реализовано, и больше к проекту не возвращался, платы демонтированы...

Re: 3-канальный DDS на STM32F303

Вс ноя 03, 2019 12:06:34

платы демонтированы...

Сурово. :)
Может быть , тогда, выложить проект целиком?
Кстати, какой шаг частоты синуса?

Re: 3-канальный DDS на STM32F303

Пт май 15, 2020 10:57:11

А кто то собирал схему из второго поста? Что то у меня на дисплее тишина, а на выходах просто постоянное напряжение.

Re: 3-канальный DDS на STM32F303

Ср окт 12, 2022 12:47:32

Всем добрый день, проблема с CAN на STM32F303VCT6 , прогу пишу в IAR, Can вообще никак не стартует, при этом gpio, таймеры все работает, может есть у кого готовый кусок кода с рабочей передачей по CAN, чтобы сравнить и найти косяк. До этого писал под st32f373, вообще никаких проблем.
Ответить