2017-03-25 30 views
1

내 STM32f3Discovery 보드에서 DAC를 사용하여 사인파를 생성해야하는 프로그램을 작성 중입니다. 아래에 나열된 여러 파일에 있습니다.STM32F3 DMA를 사용한 DAC 신호 생성

Utilities.h :

#ifndef UTILITIES_H 
#define UTILITIES_H 

/** @brief Configure GPIOE, pin 9 (LED) as output PP 
*/ 
void GPIOE_init(void); 

/** @brief Configure Timer 2, event frequency - 100Hz 
*/ 
void Timer_init(void); 

/** @brief Configure interrupt handler 
*/ 
void NVIC_config(void); 

/** @brief Configure and enable DAC channel 1 on pin PA4, 
* with TIM2 TRGO as trigger 
*/ 
void DACch1_config(void); 

/** @brief Configure DMA to work with DAC 
*/ 
void DMA_config(void); 

#endif //UTILITIES_H 

Utilities.c :

#include "utilities.h" 
#include "stm32f30x.h" 

const uint16_t sineWave12bit[32] = { 
     2048,2447,2831,3185,3495,3750,3939,4056, 
     4095,4056,3939,3750,3495,3185,2831,2447, 
     2048,1648,1264,910,600,345,156,39, 
     0,39,156,345,600,910,1264,1648 }; 

//This address is taken from reference manual for stm32f30 
//See pages 53 and 439 
#define DAC_DHR12RD_ADDRESS 0x40007420 

void Timer_init(void){ 

    /* Configuring frequency of timer, thus sinus frequency */ 
    /* Keep in mind, that system clock is set to 80Mhz */ 
    TIM_TimeBaseInitTypeDef timer2; 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 

    TIM_TimeBaseStructInit(&timer2); 
    timer2.TIM_CounterMode = TIM_CounterMode_Up; 
    //Setting prescaler so that timer clock will be only 10000Hz 
    timer2.TIM_Prescaler = 8000 - 1; 
    //Setting period so Timer will give signal of frequency 100Hz 
    timer2.TIM_Period = 100 - 1; 
    TIM_TimeBaseInit(TIM2, &timer2); 

    //generate event when counter hits TIM_period value 
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); 

    /* TIM2 enable counter */ 
    TIM_Cmd(TIM2, ENABLE); 
} 

void NVIC_config(void){ 
    NVIC_InitTypeDef nvic; 

    nvic.NVIC_IRQChannel = TIM2_IRQn; 
    nvic.NVIC_IRQChannelPreemptionPriority = 0; 
    nvic.NVIC_IRQChannelSubPriority = 0; 
    nvic.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&nvic); 
} 


void GPIOE_init(void){ 
    /* GPIOE initialization */ 
    GPIO_InitTypeDef  leds; 

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); 

    leds.GPIO_Pin = GPIO_Pin_9; 
    leds.GPIO_Mode = GPIO_Mode_OUT; 
    leds.GPIO_OType = GPIO_OType_PP; 
    leds.GPIO_Speed = GPIO_Speed_50MHz; 
    leds.GPIO_PuPd = GPIO_PuPd_NOPULL; 
    GPIO_Init(GPIOE, &leds); 
} 

void DACch1_config(void){ 
     /*******THERE IS ONLY ONE DAC ON STM32F30!!!!!!!!!!!!!!!!!!******************/ 
     DAC_InitTypeDef DACch1; 
     GPIO_InitTypeDef DACch1_out; 

     /* Enable GPIOA Periph clock */ 
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 

     /* Configure PA04 as analog */ 
     DACch1_out.GPIO_Pin = GPIO_Pin_4; 
     DACch1_out.GPIO_Mode = GPIO_Mode_AN; 
     DACch1_out.GPIO_OType = GPIO_OType_PP; 
     DACch1_out.GPIO_PuPd = GPIO_PuPd_NOPULL; 
     DACch1_out.GPIO_Speed = GPIO_Speed_50MHz; 
     GPIO_Init(GPIOA, &DACch1_out); 

     /* Enable DAC clock */ 
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); 

     /* Init the DAC_Init structure */ 
     DAC_StructInit(&DACch1); 

     /* Configure DAC */ 
     DACch1.DAC_Trigger = DAC_Trigger_T2_TRGO; 
     DACch1.DAC_WaveGeneration = DAC_WaveGeneration_None; 
     DACch1.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bits2_0; 
     DACch1.DAC_OutputBuffer = DAC_OutputBuffer_Disable; 

     /* DAC channel 1 configuration*/ 
     DAC_Init(DAC_Channel_1, &DACch1); 

     /* Enable DAC channel 1  */ 
     DAC_Cmd(DAC_Channel_1, ENABLE); 
} 


