STM32F411 에서 타이머2 인터럽트를 사용하다가,
동작이 생각처럼 안되어서 쌩쑈를 하다가 나중에 동작이 되긴 했지만 아직까지 이해가 안되는 부분이 있었습니다.
인터럽트를 처리하는 콜백 함수와 함수 내에서 사용하는 전역 변수들은 다음과 같고, main.c 파일 안에 있습니다.
이 콜백함수는 1ms 마다 호출되도록 설정했고,
콜백 함수 내에 f_tim2_cpl 가 SET 되는 부분에 LED 와 연결된 포트를 토글하면 잘 동작 됐습니다.
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 | uint8_t f_tim2_cpl=0; uint16_t cnt_tim2[5] = {0,0,0,0,0}; uint16_t ref_tim2[5] = {50,2000,40,0,0}; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { uint8_t cnt_tmr; if (htim->Instance == TIM2) { for(cnt_tmr=0;cnt_tmr<5;cnt_tmr++) { if (cnt_tim2[cnt_tmr] < ref_tim2[cnt_tmr]) { cnt_tim2[cnt_tmr]++; } if (cnt_tim2[cnt_tmr] == ref_tim2[cnt_tmr]) { cnt_tim2[cnt_tmr] = 0; switch (cnt_tmr) { case 0: f_tim2_cpl |= F_TIMCMPL_0; break; case 1: f_tim2_cpl |= F_TIMCMPL_1; break; case 2: f_tim2_cpl |= F_TIMCMPL_2; break; case 3: f_tim2_cpl |= F_TIMCMPL_3; break; case 4: f_tim2_cpl |= F_TIMCMPL_4; break; } } } } else if (htim->Instance == TIM1) { } } | cs |
그런데, main 함수 내에서 다음과 같이 f_tim2_cpl 의 상태를 while 문의 조건문 안에서 읽어서 비교하면 동작이 안되고,
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 | int main(void) { uint16_t i; /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ for(i=0;i<5;i++) cnt_tim2[i] = 0; f_tim2_cpl=0; HAL_TIM_Base_Start_IT(&htim2); printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { } printf("2 sec delay\n\r"); while(1); } | cs |
while() 문 안에, 여러가지 내용을 넣어 봤는데 동작이 되는 경우도 있고 안되는 경우도 있고,
안에 넣은 코드에 따라서 각각 다릅니다.
1. HAL_delay(1); 을 넣은 경우. (정상 동작)
1 2 3 4 5 6 7 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { HAL_Delay(1); } printf("2 sec delay\n\r"); | cs |
2. __wfi(); //wait for interrupt 을 넣은 경우. (정상 동작)
1 2 3 4 5 6 7 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { __wfi(); } printf("2 sec delay\n\r"); | cs |
3. __nop(); // no opration 을 넣은 경우. (동작 안함)
1 2 3 4 5 6 7 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { __nop(); } printf("2 sec delay\n\r"); | cs |
4. printf() 문 을 넣은 경우, (정상 동작)
1 2 3 4 5 6 7 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { printf("timer 2 Whay?\n\r"); } printf("2 sec delay\n\r"); | cs |
5. i++; (변수 1씩 증가). (동작 안함).
1 2 3 4 5 6 7 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { i++; } printf("2 sec delay\n\r"); | cs |
6. for() 루프로 딜레이. (동작 안함)
1 2 3 4 5 6 7 8 9 10 | printf("uart test\n\r"); while((f_tim2_cpl&F_TIMCMPL_1) == 0) // 2sec { for(i=0;i<1000;i++) { __nop(); } } printf("2 sec delay\n\r"); | cs |
지금까지의 테스트로 봤을 때,
인터럽트에 의한 전역 변수의 상태를 읽으려면
- 단순한 for 루프나 폴링 방식의 딜레이로는 안되고,
- __wfi(), HAL_delay(), printf() 의 함수가 사용되어야 읽을 수 있다고 볼 수 있겠습니다.
흠, 지금까지 이런 것을 염두에 두고 인터럽트를 쓰지 않았는데.. 거의 무리없이 지나왔었습니다.
그런데 이제와서 이런 경우를 겪어서 좀 황당하네요.
ㅜㅜ 뭔가 기초가 부족한 것 같습니다. 혹시 누가 정확한 원인을 아시는 분 설명 좀 부탁 드려요.
최종적으로 다음과 같이 사용하니, 별 문제가 없네요. (__wfi() 사용)
1 2 3 4 5 6 7 8 9 10 | while(1) { __wfi(); if (f_tim2_cpl & F_TIMCMPL_2) // 400ms T compare { cnt_tim2[2] = 0; // 400ms counter f_tim2_cpl &= ~F_TIMCMPL_2; // 400ms Flag clear HAL_GPIO_TogglePin(IND_LED_FL_GPIO_Port,IND_LED_FL_Pin); // LED toggle } } | cs |
'STM32F4' 카테고리의 다른 글
[STM32F4xx] Polling us Delay 함수 (0) | 2018.09.05 |
---|---|
[STM32F4xx] DWT us Delay 함수 (0) | 2018.09.05 |
[STM32F4xx] CUBEMX ver 4.19 버전 갖고 계신분? (0) | 2018.09.05 |
[STM32F4xx] CUBEMX ver 4.2 버그 많아서 못쓰겄네. (0) | 2018.09.05 |
[STM32F4xx] CUBEMX ver 4.2 버그 (HSE RCC Initialize Fail) (0) | 2018.09.05 |