본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] TIMER OC (Output Compare No Output) 사용 예제

by eteo 2022. 7. 21.

OC : 출력비교 모드는 카운터(CNT)의 값이 캡쳐/비교기에 설정된 (CCRx)값과 일치할 때 인터럽트 또는 해당 핀에 출력을 발생시키는 모드이다.

 

TIM4 의 업 카운터와 OC(출력비교) 모드를 이용하여 LED On/Off 하는 예제

 

1. 타이머의 Frequency를 1Hz로 맞춰서 업데이트 인터럽트를 발생 시 HAL_TIM_PeriodElapsedCallback 에서  LED를 On 시킴

2. OC 모드에서 CCR값과 CNT의 값이 일치할 때 출력비교 인터럽트(CCxI)가 발생하고 HAL_TIM_OC_DelayElapsedCallback 함수에서 LED를 Off 시킴

3. 스위치 1~4 의 EXTI 인터럽트 발생시 HAL_GPIO_EXTI_Callback 함수에서 CCR값을 변경시킴

 

 

 

호환보드에 대한 설명 : https://eteo.tistory.com/65

 

 

 

클락 설정

 

 

General Purpose Timer 중 TIM2,3,4,5 는 APB1에서 클락 소스를 공급받는다.

 

 

 

 

 

 

 

 

 

핀설정

 

 

 

LED를 GPIO Output으로 잡고 스위치는 EXTI 로 잡는다. 호환보드의 스위치는 풀업회로로 구성되어 있으므로 Falling edge에 트리거 되게 한다. 그리고 NVIC(Nested Vectored Interrupt Controller) 세팅에서 인터럽트도 켠다

 

 

 

 

 

 

 

타이머 설정

 

OC핀을 출력으로 쓰지 않고 CCR과 비교하는 데만 쓸 거기 때문에 채널 1을 No Output으로 설정해줬다.

PSC와 ARR은 위와 같이 설정 1Hz마다 업데이트 인터럽트가 발생되게 한다.

OC모드의 CCR 초기값은 일단 ARR과 동일한 9999로 해준다. 나중에 스위치를 눌렀을 때 변경되게 할 것이다.

 

이렇게 ARR과 CCR값이 동일하면 업데이트 인터럽트와 출력 비교 인터럽트가 동시에 일어날텐데 브레이크포인트를 찍어보니 먼저 HAL_TIM_PeriodElapsedCallback 에 들어가고 바로 그 다음에 HAL_TIM_OC_DelayElapsedCallback 에 들어가더라.

 

 

 

TIM4의 Global Interrupt 도 켠다.

 

 

 

소스코드

USER CODE 2에서 HAL_TIM_Base_Start_IT 과 HAL_TIM_OC_Start_IT 둘 다 enable 한다.

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim4);
  HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_1);
  /* USER CODE END 2 */
  
  ...
  
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM4){
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
				  	  	  	  	  |GPIO_PIN_6|GPIO_PIN_7, 1);
	}
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM4 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
				  	  	  	  	 |GPIO_PIN_6|GPIO_PIN_7, 0);
	}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==GPIO_PIN_0){
		TIM4->CCR1 = 999;
	}else if(GPIO_Pin==GPIO_PIN_1){
		TIM4->CCR1 = 2999;
	}else if(GPIO_Pin==GPIO_PIN_2){
		TIM4->CCR1 = 4999;
	}else if(GPIO_Pin==GPIO_PIN_3){
		TIM4->CCR1 = 9999;
	}
}
/* USER CODE END 4 */

 

이렇게 하면 스위치에 따라 LED의 듀티비가 10%, 30%, 50%, 100%로 변경된다.

 

 

 

결과물

 

그런데 주기를 1초로 해놨기 때문에 밝기제어가 되는게 아니라 껐다 커지는게 눈으로 보인다.

 

그래서 타이머 설정 중

  /* Initialize all configured peripherals */
  MX_TIM4_Init();
  /* USER CODE END TIM4_Init 1 */
  htim4.Init.Prescaler = 90-1;

PSC 값을 9000-1에서 90-1로 바꿨다.

 

주파수를 높이니까 CCR 값에 따라 밝기제어가 되는 것을 확인할 수 있다.

 

 

다음에는 OC핀 출력을 사용하는 버전을 올리겠다.