HAL드라이버 내에 일정시간동안 지연시켜주는 HAL_Delay 함수가 있습니다.

/**
  * @brief This function provides minimum delay (in milliseconds) based
  *        on variable incremented.
  * @note In the default implementation , SysTick timer is the source of time base.
  *       It is used to generate interrupts at regular time intervals where uwTick
  *       is incremented.
  * @note This function is declared as __weak to be overwritten in case of other
  *       implementations in user file.
  * @param Delay specifies the delay time length, in milliseconds.
  * @retval None
  */
__weak void HAL_Delay(uint32_t Delay)

지연 시간은 (Delay + 1)ms입니다.

 

즉 HAL_Delay(0);을 호출하면 1ms의 딜레이가 발생됩니다. 

 

함수 내부를 보면

__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

 함수가 호출된 시점부터 wait동안 while에 묶여있도록 코드가 작성되어있습니다.

 

default로 HAL 드라이버는 1ms마다 1Tick씩 증가하도록 코딩되어 있습니다.

 

또 mininum wait로 1ms(uwTickFreq)가 추가되도록 되어있어 Delay에 0을 넣으면 1ms의 딜레이가 발생되는 것 입니다.

 

HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1KHz */

typedef enum
{
  HAL_TICK_FREQ_10HZ         = 100U,
  HAL_TICK_FREQ_100HZ        = 10U,
  HAL_TICK_FREQ_1KHZ         = 1U,
  HAL_TICK_FREQ_DEFAULT      = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;

 

1넣었을 때 1ms 딜레이가 걸리게 하고 싶다!

1000 넣었을 때 1초 딜레이가 걸리게 하고 싶다!

 

하시는 분은 HAL_Delay 함수를 아래처럼 따로 작성하시면 됩니다.

 

/* main.c */
void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  while ((HAL_GetTick() - tickstart) < Delay)
  {
  }
}
​

 

하지만 HAL_Delay 함수를 사용하게 되면

그 위치에서 멈춰있기 때문에 저는 잘 사용하지 않습니다.

반응형

안녕하세요.

 

20.05.18일 기준 TrueStudio는 9.3.0 까지 Release되었습니다.

 

결론부터 말씀드리자면 새로 개발하는 사람들은 STM32CubeIDE로 넘어가시길 추천드립니다.

 

STM32CubeIDE는 TrueStudio와 STM32CubeMX를 결합한 개발툴로 Eclipse기반입니다.

 

ST사의 TrueStudio 홈페이지로 가면 TrueStudio가 아닌 STM32CubeIDE를 추천하고 있습니다.

 

For new designs we recommend using STM32CubeIDE instead of Atollic TrueSTUDIO. There will be no new releases of TrueSTUDIO.

 

더 이상 TrueStudio의 새 버전을 내지 않는다고 선언했습니다.

 

만약 기존 프로젝트가 TrueStudio로 되어있다면 그대로 개발을 계속 하고,

새 프로젝트를 진행하게 될 때 CubeIDE로 넘어가시면 될 것 같습니다.

 

 

 

 

 

CubeIDE, TrueStudio, CubeMX 아이콘

 

 

 

STM32CubeIDE 화면, TrueStudio와 동일하다.

 

 

STM32CubeIDE에서 .ioc 파일을 실행한 화면, IDE내에 CubeMX가 도킹이 된 상태로 실행이된다.

 

반응형

npm 설치

$> sudo apt-get install npm

 

global 옵션으로 n 설치

$> sudo npm install -g n

 

n으로 nodeJS 최신버전 설치

$> sudo n lts

 

원하는 버전으로 설치하기 위해서는

$> sudo n 8.12.0

 

설치했는데 node 명령어가 안먹힌다면

$> sudo ln -sf /usr/local/n/versions/node/(버전)/bin/node /usr/bin/node

 

반응형

'NodeJS' 카테고리의 다른 글

[Node.JS][Express.JS][ejs] alert 페이지  (0) 2021.12.09

pageHeight = document.body.scrollHeight

pageWidth = document.body.scrollWidth;

windowWidth = window.innerWidth

windowHeight = window.innerHeight

screenWidth =  screen.width;

screenHeight = screen.height;

 

 

출처: https://stackoverflow.com/questions/3437786/get-the-size-of-the-screen-current-web-page-and-browser-window

반응형

이동 평균 필터는 단순하게 동일한 Mask 영역에 데이터를 평균내어 노이즈 성분을 줄이는 간단한 필터입니다.

 

moving averge filter 수식

 

Mask의 크기가 6이라고 하면 연속하는 6개의 데이터를 평균내는 것을 말합니다.

 

