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핀 출력을 사용하는 버전을 올리겠다.
'임베디드 개발 > STM32 (ARM Cortex-M)' 카테고리의 다른 글
STM32 ] SPI 통신 사용하기 (0) | 2022.07.24 |
---|---|
STM32 ] TIMER OC (Output Compare 단자 출력) 사용 예제 (2) | 2022.07.21 |
STM32 ] 어플과 STM32간 블루투스 통신을 통한 데이터 송수신 - 프로젝트 준비과정 (5) (2) | 2022.07.19 |
STM32 ] BLDC 모터 제어 - 프로젝트 준비과정 (4) (5) | 2022.07.19 |
STM32 ] 초음파 센서로 거리재기 Timer Input Capture 사용 + 노이즈 (튀는 값) 제거 (5) | 2022.07.18 |