1. STM32CubeMX 설치하기

  • 공식 사이트에서 설치하기
  • window 11 사용 중이라 STM32CubeMX-Win을 설치하였다.

Untitled

2. STM32CubeMX는 무엇인가?

  • CubeMX: 하나의 자동화된 코드를 생성해주는 도구(tool)
  • Cube Library(Software Packages): 해당 펌웨어의 기반이 되는 각 라이브러리를 말한다.

3. 프로젝트 생성하기

Untitled

  • File → New Project 클릭

Untitled

  • 사용하고자 하는 MCU 선택
  • MCU 더블 클릭 또는 Start Project 클릭

Untitled

4. 프로젝트 저장하기

Untitled

  • File → Save Project 클릭

Untitled

  • STM32CubeIDE에서 생성한 프로젝트의 lib 경로에 들어가 생성하고자 하는 라이브러리의 폴더명을 적는다.
  • 본 포스팅에선 C:\SonDongwoo\STM32\study_code\stm32f401_fw\src\lib\cube_f401 라고 기입하였다. 마지막에 cube_f401 을 적으면 자동으로 폴더가 생성된다.

5. Pinout & Configuration 설정하기

5.1. Debug 설정

Untitled

  • System Core → SYS → Debug를 Serial Wire로 설정한다. 디버깅을 위해 필요한 설정이다.
  • Debug를 변경하면 칩의 오른쪽 상단 2개의 핀(PA13, PA14)이 활성화(초록색으로 변함)된 것을 확인할 수 있다.

5.2. Clock 설정

Untitled

  • System Core → RCC → High Speed Clock(HSE)를 Crystal/Ceramic Resonator로 변경한다.
  • 칩의 좌측에 2개의 핀(PH0, PH1)이 활성화(초록색)된 것을 확인할 수 있다.

6. Clock Configuration 설정하기

Untitled

  • Clock Configuration은 GUI를 활용하여 Clock을 변경할 수 있는 메뉴이다.

Untitled

  • HSE를 사용하기로 하였기에 PLL Source Mux에서 HSE를 선택한다.

Untitled

  • System Clock Mux에서도 HSE로 설정을 변경한다.

Untitled

  • HCLK (MHz)를 최대 주파수로 변경한다. 박스 아래에 파란색 작은 글씨로 쓰여있다.
  • HCLK (MHz)를 입력하고 Enter를 누르면 나머지 Clock도 자동으로 변경된다.

7. Project Manager 설정하기

7.1 Toolchain / IDE 변경

Untitled

  • 중간에 Toolchain / IDE 라는 부분이 존재한다.
  • STM32CubeIDE를 사용하기 때문에 변경해준다.

7.2. Peripheral 설정 변경

Untitled

  • 왼쪽에 보면 ‘Project’, ‘Code Generator’, ‘Advanced Settings’이라는 메뉴가 보일 것이다.
  • 두 번째의 ‘Code Generator’를 선택하고, ‘Generated files’ 영역 안에 가장 첫 번째 것을 선택하여 활성화한다. (Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral)
  • peripheral 마다 별도의 파일을 생성해준다. 활성화하지 않으면 peripheral과 관련된 모든 코드가 main.c 파일에 생성되어 참조하기 불편하다.

Untitled

  • 이후 오른쪽 상단의 GENERATE CODE 버튼을 클릭하면 프로젝트가 생성된다.

Untitled

  • 다운로드가 필요하다고 하여 Yes를 클릭하였다.

Untitled

  • 다운로드를 위해 로그인이 필요한 것 같다.

Untitled

  • 로그인 오류가 발생하여 중앙 상단에 위치한 myST에서 로그인을 진행하였다.

Untitled

  • 로그인을 하니 다운로드가 잘 수행되었다.

Untitled

  • CubeMX에서 생성한 프로젝트를 직접적으로 사용하진 않기에 Close를 눌러준다.

8. STM32CubeIDE에서 CubeMX 활용하기

Untitled

  • 이제 다시 STM32CubeIDE로 돌아온다. lib 폴더 내부에 CubeMX 프로젝트를 생성하였는데 보이지 않는다.

Untitled

  • 프로젝트를 우클릭한 후 Refresh를 클릭한다.

Untitled

  • CubeMX 프로젝트는 위와 같은 구성을 가진다.

8.1. Core 폴더 빌드에서 제외

Untitled

  • Core 폴더의 코드는 직접적을 사용하지 않는다. 그래서 빌드에서 제외 시켜줘야 에러가 발생하지 않는다.
  • Core 폴더를 우클릭하고, Resource Configuration → Exclude from Build를 클릭한다.

Untitled

  • 모든 곳에서 제외하기 위해 Select All을 누르고 OK 버튼을 클릭한다.

Untitled

  • Core 폴더 전체가 제외된 것을 확인할 수 있다.

8.2. Drivers Include 폴더 경로 추가

Untitled