이동 평균 필터

 

위 그림처럼 Raw Array에 데이터를 쌓고 Mask를 이동시켜 Raw Array의 값을 평균내서 새로운 배열에 값을 넣습니다.

 

아래 이동 평균 필터를 예시로 작성해 보았습니다.

 

#define MASK_LENGTH 	(3)

uint16_t raw_array[MASK_LENGTH] = {0,};
uint16_t raw_array_index = 0;

/* Mask 크기만큼 데이터를 평균낸다. */
float movingAverageFilter()
{
    int i = 0;
    uint16_t sum = 0;

    for (i = 0; i < MASK_LENGTH; i++) {
    	sum += raw_array[i];
    }
    return ((float)sum / MASK_LENGTH);
}

/* 새로운 데이터를 array에 넣는다. */
void insertIntoRawArray(uint16_t value)
{
    raw_array[raw_array_index] = value;

    raw_array_index++;

    if (raw_array_index >= MASK_LENGTH) {
    	raw_array_index = 0;
    }
}

int main()
{
	insertIntoRawArray(4034);
	insertIntoRawArray(4036);
	insertIntoRawArray(4031);
	insertIntoRawArray(4035);
	insertIntoRawArray(4034);
	insertIntoRawArray(4032);
	printf("%f\r\n", movingAverageFilter());

	insertIntoRawArray(4033);
	printf("%f\r\n", movingAverageFilter());

	insertIntoRawArray(4032);
	printf("%f\r\n", movingAverageFilter());

	insertIntoRawArray(4036);
	printf("%f\r\n", movingAverageFilter());

	insertIntoRawArray(4034);
	printf("%f\r\n", movingAverageFilter());
}

결과

 

Mask길이에 따른 필터링 결과 비교

 

* Mask 길이: 3

Mask길이 3일 때 Raw데이터와 필터 결과 비교

 

* Mask 길이: 10

Mask길이 10일 때 Raw데이터와 필터 결과 비교

 

* Mask 길이: 30

Mask길이 30일 때 Raw데이터와 필터 결과 비교

 

* Mask 길이: 100

Mask길이 100일 때 Raw데이터와 필터 결과 비교

 

 

Mask 길이가 길면 길 수록 평균내는 값이 많아져 노이즈가 줄어드는 효과를 주지만,

그만큼 연산량이 증가하고, Mask길이만큼 데이터를 가지고 있어야하기 때문에 메모리를 많이 차지한다라는 단점이 있습니다.

반응형

사용 MCU: STM32F103VCT

사용 IDE: TrueSTUDIO 9.3.0

 

STM32F HAL드라이브에서 HAL_ADCEx_Calibration_Start라는 함수가 있습니다.

/**
  * @brief  Perform an ADC automatic self-calibration
  *         Calibration prerequisite: ADC must be disabled (execute this
  *         function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
  *         During calibration process, ADC is enabled. ADC is let enabled at
  *         the completion of this function.
  * @param  hadc: ADC handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc);

 

이 함수를 꼭 써야하는가 ? 의문이 들어서 Calibration을 하고 안 하고의 차이점을 확인하기 위해 직접 실험 해 보았습니다.

 

STM32F103VCT6가 달려있는 보드를 사용했고 ADC한 회로는 아래와 같이 가변저항으로 실험 했고 확인하기 좋게

한쪽으로 끝까지 돌려 PC5_SBT에 3.3V가 들어가도록 하였습니다. 

 

이론적으로 ADC결과는 4095(12bit ADC)가 나와야합니다.

가변저항 회로도

 

실험한 코드는 아래와 같습니다.

 

/* 100ms마다 ADC결과 전송 */
void adc_task()
{
    static uint32_t time = 0;
    uint16_t value;
    
    if (HAL_GetTick() - time < 100) {
    	return;
    }
    
    time = HAL_GetTick();
    
    /* ADC 시작 */
    HAL_ADC_Start(&hadc1);
    
    /* ADC가 완료될 때까지 대기 */
    while(HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK);
    
    /* ADC 값 가져오기 */
    value = HAL_ADC_GetValue(&hadc1);
    
    /* ADC 중지 */
    HAL_ADC_Stop(&hadc1);

    printf("%d\r\n", value);
}


int main(void)
{
  ...
  
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  
  ...
  
  /* ADC Calibration ? 실험 포인트 */
  while(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK);
  
  while(1)
  {
  	adc_task();
  
  }
}

 

결과 확인

결과는 제가 확인하기 편하게 Electron으로 GUI툴을 작성하여 Serial값을 수신하여 값과 차트로 표현하도록 하였습니다.

 

