AnsweredAssumed Answered

Sinewave using Dual DAC basically doesn't work

Question asked by Antoine.PM on Jun 27, 2016
Latest reply on Jun 29, 2016 by Antoine.PM
Hi.

I am trying to output a sine using the DAC of my STM32 F334R8.

I spent days trying to do so with the example in the SPL. This example uses a button (which is not present on my board) to switch between, in one hand, a sine and an escalator waveform (using respectively channel 1 and 2), and in other hand noise and triangle waveform (using both channels too). I thought it would be ok if I just isolated the waveform I wanted, but it turned out it was not.

What I did just now is to use a code kindly provided on [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/sawtooth&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=97]an older thread by clive1 to generate a sinewave using both channels.

It was not the same device, so I adjusted it the best I could, and it almost works, I think.

The problem is, my amplitude is ridiculously low: circa 3 mV.
When I do the proper adjustments on the oscilloscope, it almost looks like a very ugly sine, but I think this is mainly noise.

Honestly I don't know what I could do.
My goal is to have a sine with an amplitude of 3.3 V, and a frequency of, let's say 1 or 10 kHz.

I have tried many things, many codes, tried to get familiar with the device by using some easier examples, but eventually I'm always stuck there.

Here is the code I came up with, if you see some huge mistake or anything please point them out:

001.#include "main.h"
002. 
003.const uint16_t Sine12bit[32] = {
004.  2047, 2447, 2831, 3185,
005.  3498, 3750, 3939, 4056,
006.  4095, 4056, 3939, 3750,
007.  3495, 3185, 2831, 2447,
008.  2047, 1647, 1263,  909,
009.   599,  344,  155,   38,
010.     0,   38,  155,  344,
011.   599,  909, 1263, 1647};
012.   
013.uint16_t SineTable[64];
014.   
015./**************************************************************************/
016.   
017.void RCC_Config(void)
018.{
019.  /* DMA1 clock and GPIOA clock enable (to be used with DAC) */
020.  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
021.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
022.     
023.   
024.  /* DAC and TIM6 Peripheral clock enable */
025.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);
026.}
027.   
028./**************************************************************************/
029.   
030.void GPIO_Config(void)
031.{
032.  GPIO_InitTypeDef GPIO_InitStructure;
033.   
034.  /* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
035.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
036.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
037.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
038.  GPIO_Init(GPIOA, &GPIO_InitStructure);
039.}
040.   
041./**************************************************************************/
042.   
043.void TIM6_Config(void)
044.{
045.    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
046.    int Period;
047.   
048.  Period = ((SystemCoreClock / 2) / 200000); // 200 KHz timebase, 6.25 KHz Sine
049.   
050.  /* Time base configuration */
051.  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
052.  TIM_TimeBaseStructure.TIM_Period = Period - 1;
053.  TIM_TimeBaseStructure.TIM_Prescaler = 0;
054.  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
055.  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
056.  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
057.   
058.  /* TIM6 TRGO selection */
059.  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
060.   
061.  /* TIM6 enable counter */
062.  TIM_Cmd(TIM6, ENABLE);
063.}
064.   
065./**************************************************************************/
066.   
067.#define DAC_DHR12RD_ADDRESS 0x40007428 // Right Align 12-bit Dual
068.   
069.void DAC_Config(void)
070.{
071.    DAC_InitTypeDef DAC_InitStructure;
072.  DMA_InitTypeDef DMA_InitStructure;
073.   
074.  /* DAC channel 1 and 2 Configuration */
075.  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
076.  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
077.//  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //doesn't exist with standard libraries
078.    DAC_InitStructure.DAC_Buffer_Switch = DAC_BufferSwitch_Enable;
079.  DAC_Init(DAC1, DAC_Channel_1, &DAC_InitStructure);
080.  DAC_Init(DAC1, DAC_Channel_2, &DAC_InitStructure);
081.   
082.  /* DMA1_channel3 configuration **************************************/
083.  DMA_DeInit(DMA1_Channel3);
084.  DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_ADDRESS;
085.  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&SineTable;
086.  DMA_InitStructure.DMA_BufferSize = 32; // 16-bit x 64 / 2
087.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // 32-bit 16x2
088.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
089.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
090.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
091.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
092.  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
093.  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
094.  DMA_Init(DMA1_Channel3, &DMA_InitStructure);
095. 
096.   
097.  /* Enable DMA1_Channel3 */
098.  DMA_Cmd(DMA1_Channel3, ENABLE);
099.   
100.  /* Enable DAC Channel 1 and 2 */
101.  DAC_Cmd(DAC1, DAC_Channel_1, ENABLE);
102.  DAC_Cmd(DAC1, DAC_Channel_2, ENABLE);
103. 
104./*If I comment the two lines above, almost nothing change in the signal I see. I take it as an evidence this code doesn't work at all */
105.   
106.  /* Enable DMA for DAC Channel1 */
107.  DAC_DMACmd(DAC1, DAC_Channel_1, ENABLE);
108.}
109.   
110./**************************************************************************/
111.   
112.int main(void)
113.{
114.  int i, j;
115.   
116.  j = 0;
117.   
118.  for(i=0; i<32; i++)
119.  {
120.    SineTable[j++] = Sine12bit[i];
121.    SineTable[j++] = Sine12bit[(i + 8) % 32]; // 90 degree phase shift on Channel 2
122.  }
123.   
124.  RCC_Config();
125.   
126.  GPIO_Config();
127.   
128.  TIM6_Config();
129.   
130.  DAC_Config();
131.   
132.  while(1); // Do not exit
133.}

- i don't understand how the dual mode works: how does the DAC know it is supposed to outputs each case of the table alternatively in each channel?

- What is the point of doing that, rather than using just one channel?

- My stm32f30x_tim.h specifically says that the basic TIM_TimeBaseInitTypeDef; is "
used with all TIMx except for TIM6 and TIM7." So i changed it for TIM2, which doesn't work either.
Besides, how am I supposed to use the Timer 6 and 7? How do they work? I only know they are basic timers dedicated to DAC, but nothing about how to use it, how to implement it.

- If i have in fact the value 4095 in the table, I suppose I should see a max of 3.3 V. Why is it not the case?

- How do i know if the table is even read? I'm not sure I know how to interprete correctly the debug mode.

I have more or less the same result when I use the code from the example.

I wonder if something could be wrong in the startup file or something like that.

Thank you.

Outcomes