void DMA_config(void){ 
    DMA_InitTypeDef mem2DAC; 

    /* Enable clock for DMA1 */ 
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 

    /* Reset DMA1 channel 1 register values to default */ 
    DMA_DeInit(DMA1_Channel1); 

    //Specify destination address 
    mem2DAC.DMA_PeripheralBaseAddr = DAC_DHR12RD_ADDRESS; 
    //Specify source address - LUT for sine 
    mem2DAC.DMA_MemoryBaseAddr = (uint32_t) &sineWave12bit; 
    //Set Peripheral as destination 
    mem2DAC.DMA_DIR = DMA_DIR_PeripheralDST; 
    mem2DAC.DMA_BufferSize = 32; 
    mem2DAC.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    mem2DAC.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    mem2DAC.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 
    mem2DAC.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
    mem2DAC.DMA_Mode = DMA_Mode_Circular; 
    mem2DAC.DMA_Priority = DMA_Priority_High; 
    mem2DAC.DMA_M2M = DMA_M2M_Disable; 

    DMA_Init(DMA1_Channel1, &mem2DAC); 

    /* Enable DMA1 Channel1 */ 
    DMA_Cmd(DMA1_Channel1, ENABLE); 

    /* Enable DMA fo DAC channel 1*/ 
    DAC_DMACmd(DAC_Channel_1, ENABLE); 

} 

을 main.c :

/** 
    ****************************************************************************** 
    * @file main.c 
    * @author Ac6 
    * @version V1.0 
    * @date 01-December-2013 
    * @brief Default main function. 
    ****************************************************************************** 
*/ 


#include "stm32f30x.h" 
#include "utilities.h" 

int main(void) 
{ 
    DMA_config(); 

    DACch1_config(); 

    Timer_init(); 

    while(1){ 

    } 
} 

그래서 이론적으로는 핀 A.04에 사인 파형을 생성한다 . 그러나 osciloscope를 사용하여이 핀의 전압을 볼 때 아무 것도 표시되지 않습니다 (접지 전위).

무엇이 잘못 되었습니까?

답변

2

괜찮 았어. 관심있는 사람이 있다면 DAC_1을 DMA2 채널 3로 사용할 수있는 적합한 DMA 채널처럼 보입니다. DMA1 채널 3으로 다시 매핑 될 수 있습니다.

편집 :

모든 것이 작동합니다.

  1. 이 timerX을 위해 시계를 사용 (꼭 타이머 TRGO 이벤트와 DAC를 트리거 할 사용할 수있는 참조), DMA :이 사람에게 어떤 도움 인 경우, 여기 STM32f3에 DAC의 woring를 얻기 위하여 필요한 모든 조치는 , DAC 및 GPIOA. DAC에 기본값이 아닌 DMA를 사용하려면 SYSCFG의 시계를 활성화하십시오.

  2. 원하는 DAC 채널을 설정하십시오. STM32f3 디스커버리 (Discovery)에는 2 개의 채널이있는 DAC가 1 개뿐입니다. DACch1 출력은 PA4이고, DACch2 출력은 PA5입니다.

  3. 선택한 GPIOA를 아날로그 입력 및 초기화로 구성하십시오.

  4. DAC 및 초기화를 구성하십시오. DAC에서 DMA를 사용하도록하십시오.

  5. DAC에서 사용할 DMA의 기본 설정을 변경하려면 SYSCFG_DMAChannelRemapConfig 명령을 사용하십시오.

  6. DMA 및 init을 구성하십시오.

  7. 원하는 타이머와 init을 구성하십시오. TRGO 인터럽트를 설정하는 것을 잊지 마십시오!

아래에는 기본값이 아닌 DMA를 사용하는 DACch1에서 사인파 생성을위한 작업 코드가 포함됩니다.

#include "utilities.h" 
#include "stm32f30x.h" 

const uint16_t sineWave12bit[64] = { 
     2048,2248,2447,2642,2831,3013,3185,3346, 
     3495,3630,3750,3853,3939,4007,4056,4085, 
     4095,4085,4056,4007,3939,3853,3750,3630, 
     3495,3346,3185,3013,2831,2642,2447,2248, 
     2048,1847,1648,1453,1264,1082,910,749, 
     600,465,345,242,156,88,39,10, 
     0,10,39,88,156,242,345,465, 
     600,749,910,1082,1264,1453,1648,1847 }; 

//This address is taken from reference manual for stm32f30 
//See pages 53 and 439 
#define DAC_DHR12R1_ADDRESS 0x40007408 

void Timer_init(void){ 

    /* Configuring frequency of timer, thus sinus frequency */ 
    /* Keep in mind, that system clock is set to 80Mhz */ 
    TIM_TimeBaseInitTypeDef timer2; 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 

    TIM_TimeBaseStructInit(&timer2); 
    timer2.TIM_CounterMode = TIM_CounterMode_Up; 
    //Setting prescaler so that timer clock will be only 10000Hz 
    timer2.TIM_Prescaler = 8000 - 1; 
    //Setting period so Timer will give signal of frequency 1000Hz 
    timer2.TIM_Period = 10 - 1; 
    TIM_TimeBaseInit(TIM2, &timer2); 

    //generate event when counter hits TIM_period value 
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); 

    /* TIM2 enable counter */ 
    TIM_Cmd(TIM2, ENABLE); 
} 

