Question
Sinewave using Dual DAC basically doesn't work
Posted on June 27, 2016 at 19:01
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¤tviews=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:
#include ''main.h''
const
uint16_t Sine12bit[32] = {
2047, 2447, 2831, 3185,
3498, 3750, 3939, 4056,
4095, 4056, 3939, 3750,
3495, 3185, 2831, 2447,
2047, 1647, 1263, 909,
599, 344, 155, 38,
0, 38, 155, 344,
599, 909, 1263, 1647};
uint16_t SineTable[64];
/**************************************************************************/
void
RCC_Config(
void
)
{
/* DMA1 clock and GPIOA clock enable (to be used with DAC) */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* DAC and TIM6 Peripheral clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);
}
/**************************************************************************/
void
GPIO_Config(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**************************************************************************/
void
TIM6_Config(
void
)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
int
Period;
Period = ((SystemCoreClock / 2) / 200000);
// 200 KHz timebase, 6.25 KHz Sine
/* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
/* TIM6 TRGO selection */
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
/* TIM6 enable counter */
TIM_Cmd(TIM6, ENABLE);
}
/**************************************************************************/
#define DAC_DHR12RD_ADDRESS 0x40007428 // Right Align 12-bit Dual
void
DAC_Config(
void
)
{
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* DAC channel 1 and 2 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
// DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //doesn't exist with standard libraries
DAC_InitStructure.DAC_Buffer_Switch = DAC_BufferSwitch_Enable;
DAC_Init(DAC1, DAC_Channel_1, &DAC_InitStructure);
DAC_Init(DAC1, DAC_Channel_2, &DAC_InitStructure);
/* DMA1_channel3 configuration **************************************/
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&SineTable;
DMA_InitStructure.DMA_BufferSize = 32;
// 16-bit x 64 / 2
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
// 32-bit 16x2
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* Enable DMA1_Channel3 */
DMA_Cmd(DMA1_Channel3, ENABLE);
/* Enable DAC Channel 1 and 2 */
DAC_Cmd(DAC1, DAC_Channel_1, ENABLE);
DAC_Cmd(DAC1, DAC_Channel_2, ENABLE);
/*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 */
/* Enable DMA for DAC Channel1 */
DAC_DMACmd(DAC1, DAC_Channel_1, ENABLE);
}
/**************************************************************************/
int
main(
void
)
{
int
i, j;
j = 0;
for
(i=0; i<32; i++)
{
SineTable[j++] = Sine12bit[i];
SineTable[j++] = Sine12bit[(i + 8) % 32];
// 90 degree phase shift on Channel 2
}
RCC_Config();
GPIO_Config();
TIM6_Config();
DAC_Config();
while
(1);
// Do not exit
}
- 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.