AnsweredAssumed Answered

Timer/DAC reset?

Question asked by meyer.mike.001 on Jul 16, 2016
Latest reply on Jul 21, 2016 by waclawek.jan
I'm trying to do a thorough exploration of the DAC, so set up a demo on a STM32F429I-Discovery that uses a number of different techniques to set up a waveform, switching between them (and spitting out the demo name) when the user button is pressed.

Everything works fine - if it's run first. The two demos that use the DAC wave generation fail in different ways if the other one is run first. This makes me think the issue is that I'm not properly resetting something between demos. Actually, two somethings, as the two fail in different ways.

I'm using libopencm3 as a HAL. Here's the reset code, which is also run before the first demo, just to make sure:

static void
dac_teardown(void) {
     timer_disable_counter(TIM6);
     timer_disable_update_event(TIM6);
     timer_reset(TIM6);
 
     dac_disable(CHANNEL_2);
     dac_trigger_disable(CHANNEL_2);
     dac_disable_waveform_generation(CHANNEL_2);
}

The first example - noise generation - doesn't use the timer, but uses a software trigger in the main code to cause new values to be loaded from the DAC. Here's the setup code:

static void
dac_noise_setup(void) {
     dac_set_waveform_generation(DAC_CR_WAVE2_NOISE);
     /* 9 bit - or 512 - maximum amplitude value, 1024 sample wavelength */
     dac_set_waveform_characteristics(DAC_CR_MAMP2_8);
     dac_set_trigger_source(DAC_CR_TSEL2_SW);
     dac_trigger_enable(CHANNEL_2);
     dac_enable(CHANNEL_2);
}

When this demo is run first, it works fine. If run after the second demo (setup below), it acts like MAMPS is set to 12 instead of 8.

The second demo uses the the timer6 trigger to generate a triangle wave. Setup is:

static void
dac_triangle_setup(void) {
    /* Set up and start the dac wave generation */
     dac_set_waveform_generation(DAC_CR_WAVE2_TRI);
     dac_set_waveform_characteristics(DAC_CR_MAMP2_10);
     dac_buffer_enable(CHANNEL_2);
     dac_trigger_enable(CHANNEL_2);
     dac_set_trigger_source(DAC_CR_TSEL2_T6);
     dac_enable(CHANNEL_2);
 
     /* Set up and start the timer. */
     timer_set_prescaler(TIM6, 0);
     timer_set_period(TIM6, 9);
     timer_continuous_mode(TIM6);
     timer_enable_update_event(TIM6);
     timer_set_master_mode(TIM6, TIM_CR2_MMS_UPDATE);
     timer_enable_counter(TIM6);
}

Again, this works if it's run first. If run after the noise demo above, it doesn't generate output.

Both demo's run fine if I run them first. If I run them second, or switch to the other demo and then back to them after running them first, I get the broken behavior described. I've disabled all the other demos, so no other setup code is running. The reference manual talks about order dependencies for some of these things, but that I run the teardown code before any demos and they still work first time makes me think I've got those right, possibly incorrectly.

Note that I'm posting libopencm3 code because I want to post the code I'm using. If you have working code to do similar things using a different HAL, please don't hesitate to share it!

Outcomes