void NVIC_config(void){ 
    NVIC_InitTypeDef nvic; 

    nvic.NVIC_IRQChannel = TIM2_IRQn; 
    nvic.NVIC_IRQChannelPreemptionPriority = 0; 
    nvic.NVIC_IRQChannelSubPriority = 0; 
    nvic.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&nvic); 
} 


void GPIOE_init(void){ 
    /* GPIOE initialization */ 
    GPIO_InitTypeDef  leds; 

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); 

    leds.GPIO_Pin = GPIO_Pin_9; 
    leds.GPIO_Mode = GPIO_Mode_OUT; 
    leds.GPIO_OType = GPIO_OType_PP; 
    leds.GPIO_Speed = GPIO_Speed_50MHz; 
    leds.GPIO_PuPd = GPIO_PuPd_NOPULL; 
    GPIO_Init(GPIOE, &leds); 
} 

void DACch1_config(void){ 
     /*******THERE IS ONLY ONE DAC ON STM32F30!!!!!!!!!!!!!!!!!!******************/ 
     DAC_InitTypeDef DACch1; 
     GPIO_InitTypeDef DACch1_out; 

     /* Enable GPIOA Periph clock */ 
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 

     /* Configure PA04 as analog */ 
     DACch1_out.GPIO_Pin = GPIO_Pin_4; 
     DACch1_out.GPIO_Mode = GPIO_Mode_AN; 
     DACch1_out.GPIO_PuPd = GPIO_PuPd_NOPULL; 
     GPIO_Init(GPIOA, &DACch1_out); 

     /* Enable DAC clock */ 
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); 

     /* Init the DAC_Init structure */ 
     DAC_StructInit(&DACch1); 

     /* Reset DAC configuration */ 
     DAC_DeInit(); 

     /* Configure DAC */ 
     DACch1.DAC_Trigger = DAC_Trigger_T2_TRGO; 
     DACch1.DAC_WaveGeneration = DAC_WaveGeneration_None; 
     DACch1.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bits2_0; 
     DACch1.DAC_OutputBuffer = DAC_OutputBuffer_Enable; 

     /* DAC channel 1 configuration*/ 
     DAC_Init(DAC_Channel_1, &DACch1); 

     /* Enable DAC channel 1  */ 
     DAC_Cmd(DAC_Channel_1, ENABLE); 
} 


void DMA_config(void){ 
    DMA_InitTypeDef mem2DAC; 

    /* Enable clock for SYSCFG in order to change DMA for DAC from 
    * DMA2 channel3 to DMA1 channel 3 (default is DMA2 channel 3) */ 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 

    /* Use DMA1 channel 3 for DAC1 */ 
    SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM6DAC1, ENABLE); 

    /* Enable clock for DMA1 */ 
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 

    /* Reset DMA1 channel 1 register values to default */ 
    DMA_DeInit(DMA1_Channel3); 

    mem2DAC.DMA_PeripheralBaseAddr = DAC_DHR12R1_ADDRESS; 
    mem2DAC.DMA_MemoryBaseAddr = (uint32_t)&sineWave12bit; 
    mem2DAC.DMA_DIR = DMA_DIR_PeripheralDST; 
    mem2DAC.DMA_BufferSize = 64; 
    mem2DAC.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    mem2DAC.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    mem2DAC.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
    mem2DAC.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
    mem2DAC.DMA_Mode = DMA_Mode_Circular; 
    mem2DAC.DMA_Priority = DMA_Priority_High; 
    mem2DAC.DMA_M2M = DMA_M2M_Disable; 

    DMA_Init(DMA1_Channel3, &mem2DAC); 

    /* Enable DMA1 Channel1 */ 
    DMA_Cmd(DMA1_Channel3, ENABLE); 

    /* Enable DMA fo DAC channel 1*/ 
    DAC_DMACmd(DAC_Channel_1, ENABLE); 

} 
0

비슷한 문제가 발생했습니다. 먼저 MCU에 DAC 블록이 있는지 확인하십시오. DAC 주변 장치가 없을 경우 사인파가 생성되지 않습니다. 특정 마이크로 컨트롤러 패키지의 데이터 시트에서이를 확인할 수 있습니다.

+0

예, DAC가 있습니다. 특정 마이크로 컨트롤러 이름은 STM32f303VC이다. 공식 제품 사양 (http://www.st.com/content/ccc/resource/technical/document/datasheet/f2/1f/e1/41/ef/59/4d/50/DM00058181.pdf/)에서 확인했습니다. files/DM00058181.pdf/jcr : content/translations/en.DM00058181.pdf). DAC1 출력은 PA4 출력에서 ​​사용할 수 있으므로 제대로 작동해야합니다.나는 명백한 것에 대해 잊어 버렸다고 생각하지만 실수를 발견 할 수는 없다. –