1. while(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK); 를 주석처리 하고 ADC 결과 값 확인

Calibration 없이 3.3V ADC 결과

이론적이라면 ADC값이 최대값인 4095가 나와야하는데 4030~40대가 나오네요.

 

 

2. while(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK); 호출한 후 ADC 결과 값 확인

Calibration 후 3.3V ADC 결과

 

중간에 하나씩 튀는 값이 있지만 이론값대로 4095가 나오는 것을 볼 수 있습니다.

 

 

아래는 위 두 실험을 한 차트에 표현했을 때 차트입니다. 차이가 있는것을 볼 수 있습니다.

(Calibration 후 ADC가 flat하니 보기 좋은데 최대 전압이라 그렇지 전압을 조금 내리면 노이즈 정도는 비슷합니다.)

 

반응형

HAL Driver 중에 GPIO에 대해서 소개하겠습니다.

 

 

stm32f1xx_hal_gpio.c

 

 

  • void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)

      CubeMX로 생성한 코드는 아래와 같이 GPIOx 페리페럴을 초기화한다.

 

      GPIO Mode

          GPIO_MODE_INPUT: 입력모드

          GPIO_MODE_OUTPUT_PP: 출력 (Push Pull) 모드

          GPIO_MODE_OUTPUT_OD: 출력 (Open Drain) 모드

          GPIO_MODE_AF_PP: 대체 기능(Alternate Function), (Push Pull)모드

          GPIO_MODE_AF_OD: 대체 기능(Alternate Function), (Open Drain)모드

 

          GPIO_MODE_ANALOG: 아날로그 모드

 

          GPIO_MODE_IT_RISING: 외부 인터럽트(External Interrupt)모드, Rising Edge

          GPIO_MODE_IT_FALLING: 외부 인터럽트(External Interrupt)모드, Falling Edge

          GPIO_MODE_IT_RISING_FALLING: 외부 인터럽트(External Interrupt)모드, Rising & Falling Edge

          

          GPIO_MODE_EVT_RISING: 외부 이벤트(External Event)모드, Rising Edge

          GPIO_MODE_EVT_FALLING: 외부 이벤트(External Event)모드, Falling Edge

          GPIO_MODE_EVT_RISING_FALLING: 외부 이벤트(External Event)모드, Rising & Falling Edge

            * Event모드는 인터럽트 발생시키지 않고 저전력모드에서 Wake-up하는데 사용된다.

          

      GPIO Pull

          GPIO_NOPULL

          GPIO_PULLUP

          GPIO_PULLDOWN

 

      GPIO Speed

          GPIO_SPEED_FREQ_LOW

          GPIO_SPEED_FREQ_MEDIUM

          GPIO_SPEED_FREQ_HIGH

/* GPIO 초기화 */
void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIOD APB2 Clock ENABLE */
    __HAL_RCC_GPIOD_CLK_ENABLE();
    
    /* Configure GPIO pins : PD13 PDPin */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    /* 외부 인터럽트(EXTI) 설정 */
    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}

 

  • void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)

      GPIO 설정을 초기화 한다

 

  • void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

      GPIOx의 Pin의 상태를 설정한다.

      GPIO_PinState에는 GPIO_PIN_RESET(0) 과 GPIO_PIN_SET(1) 이 있다.     

/* HAL_GPIO_WritePin 예시 */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET); // GPIO OUTPUT LOW
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);   // GPIO OUTPUT HIGH

HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, 0); // GPIO OUTPUT LOW
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, 1); // GPIO OUTPUT HIGH

 

  • GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

      GPIOx의 GPIO_Pin의 상태를 가져온다. 이때 GPIO Pin의 mode는 GPIO_MODE_INPUT 이어야 한다.

GPIO_PinState state;

state = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_5); // GPIOE5 의 상태를 읽는다

 

  • void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

      GPIO의 상태를 반전(Toggle)시킨다.

HAL_GPIO_TogglePin(GPIOE, GPIO_Pin_5); // GPIOE5 핀의 출력 상태를 반전시킨다.

 

  • HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

      GPIO Pin의 설정을 고정시킨다.

반응형

C

  • C/C++

C#

  • C#

Javascript

  • ESLint

Python

  • Python

Git

  • Git Graph
  • Git History
  • GitLens

Project

  • Project Manager

기타

  • Korean Language Pack for Visual Studio Code
  • TODO Highlight
  • Todo Tree
  • vscode-icons
  • Color Highlight
  • Prettier

 

반응형

'기타' 카테고리의 다른 글

[Hyper-V] 우분투 해상도 변경  (1) 2020.04.20

+ Recent posts