STM32 DAC Dual Channel - FabLabSeoul/WingProject GitHub Wiki

STM32 DAC Dual Channel ํ”„๋กœ๊ทธ๋ž˜๋ฐ

STM32 Value line discovery ๋ณด๋“œ์šฉ ํŠœํ† ๋ฆฌ์–ผ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์„ค๋ช…ํ•˜๋Š” ์˜ˆ์ œ์ฝ”๋“œ๋Š” http://elk.informatik.fh-augsburg.de/pub/stm32lab/libs/STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Examples/DAC/TwoChannels_TriangleWave/ ์‚ฌ์ดํŠธ์— ์žˆ๋‹ค.

STM32 DAC ์˜ˆ์ œ์—์„œ๋Š” ํ•˜๋‚˜์˜ ์ฑ„๋„๋กœ ์•„๋‚ ๋กœ๊ทธ ์ถœ๋ ฅ์„ ํ–ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ ์ฑ„๋„๋กœ ์•„๋‚ ๋กœ๊ทธ ์ถœ๋ ฅ์„ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํƒ€์ด๋จธ๋ฅผ ํ†ตํ•ด ํด๋Ÿญ์„ ์กฐ์ ˆํ•œ๋‹ค. STM32 DAC์—์„œ๋Š” Software Trigger๋ฅผ ํ†ตํ•ด ๋™๊ธฐํ™” ์‹œ์ผฐ๋‹ค. DAC ๋‘๊ฐœ์˜ ์ถœ๋ ฅ์€ PA4,5 ํฌํŠธ๋กœ ๋‚˜์˜จ๋‹ค. STM32 ๊ธฐ๋ณธ ์„ค์ •์ด๋‹ค.

๋จผ์ € ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜์ž. STM32๋Š” PWM์„ ์œ„ํ•œ TIM1๊ณผ ์ผ๋ฐ˜ ์šฉ๋„์˜ TIM2,3,4 ๊ฐ€ ์žˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ stm32f103์‘์šฉ.pdf๋ฅผ ์ฐธ์กฐํ•˜์ž. ์—ฌ๊ธฐ์„œ๋Š” TIM2๋ฅผ ์ด์šฉํ•ด DAC๋ฅผ ๋™๊ธฐํ™” ์‹œํ‚จ๋‹ค.

STM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํƒ€์ด๋จธ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

/** 
  * @brief TIM
  */
typedef struct
{
  __IO uint16_t CR1;
  uint16_t  RESERVED0;
  __IO uint16_t CR2;
  uint16_t  RESERVED1;
  __IO uint16_t SMCR;
  uint16_t  RESERVED2;
  __IO uint16_t DIER;
  uint16_t  RESERVED3;
  __IO uint16_t SR;
  uint16_t  RESERVED4;
  __IO uint16_t EGR;
  uint16_t  RESERVED5;
  __IO uint16_t CCMR1;
  uint16_t  RESERVED6;
  __IO uint16_t CCMR2;
  uint16_t  RESERVED7;
  __IO uint16_t CCER;
  uint16_t  RESERVED8;
  __IO uint16_t CNT;
  uint16_t  RESERVED9;
  __IO uint16_t PSC;
  uint16_t  RESERVED10;
  __IO uint16_t ARR;
  uint16_t  RESERVED11;
  __IO uint16_t RCR;
  uint16_t  RESERVED12;
  __IO uint16_t CCR1;
  uint16_t  RESERVED13;
  __IO uint16_t CCR2;
  uint16_t  RESERVED14;
  __IO uint16_t CCR3;
  uint16_t  RESERVED15;
  __IO uint16_t CCR4;
  uint16_t  RESERVED16;
  __IO uint16_t BDTR;
  uint16_t  RESERVED17;
  __IO uint16_t DCR;
  uint16_t  RESERVED18;
  __IO uint16_t DMAR;
  uint16_t  RESERVED19;
} TIM_TypeDef;

ํƒ€์ด๋จธ ๋ ˆ์ง€์Šคํ„ฐ์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ๋งค๋‰ด์–ผ 311ํŽ˜์ด์ง€์— ์ž˜ ๋‚˜์™€ ์žˆ๋‹ค.

ํƒ€์ด๋จธ ์„ค์ •

๋‹ค์Œ ์ฝ”๋“œ๋Š” STM32 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํƒ€์ด๋จธ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ํ™˜๊ฒฝ์„ค์ •์„ ํ•œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‚˜๋„ ์ž˜ ๋ชจ๋ฅด๋‹ˆ ํŒจ์Šค~