Untitled

  • 프로젝트를 우클릭한 후 Properties를 클릭한다.

Untitled

  • C/C++ Build → Settings → Tool Settings → MCU GCC Compiler → Include paths 클릭
  • path 추가 버튼 클릭

Untitled

  • ${workspace_loc:/${ProjName}/src/lib/cube_f401/Drivers/CMSIS/Device/ST/STM32F4xx/Include} 추가

Untitled

  • ${workspace_loc:/${ProjName}/src/lib/cube_f401/Drivers/CMSIS/Include} 추가

Untitled

  • ${workspace_loc:/${ProjName}/src/lib/cube_f401/Drivers/STM32F4xx_HAL_Driver/Inc} 추가

Untitled

  • 총 3개의 경로를 추가한다.
  • Apply and Close 버튼 클릭

8.3. HAL Driver MCU 정의

Untitled

  • HAL_Driver는 여러 MCU를 지원한다. 그래서 어떤 MCU를 사용하는지 정의해야 한다.
  • ${workspace_loc:/${ProjName}/src/lib/cube_f401/Drivers/CMSIS/Device/ST/STM32F4xx/Include//stm32f4xx.h} 파일 안에 정의하는 부분이 있다.
  • 사용하는 MCU(STM32F401RE)가 있는 주석의 정의 부분(STM32F401xE)을 복사한다.

Untitled

  • 프로젝트 우클릭 후 Properties 선택
  • C/C++ Build → Settings → Tool Settings → MCU GCC Compiler → Preprocessor 클릭
  • 복사한 주석의 정의 부분(STM32F401xE)을 추가한다.

Untitled

Untitled

  • lib/cube_f401/Core/Src 폴더 안에 있는 3개의 파일(stm32f4xx_hal_msp.c, stm32f4xx_if.c, system_stm32f4xx.c)을 bsp 폴더 안에 복사한다.

Untitled

  • lib/cube_f401/Core/Inc 폴더 안에 있는 2개의 파일(stm32f4xx_hal_conf.h, stm32f4xx_it.h)을 bsp 폴더 안에 복사한다.
  • stm32f4xx_hal_conf.h 에는 주변 장치에 대한 정보가 담겨있다. 새로운 주변 장치를 추가하면 CubeMX 프로젝트가 변경되는데 이때 다시 복사를 진행해야 한다. CubeMX 프로젝트를 직접적으로 사용하지 않기 때문이다.

Untitled

Untitled

  • lib/cube_f401/Core/Src/main.c 에서 2개의 함수(HAL_Init(), SystemClock_Config())를 복사한 후 bsp.c 파일에 붙여 넣는다.

Untitled

  • void SystemClock_Config(void)void Error_Handler(void) 함수 복사 후 bsp.c 파일에 붙여 넣는다.
  • SystemClock_Config, Error_Handler

      void SystemClock_Config(void)
      {
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
        
        /** Configure the main internal regulator output voltage
        */
        __HAL_RCC_PWR_CLK_ENABLE();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
        
        /** Initializes the RCC Oscillators according to the specified parameters
        * in the RCC_OscInitTypeDef structure.
        */
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
        RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
        RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
        RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
        RCC_OscInitStruct.PLL.PLLM = 8;
        RCC_OscInitStruct.PLL.PLLN = 84;
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
        RCC_OscInitStruct.PLL.PLLQ = 4;
        if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
        {
          Error_Handler();
        }
        
        /** Initializes the CPU, AHB and APB buses 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();
        }
      }
        
      /* 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 */
        __disable_irq();
        while (1)
        {
        }
        /* USER CODE END Error_Handler_Debug */
      }
    

Untitled

  • 우선 복사한 부분을 bsp.c 안에 넣고 상단에 SystemClock_Config 함수의 정의를 추가한다.

Untitled

  • Error_Handler는 다른 곳에서도 호출하는 경우가 있기 때문에 bsp.h 에 정의한다.

Untitled

Untitled

  • ST-LINK를 사용하기 때문에 GPIO를 설정해야 한다. GPIO 설정 코드는 gpio.c에 있다. 사진과 같이 2개의 함수(__HAL_RCC_GPIOH_CLK_ENABLE(), __HAL_RCC_GPIOA_CLK_ENABLE())를 복사하고 bsp.c 파일 안 bspInit 함수 내부에 추가한다.

Untitled

  • 이후 빌드를 하니 파일이 없다는 에러가 발생한다.

Untitled

Untitled

  • HAL_Driver를 사용하기 위해 가장 최상위 헤더 파일을 가져와야 한다.
  • lib/cube_f401/Core/Inc/main.h 에 있는 #include "stm32f4xx_hal.h"bsp.h에 복사한다.
  • 이후 다시 빌드하면 정상적인 것을 확인할 수 있다.

Untitled

  • bsp.c 파일의 delay, millis 함수의 정의 부분을 추가한다.
  • 이후 빌드한다.

9. 참고 문헌