본문으로 바로가기

STM32 타이머 제어하기(STM32F429I Discovery)

category MCU/STM32F429 2020. 4. 30. 00:44
반응형

STM32F429I Discovery를 이용해서 타이머를 제어하려고 합니다. CubeMX에서는 HAL_Delay라는 라이브러리 함수를 제공해 주는데요, 타이머를 이용하여 동일한 함수를 구현해보도록 하겠습니다. 함수를 구현하기 위해서는 HAL_Delay(1)에 해당하는 1ms를 타이머를 통해서 만들어야 합니다. 




 CubeMX 설정



TIM2를 선택 후 Clock Source에서 Internal Clock을 설정합니다.





Configuration 탭에서 TIM2를 클릭합니다.





Prescaler는 분주비로 타이머 클럭을 나눠주는데 사용됩니다. Counter Period는 주기를 정하는데 사용됩니다. Prescaler와 Counter Period는 모두 0부터 시작하기 때문에 설정한 값에 -1을 해줍니다.



계산 방법




Timer Clock이 84MHz이기 때문에 Prescaler를 84 -1로 설정을 하였고 주기는 1000 - 1로 설정을 하였습니다. 위와 같이 계산을 하게 되면 


1ms라는 값이 나오게 됩니다. 해당 타이머의 Timer Clock은 아래와 같이 Datasheet를 통해서 확인할 수 있습니다.





STM32F429ZI의 Datasheet의 Block Diagram을 보면 TIM2가 APB1에 연결이 되어있는 것을 볼 수 있습니다.






CubeMX에서 Clock Configuration 탭을 확인해보면 APB1 Timer Clocks은 84MHz로 설정이 되어있네요. 이에 맞춰서 Prescaler를 설정하면 됩니다.






NVIC Settings 탭에서 TIM2 global interrupt를 선택 후 코드를 생성합니다. 생성된 코드를 확인해보겠습니다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
 
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
 
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 84 - 1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000 - 1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

설정이 완료가 되었으니 delay 함수를 만들어보도록 하겠습니다.





 소스코드



1
2
3
4
5
6
7
8
9
10
11
volatile unsigned int gTick;
void TimerISR(void)
{
  gTick = gTick + 1;
}
 
void delay_ms(int msec)
{
  int next_tick = gTick + msec;
  
  while(next_tick > gTick);

USER CODE BEGIN 0에 코드를 추가해줍니다. delay_ms 함수에서 msec만큼 While 루프를 돌게 됩니다. 여기서 gTick의 변수를 volatile로 설정하지 않으면 제대로 동작을 하지 않게 됩니다. 아마도 코드가 최적화가 되면서 문제를 일으키는것 같습니다. volatile을 붙이면 컴파일러는 해당 변수를 최적화를 하지 않습니다.





1
2
3
4
5
6
7
8
9
10
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */
  TimerISR();
  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */
  
  /* USER CODE END TIM2_IRQn 1 */
}

타이머 IRQ Handler에 코드 위와 같이 코드를 한줄 추가합니다. TimerISR()를 1ms 마다 호출을 하여 gTick을 증가시킵니다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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_CRC_Init();
  MX_DMA2D_Init();
  MX_FMC_Init();
  MX_I2C3_Init();
  MX_LTDC_Init();
  MX_SPI5_Init();
  MX_USART1_UART_Init();
  MX_USB_HOST_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT (&htim2);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
    MX_USB_HOST_Process();
 
  /* USER CODE BEGIN 3 */
    HAL_GPIO_WritePin(GPIOG, LD3_Pin|LD4_Pin, GPIO_PIN_SET);
    delay_ms(500);
     
    HAL_GPIO_WritePin(GPIOG, LD3_Pin|LD4_Pin, GPIO_PIN_RESET);
    delay_ms(500);
  }
  /* USER CODE END 3 */
}


HAL_TIM_Base_Start_IT (&htim2)는 타이머 인터럽트를 활성화합니다. USER CODE BEGIN 3에 코드는 만들어진 delay함수를 테스트하는 코드입니다. 500ms마다 LED가 ON, OFF를 반복하게 됩니다.








2020/04/05 - [MCU/STM32F429] - GPIO 입출력 제어하기(STM32F429I Discovery)

2020/03/28 - [MCU/STM32F429] - CubeMX Setting 하기

2020/02/26 - [프로그래밍/C++] - 프로그래머스 - 완주하지 못한 선수, sort algorithm 정리

2020/01/20 - [프로그래밍] - tortoise svn lock 해제 update 매크로

2020/01/11 - [프로그래밍] - 비트맵의 구조, 24비트 비트맵의 구조는 어떻게 될까?

2020/01/05 - [프로그래밍/C] - 이중 연결 리스트(Double linked list), 이중 원형 연결 리스트 예제

2019/12/22 - [프로그래밍/C] - 프로그래머스 2016년, 날짜에 따른 요일 구하기

반응형

'MCU > STM32F429' 카테고리의 다른 글

적외선 수신기 기능 구현  (1) 2020.12.03
STM32 Semihosting(STM32F429I Discovery)  (1) 2020.05.10
GPIO 입출력 제어하기(STM32F429I Discovery)  (2) 2020.04.05
CubeMX Setting 하기  (1) 2020.03.28