ST/STM32F103C8

STM32F103C8 - LL driver + ADC + DMA

engineer4ever 2025. 8. 8. 10:47

 

MCU
STM32F103(ST)
IDE
Atollic(TrueSTUDIO), STM32CubeMX
목표
LL driver를 사용하여 ADC를 DMA mode로 conversion 한다.

 

1. STM32CubeMX

- DMA, ADC LL driver 설정

 

- ADC Configuration 확인

ADC_Settings >

1) Scan Convsersion Mode : Disabled

여러 채널을 샘플링 하는 경우 scan 모드를 enable 하고 한개 채널만 샘플링 하는 경우 disable

2) Continous conversion mode : Disabled

3) Discontinous conversion mode : Disabled

 

ADC_Regular_Conversion Mode >

1) Enable Regular Conversions : Enable

2) Number of Conversion : 1

3) 각 Rank 별로 원하는 ADC 채널 선택

 

- DMA Settings 확인

1) DMA Request : ADC1

2) Data Width : Word(uint32_t)

3) Mode : Circular

- GENERATE CODE 클릭


2. ATOLLIC

- main.c 수정

uint32_t adc_val[20] = {1, };

LL_DMA_DisableChannel(DMA1,LL_DMA_CHANNEL_1);

LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1,
					  LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA),
					  (uint32_t)&adc_val, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 4);

LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1);

LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);

LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
LL_ADC_Enable(ADC1);

HAL_GPIO_WritePin (LED_WDT_GPIO_Port, LED_WDT_Pin, GPIO_PIN_RESET);
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
	LL_ADC_REG_StartConversionSWStart(ADC1);
	printf("%d\n", adc_val[0]);
}
 
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
  /**ADC1 GPIO Configuration
  PA2   ------> ADC1_IN2
  PC5   ------> ADC1_IN15
  PB0   ------> ADC1_IN8
  PB1   ------> ADC1_IN9
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* ADC1 DMA Init */

  /* ADC1 Init */
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW);

  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);

  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_WORD);

  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_WORD);

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
  ADC_InitStruct.SequencersScanMode = LL_ADC_SEQ_SCAN_DISABLE;
  LL_ADC_Init(ADC1, &ADC_InitStruct);
  ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
  LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
  ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
  ADC_REG_InitStruct.SequencerLength = 1;
  ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
  LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
  /** Configure Regular Channel
  */
  LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_15);
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_55CYCLES_5);
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
 

 

- stm32f1xx_it.c : DMA1_Channel1_IRQHandler(void) 수정

void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
	 if( LL_DMA_IsActiveFlag_TC1(DMA1))
	 {
		  LL_DMA_ClearFlag_TC1(DMA1);
	 }
	 else if(LL_DMA_IsActiveFlag_TE1(DMA1))
	 {
	 	 LL_DMA_ClearFlag_TE1(DMA1);
	 }
  /* USER CODE END DMA1_Channel1_IRQn 0 */

  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */

  /* USER CODE END DMA1_Channel1_IRQn 1 */
}
 

 

- 실행 결과

 

'ST > STM32F103C8' 카테고리의 다른 글

STM32F103C8 - I2C LCD(SSD1306)  (0) 2025.08.08
STM32F103C8 - RAM 48KB + bonus?  (0) 2025.08.08
STM32F103C8 - 1cycle Time  (0) 2025.08.08
STM32F103C8 - I2C HAL driver 오류  (0) 2025.08.08
STM32F103C8 - ADC(DMA interrupt)  (1) 2025.08.08