/* TIM2 Configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xF;
TIM_TimeBaseStructure.TIM_Prescaler = 0xF;       
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);	

DAC ์„ค์ •

DAC ๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. ๋‘ ๊ฐœ์˜ ์ฑ„๋„์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๋ฒˆ์˜ DAC_Init() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๋‘ ์ฑ„๋„์˜ ๋‹ค๋ฅธ์ ์€ DAC_TriangleAmplitude_x ๋ฐ–์— ์—†๋‹ค. ๋‘ ๋ฒˆ์งธ ์ฑ„๋„์ด ์ข€๋” ์•ฝํ•œ ์‹ ํ˜ธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. ์›๋ณธ ์˜ˆ์ œ์ฝ”๋“œ๋Š” OutputBuffer๋ฅผ ๋น„ํ™œ์„ฑ์ƒํƒœ๋กœ ์„ค์ • ํ–ˆ๋‹ค. ์˜ค์‹ค๋กœ์Šค์ฝ”ํ”„๋กœ ํŒŒํ˜•์„ ๋ณด๊ธฐ ์œ„ํ•ด์„œ์ธ๋ฐ, ๋‚˜๋Š” ๊ทธ๋Ÿฐ ๋น„์‹ผ ์žฅ๋น„๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ณผ๋ฅผ ์Šคํ”ผ์ปค๋กœ ์ถœ๋ ฅํ–ˆ๋‹ค. ์ถœ๋ ฅ๋‹จ์ž์— ์ €ํ•ญ์ด ์žˆ๋”๋ผ๋„ ๋˜‘๊ฐ™์€ ์ „์••์„ ์ถœ๋ ฅํ•˜๋ ค๋ฉด OutputBuffer ๋ฅผ ํ™œ์„ฑํ™” ํ•ด์•ผํ•œ๋‹ค. ๊ทธ ๋ถ€๋ถ„์ด ๋ฐ”๋€ ๋ถ€๋ถ„์ด๋‹ค.

/* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095; 
//DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);

/* DAC channel2 Configuration */
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;
DAC_Init(DAC_Channel_2, &DAC_InitStructure);

/* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is 
   automatically connected to the DAC converter. */
DAC_Cmd(DAC_Channel_1, ENABLE);

/* Enable DAC Channel2: Once the DAC channel2 is enabled, PA.05 is 
   automatically connected to the DAC converter. */
DAC_Cmd(DAC_Channel_2, ENABLE);

/* Set DAC dual channel DHR12RD register */
DAC_SetDualChannelData(DAC_Align_12b_R, 0x100, 0x100);

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

์ „์ฒด์ฝ”๋“œ

์ด ์˜ˆ์ œ๋Š” DAC ๋‘ ์ฑ„๋„์„ ์ด์šฉํ•ด ์‚ผ๊ฐํŒŒ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. ์Šคํ”ผ์ปค(piezo buzzer)๋ฅผ ๋‹ฌ๋ฉด ์†Œ๋ฆฌ๋ฅผ ๋“ค์„ ์ˆ˜ ์žˆ๋‹ค. ์ž์ฒด ํƒ€์ด๋จธ๋ฅผ ์ด์šฉํ•˜๊ณ , ์ฑ„๋„์„ ์ด์šฉํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” \STM32\stm32vldiscovery_package\Project\Examples\DAC_Channel2 ํด๋”์— ์žˆ๋‹ค.

#include "stm32f10x.h"

DAC_InitTypeDef 		DAC_InitStructure;
TIM_TimeBaseInitTypeDef	TIM_TimeBaseStructure;

void RCC_Configuration(void);
void GPIO_Configuration(void);
void Delay(__IO uint32_t nCount);

int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */
       
  /* System Clocks Configuration */
  RCC_Configuration();   

  /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically 
     connected to the DAC converter. In order to avoid parasitic consumption, 
     the GPIO pin should be configured in analog */
  GPIO_Configuration();

  /* TIM2 Configuration */
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 0xF;
  TIM_TimeBaseStructure.TIM_Prescaler = 0xF;       
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* TIM2 TRGO selection */
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);	

  /* DAC channel1 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095; 
	//DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  /* DAC channel2 Configuration */
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);

  /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is 
     automatically connected to the DAC converter. */
  DAC_Cmd(DAC_Channel_1, ENABLE);

  /* Enable DAC Channel2: Once the DAC channel2 is enabled, PA.05 is 
     automatically connected to the DAC converter. */
  DAC_Cmd(DAC_Channel_2, ENABLE);

  /* Set DAC dual channel DHR12RD register */
  DAC_SetDualChannelData(DAC_Align_12b_R, 0x100, 0x100);

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

  while (1)
  {
  }
}


/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{   
  /* Enable peripheral clocks ------------------------------------------------*/
  /* GPIOA Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  /* DAC Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
	
  /* TIM2 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}

/**
  * @brief  Configures the different GPIO ports.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Once the DAC channel is enabled, the corresponding GPIO pin is automatically 
     connected to the DAC converter. In order to avoid parasitic consumption, 
     the GPIO pin should be configured in analog */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/**
  * @brief  Inserts a delay time.
  * @param  nCount: specifies the delay time length.
  * @retval None
  */
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif