DMA란?
입출력 장치 제어기(IO device controller)가 CPU에 의한 프로그램의 실행없이 자료의 이동을 할 수 있도록 하는 것이 DMA이다. 이 방식에 의해서 입출력의 속도를 향상할 수 있으며, CPU와 주변 장치간의 속도차를 줄일 수 있다. 입출력 장치가 DMA를 요구하면 CPU가주메모리의 제어를 넘겨주게 되는데 CPU는 이 작업을 CPU 사이클이 끝나는 지점마다 허용할 수 있다.
출처: 네이버 백과
CUBE MX 설정



scan conversion mode를 enable할 경우, 먼저 number of conversion의 수를 2 이상으로 설정해야 한다.



<truestudio>
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
#include<stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
#define APP_RX_DATA_SIZE 64
#define APP_TX_DATA_SIZE 64
extern uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
extern uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
uint8_t bufftx[100] ;
extern int i;
__IO uint32_t ADCvalue[2];
volatile uint32_t data=0;
__IO float db[2];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
int _write(int file, unsigned char* p, int len)//printf를 위한 함수
{
HAL_UART_Transmit(&huart1, p, len, 10);
return len;
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//adc interrupt callback function
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
/* USER CODE END WHILE */
db[0]= ADCvalue[0]*(3.3)/4095;
db[1]= ADCvalue[1]*(3.3)/4095;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
MX_USB_DEVICE_Init();
MX_DMA_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_OC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_ADCEx_Calibration_Start(&hadc1);
setvbuf(stdout, NULL, _IONBF, 0);// 즉시 pintf 가 송신될수 있도록 stdout buffer size를 0으로 만들어준다.
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADCvalue,2);//ADCvalue is the temporary buffer to store the data
//data = ADCvalue[0];
/*
sprintf(bufftx,"%d",data);
strcat(bufftx,"\n");
HAL_UART_Transmit(&huart1, bufftx, sizeof(bufftx), 100) ; // send data using uart1
CDC_Transmit_FS((uint8_t*)bufftx, strlen((const char*)bufftx));//send data using virtual uart
memset(bufftx, 0, sizeof(bufftx));//clear the buffer
*/
//HAL_Delay(10);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#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 CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
ISR내부에서 USART를 통해 ADC값을 출력하거나 while안에서 출력하면 됨.
db배열에 저장된 값은 ADC값에 연산하여 얻어낸 전압값으로, 0~3.3V의 전압을 검출할 수 있다.
12비트 ADC이므로, 값은 4095 까지 나올 수 있다.
'Programming > Embedded' 카테고리의 다른 글
[STM32F103C8] USART통신 X CDC통신 : 문자열 전송 (0) | 2022.02.20 |
---|---|
turestudio에서 디버깅창 없이 바로 업로드 하는 기능 설정 & cubemx 파일 복사하는 방법 (0) | 2022.02.20 |
[공유] [HID]STM32F103C8 보드와 STLink만으로 printf 사용하기 #2. TrueSTUDIO (0) | 2022.02.20 |
[STM32F103] CDC통신을 통한 정수형데이터 전송 TIP (0) | 2022.02.19 |
[stm32f103f8][공유] STM32F사용중 ST-Link V2 타겟보드 인식 불가현상 해결법 (0) | 2022.02.19 |