본문 바로가기
  • SpokeHouse
STM32/STM32F

STM32F103 - ADC DMA 읽어오기

by SpokeHouse 2023. 12. 9.
728x90
728x90

안녕하세요 오토입니다.

 

이번 메모 포스팅은 STM32F103에서 ADC 값을 DMA로 읽어오는 방법에 대해 메모하고자합니다.

 

간단한 제품의 경우 POLLING 방식으로 계속 데이터를 확보하면 되는데

 

현재 진행중인 제품은 무선통신이 우선적으로 동작하여 신뢰성을 확보하여야 하기 때문에 프로세서의 부담을 줄이고자

 

DMA로 데이터를 확보하기로 하고 진행하였다.

 

먼저 IDE에서 파라미터들 세팅해준다

 

인터럽트도 일단 켜주고

다음으로 DMA REQUEST 추가 해준다

클럭도 이렇게 세팅해주고

코드를 제네레이션 해주면 일단 세팅은 마무리된다

 

지금 하고있는 작업은 전류센서의 데이터를 확보하기 위함이며, ACS712 제품이다.

 

관련 소스 파일 및 헤더파일 생성해주고

 

헤더파일.

#ifndef INC_ADCACS712CURRENT_H_
#define INC_ADCACS712CURRENT_H_

#include "main.h"
#include "adc.h"

#define ADC_BUF_SIZE 2

extern __IO uint32_t ADC_value[2];
extern uint32_t readValue;
extern float sensitivity ;
extern float rawVoltage;
extern float current;

void adcInit();
void adcrun();


#endif /* INC_ADCACS712CURRENT_H_ */

소스파일

uint32_t ADC_buf[ADC_BUF_SIZE];
uint8_t flag=0;
float aver_currnt=0;
uint32_t aver_count =0;

float sensitivity = 185; // ACS712ELCTR-05B-T의 민감도 (V/A)
float rawVoltage=0;
float current =0;
float Vdd=0;
float adc_final_value=0;

char uart_Send_buffer[20];


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    Vdd = (uint16_t)ADC_buf[0];
}

//void HAL_IncTick(void) // HAL_getTick()
//{
//    uwTick += uwTickFreq;
//    if((uwTick % 50)==0) //1000mS tick
//    {
//        flag=1; //adcrun() hal_adc_start_DMA
//    }
//}

void adcInit()
{
  HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_buf, ADC_BUF_SIZE);
  HAL_ADCEx_Calibration_Start(&hadc1);

}


void adcrun()
{

	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_buf, ADC_BUF_SIZE);

	rawVoltage =Vdd;
	current =(((((rawVoltage - 2400)/sensitivity)*-0.25)-0.63)*1.55);
	aver_count++;
	aver_currnt = aver_currnt+current;
	//		aver_currnt = (((aver_currnt - 25)*-1000)/3);


	sprintf(uart_Send_buffer, "%.2f", adc_final_value);


	if(aver_count == 20000)

		{
			adc_final_value = aver_currnt/aver_count;
			//adc_final_value = ((33.18-(aver_currnt/aver_count))/4)*1000;
	//		HAL_UART_Transmit(&huart2, (uint8_t*)uart_Send_buffer, strlen(uart_Send_buffer), HAL_MAX_DELAY);
//			printf("----count_value:%ld \r\n",aver_count);
//			printf("----ADC_Value:%.2lfA\r\n",adc_final_value);
			aver_count = 0;
			aver_currnt = 0;
			adc_final_value = 0;
		}
}

먼저

1. INIT 해주면서 DMA START 해주고 

2. CALIBRATION START 해준다

다른 실험 포스팅을 보니 CALIBRATION 유무는 지속 데이터에서 크게 작용하진 않지만 뭐 있는걸 안쓰는것보단 나을것같다

3. ADC CONVERSION이 끝나면 호출되는

HAL_ADC_ConvCpltCallback

콜백 함수에서 ADC 버퍼 데이터를 VDD에 일단 넣어주는 형식으로 진행된다

4. rawVlotage 변수에 vdd를 넣어주고 

5.current에서는 받은 rawVlotage 데이터를 계산해준다 

-해당 식은 데이터 시트 및 gpt에서 얻은 데이터를 바탕으로 하였는데 안맞아서 역산하여 수식 만들어준것이다

보드 특성상 노이즈도 심하고 부가적인 레퍼런스 전압을 잡아줄 수 있는 회로가 없어서 수식이 좀 더럽다

기존식은 이것이고 데이터시트하고 여러 문서들 참고하여 업데이트 하시면 좋을듯하다.

 

6.sprintf로 넘겨서 출력하려고 넣어놨고

7. aver_count ++ 진행하여 2만번 데이터 확보하고 나눠서 평균값 출력한다.

 

데이터는 잘 나온다. 그런데 수식을 계속 보정해야한다. 

 

참고용 데이터 확보이기 때문에 상관은 없지만 정밀하게 데이터를 확보하고자 한다면 꼭 손보고 사용하시길

 

그럼 이만 오늘도 대단히 맛있는거 많이드시고!

 

728x90
728x90

댓글