main.c
0.01MB
stm32f4xx_it.c
0.01MB

 

드론 외에 ADC와 DAC를 사용한 다른 프로젝트를 생각한 게 있어 기본 코드를 작성했다.

 

ADC, DAC모두 DMA를 사용하며 TIM2에서 TRGO 신호를 받아 작동한다.

 

 

TIM 코드 생성 - (0)

PIN
Parameter Settings

TIM2는 ADC의 변환과 DAC의 값을 출력할때의 Trigger 신호를 발생한다.

 

UPDATE Event가 발생하면 신호가 발생하여 ADC와 DAC를 작동한다.

 

ARR 레지스터의 값에 해당하는 Counter Period의 값은 원하는 값으로 변경해서 사용할 것이므로 아무 값을 넣었다.

 

 

ADC 코드 생성 - (1)

Parameter Settings
NVIC Settings
DMA Settings

 

ADC 는 TIM2의 Trigger 신호를 받아 변환을 시작한다.

 

Interrupt는 DMA interrupt 외에 사용하지 않는다.

 

DMA의 경우 Circular 모드를 사용하여 DMA_SxNDTR레지스터가 원래 설정해둔 값으로 자동으로 초기화할 수 있도록 한다.

 

 

DAC 코드 생성 - (2)

Parameter Settings
NVIC Settings
DMA Settings

Trigger는 TIM2의 UPDATE Event에 의해 발생하는 신호에 의해 값이 출력이 된다.

 

DMA의 경우 ADC와 동일하게 Circular 모드를 사용한다.

 

 

main.c - (3)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* USER CODE BEGIN 0 */
 
uint16_t adc[160];
uint8_t condition_tc=0;
 
/* USER CODE END 0 */
 
 
 /* USER CODE BEGIN 2 */
 
  LL_TIM_SetAutoReload(TIM2,50);
  LL_TIM_EnableCounter(TIM2);
 
  LL_DMA_SetDataLength(DMA2,LL_DMA_STREAM_0,16);
  LL_DMA_SetPeriphAddress(DMA2,LL_DMA_STREAM_0,(uint32_t)(&ADC1->DR));
  LL_DMA_SetMemoryAddress(DMA2,LL_DMA_STREAM_0,(uint32_t)adc);
  LL_DMA_EnableIT_TC(DMA2,LL_DMA_STREAM_0);
  LL_DMA_EnableStream(DMA2,LL_DMA_STREAM_0);
 
  LL_DMA_SetDataLength(DMA1,LL_DMA_STREAM_5,16);
  LL_DMA_SetPeriphAddress(DMA1,LL_DMA_STREAM_5,LL_DAC_DMA_GetRegAddr(DAC1,LL_DAC_CHANNEL_1,LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED));
  LL_DMA_SetMemoryAddress(DMA1,LL_DMA_STREAM_5,(uint32_t)adc);
  LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_5);
 
  LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
  LL_ADC_Enable(ADC1);
 
 
  LL_DAC_EnableTrigger(DAC1,LL_DAC_CHANNEL_1);
  LL_DAC_EnableDMAReq(DAC1,LL_DAC_CHANNEL_1);
  LL_DAC_Enable(DAC1,LL_DAC_CHANNEL_1);
 
  /* USER CODE END 2 */
 

 

3번째 줄의 adc 배열은 ADC의 값들을 저장하는 배열이다. DMA가 전달하는 데이터의 양은 16으로 설정했지만 그 이상의 개수를 실험하기 위해 160 정도를 선언했다.

 

4번째 줄의 condition_tc는 stm32f4xx_it.c 파일 내부의 ADC의 DMA2 Stream0 TC Interrupt가 실행되면 1이 된다. 즉 ADC가 16개의 값을 Sampling 하여 DMA가 adc 배열에 모든 값을 저장하면 interrupt가 실행된다.

 

11번째 줄의 LL_TIM_SetAutoreload()로 TIM의 ARR레지스터의 값을 변경할 수 있다. 1000으로 설정한 값을 50으로 낮춰 약 50us의 주기로 sampling한다. 원하는 주기의 값으로 설정하면 된다.

 

14에서 23번째 줄까지 ADC, DAC의 DMA설정을 하는 부분이다.

 

 

25번째 줄의 설정은 ADC_CR2의 레지스터를 변경하는데 DDS를 SET, DMA를 SET하지 않을경우 지속적으로 DMA가 실행되지 않는다.

 

while문 내부의 코드는 TC Interrupt가 발생하면 DMA가 전달한 데이터를 출력하는 간단한 코드이므로 추가적인 설명은 하지 않겠다.

 

 

결과 - (4)

1
2
3
4
5

 

1번 사진은 값들을 터미널 프로그램으로 값들을 출력하는 사진이다.

 

2번 사진의 경우 노란색 신호가 Rising edge, Falling edge일때edge일 때 ADC가 Sampling 하는 순간이다. 파란색 신호의 경우 Rising edge, Falling edge일 때 ADC DMA의 TC Interrupt가 발생하는 순간이다.

 

3번의 사진은 코드에는 작성하지 않고 따로 실험해본 결과인데 ADC DMA의 TC Interrupt, DAC DMA의 TC Interrupt가 발생하는 순간이다.

 

4번의 사진은 ADC에 연결되어 있는 가변저항을 조절하여 전압의 변화를 줬을때 그 전압값을 ADC가 Sampling 하여 DAC로 출력한 결과이다.

 

5번 사진은 실제 연결되어 있는 모습을 보여준다.

 

 

 

-

ADC와 DAC를 사용하여 헥사콥터 외의 프로젝트를 조금씩 시작해 보려고 한다.

 

생각하는 프로젝트의 기본이 되는 ADC와 DAC를 작동하는 코드를 작성해 보았으며 제대로 작동하고 있는 모습을 보여준다.

 

아직 고려해야할 사항이 많기 때문에 구체적인 내용은 나중에 쓸 생각이다.

 

 

생각하는 프로젝트 외에 STM32를 사용한 CMSIS DSP라이브러리를 사용하여 FFT를 하는 코드도 나중에 작성할 생각이다.

Posted by DDTXRX
,