기존에 제작하던 쿼드콥터의 경우 STM32 MCU를 사용하고 HAL드라이버를 사용하여 코드를 작성하였다.

 

이번에 제작하고자 하는 헥사콥터의 경우 HAL 드라이버가 아닌 LL 드라이버를 사용하여 코드를 작성하여 헥사콥터를 제어할 것이다.

 

따라서 LL 드라이버에 관한 내용에 관해 글을쓰면서 진행할 생각이다.

 

기본 코드 편집기는 STM32CubeIDE를 사용할 것이고 기본적인 기능은 사용할 수 있다고 가정하고 글을 쓸 것이다.

 

LL드라이버의 경우 데이터시트를 많이 볼 수밖에 없다. 따라서 데이터시트 링크를 같이 첨부했다.

https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

 

 

MCU

STM32F407VGT6
STM32F407VX_M_schematics.pdf
0.28MB

드론에 사용할 MCU보드이며 회로도는 찾기 힘들 수 있으므로 추가로 첨부했다.

 

 

LL드라이버 생성 (0)

 clock 설정

기본 클럭 설정은 쿼드콥터에서 사용한 클럭 설정을 그대로 사용할 것이다.

 

최대 SYSCLK는 168Mhz지만 84Mhz여도 문제가 없기 때문에 기존에 사용하던 84Mhz를 사용한다.

 

 

LL드라이버 세팅

처음 MCU를 만지면 GPIO를 제어하는 것이 국룰이므로 GPIO 제어코드를 작성해 볼 것이다.

 

PA0는 OUTPUT, PA2은 INPUT으로 설정 후 Project Manger -> Advanced Settings에 들어가 HAL에서 LL로 변경하면 HAL 드라이버가 아닌 LL 드라이버로 코드를 생성할 수 있다.

 

다른 UART, SPI, I2C 등 다른 Peripheral 들을 제어할 때 LL드라이버로 생성하고 싶으면 Advanced Settings에 들어가 LL드라이버로 변경하면 된다.

 

 

 

stm32f4xx_ll_gpio.h

코드를 생성하고 생성된 코드에 관한 내용을 보려면 referance manual을 참고하여 코드를 작성해도 되지만 생성된 파일에서 원하는 함수들을 찾아 사용해도 된다.

 

HAL드라이버와 다르게 LL드라이버의 경우 헤더 파일에 inline 함수로 정의되어있다.

Drivers -> STM32F4xx_HAL_Driver -> Inc에 들어가면 헤더 파일 들을 볼 수 있다.

 

 

코드 - (1)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_0);
      LL_mDelay(200);
      LL_GPIO_ResetOutputPin(GPIOA,LL_GPIO_PIN_0);
      LL_mDelay(200);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
1
2
3
4
5
6
7
8
9
__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
  WRITE_REG(GPIOx->BSRR, PinMask);
}
 
__STATIC_INLINE void LL_GPIO_ResetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
  WRITE_REG(GPIOx->BSRR, (PinMask << 16));
}
 

LL_GPIO_SetOutputPin과 LL_GPIO_ResetOutputPin은 헤더 파일에 inline함수로 정의되어 있고 레지스터에 직접 제어하는 방식으로 구성되어 있다.

 

GPIO 레지스터 BSRR의 경우 ODR 레지스터를 SET 하고 RESET 시킬 수 있고, LL_GPIO_WriteOutputPort 으로 직접 ODR 레지스터에 값을 쓸 수 있다.

 

HAL_Delay() 함수와 다르게 LL드라이버는 LL_mDelay() 함수를 사용한다.

 

빌드를 하고 MCU에 코드를 올리면 LED가 꺼지고 켜지는 것을 반복한다.

 

 

코드 - (2)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      if(LL_GPIO_IsInputPinSet(GPIOA,LL_GPIO_PIN_2))
          LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_0);
      else
            LL_GPIO_ResetOutputPin(GPIOA,LL_GPIO_PIN_0);
 
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
1
2
3
4
__STATIC_INLINE uint32_t LL_GPIO_IsInputPinSet(GPIO_TypeDef *GPIOx, uint32_t PinMask)
{
  return (READ_BIT(GPIOx->IDR, PinMask) == (PinMask));
}
 

LL_GPIO_IsInputPinSet으로 IDR 레지스터에서 INPUT값을 읽을 수 있다.

 

스위치를 올리면 LED가 켜지고 내리면 LED가 꺼진다.

 

 

 

-

MCU의 기본이 되는 GPIO제어를 LL드라이버를 사용하여 제어했다.

 

레지스터에 대해 많이 찾아봐야 해서 HAL드라이버 보다 코드를 작성하는 시간이 길어지지만  알아볼 수 있어 나름 재미있다.

 

다음 글은 UART 통신에서 printf사용과 DMA를 사용한 코드에 대해 쓸 것이다.

 

실제 컴퓨터에서 데이터를 받아 볼 수 있는 중요한 기능이므로 I2C, SPI 통신보다 먼저 작성할 것이다.

 

 

Posted by DDTXRX
,