MCU
|
STM32F103(ST)
|
IDE
|
Atollic(TrueSTUDIO), STM32CubeMX
|
목표
|
HAL driver를 사용하여 ADC를 여러개를 DMA interrupt mode로 주기적으로 multi conversion 한다.
|
1. STM32CubeMX : ADC-DMA 설정
- 'Pinout & Configuration' Tab으로 이동
1) Analog 선택
2) ADC1 항목 선택
- ADC Configuration 확인
ADC_Settings >
1) Scan Convsersion Mode : Enabled
여러 채널을 샘플링 하는 경우 scan 모드를 enable 하고 한개 채널만 샘플링 하는 경우 disable
2) Continous conversion mode : Enabled
3) Discontinous conversion mode : Disabled
ADC_Regular_Conversion Mode >
1) Enable Regular Conversions : Enable
2) Number of Conversion : 3
3) 각 Rank 별로 원하는 ADC 채널 선택

- DMA Settings 확인
1) DMA Request : ADC1
2) ADC1 and ADC2 global interrupts : Enabled에 체크
3)Data Width : Word(uint32_t), Half Word(uint16_t)
4)Mode : Normal(HAL_ADC_Start_DMA() 함수를 계속 호출해야 함),
Circular(HAL_ADC_Start_DMA() 함수를 최초에 한번만 호출하면 됨)

- GENERATE CODE 클릭
2. ATOLLIC : main.c 수정
- 변수 선언 ; CubeMX에서 Half Word(uint16_t)로 설정
/* USER CODE BEGIN 0 */
uint16_t adc_read[3] = {1, };
- HAL_ADC_Start_DMA 호출 ; CubeMX에서 DMA 설정을 Circular로 했기 때문에 1번만 호출해 주면됨(매번 호출할 필요 없음)
- DMA와 설정은 같으나, interrupt handler에서 주기적으로 읽어오기 위해 아래와 같은 방법을 사용합니다.
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint16_t*)&(adc_read[0]),3);
/* USER CODE END 2 */
- ATOLLIC : stm32f1xx_it.c 수정
아래와 같이 작성하였는데 동일 값이 두번씩 중복되어 들어옴
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
/* USER CODE END DMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
if(adc_flag == 1)
{
adc_read1[adc_index] = adc_read[0];
adc_read2[adc_index] = adc_read[1];
adc_read3[adc_index++] = adc_read[2];
if(adc_index > 999) {
adc_flag = 0;
}
}
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
- ATOLLIC : stm32f1xx_hal_dma.c 수정
- HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) 함수 안으로 들어가 보면 Half Transfer인지 Full Trasfer인지 flag 확인하는 부분이 있는데 Full Trasfer안에 코드 작성
/* Transfer Complete Interrupt management ***********************************/
else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET))
{
if(adc_flag == 1)
{
adc_read1[adc_index] = adc_read[0];
adc_read2[adc_index] = adc_read[1];
adc_read3[adc_index++] = adc_read[2];
if(adc_index > 999) {
adc_flag = 0;
}
}
- ADC를 DMA로 읽어오면서 굳이 interrupt안에서 짤 필요가 있나 생각할 수 있는데 필요에 의해 위와 같이 작성. 일반적인 상황에서는 DMA로 지정한 변수(adc_read)만 사용해도 충분함
'ST > STM32F103C8' 카테고리의 다른 글
STM32F103C8 - 1cycle Time (0) | 2025.08.08 |
---|---|
STM32F103C8 - I2C HAL driver 오류 (0) | 2025.08.08 |
STM32F103C8 - I2C(EEPROM) (1) | 2025.08.08 |
STM32F103C8 - RTC(Systick handler) (0) | 2025.08.08 |
STM32F103C8 - PWM (0) | 2025.08.08 |