이전의 동기식 / 비동기식 카운터 프로그래밍으로 구현하기 글에서 이어진다.
2022.05.23 - [MCU/STM32 (ARM Cortex-M)] - STM32 , 동기식 / 비동기식 카운터 프로그래밍으로 구현하기 ( + Timer 사용 방법 )
프로젝트 파일은 위 글 똑같고 while문 내에서 지역변수를 토글시키며 HAL_Delay(500) 한 이전버전과 달리 Timer 인터럽트 기능을 사용해 카운터함수에 클락펄스를 준 버전이다.
이번에 사용한건 General Purpose Timer 인 TIM2이고,
레퍼런스 매뉴얼 67페이지 참고. TIM2는 APB1을 사용한다.
Clock Configuration 가서 확인하면 APB1 Timer Clocks 는 90MHz이다.
TIM2 - Clock Source를 Internal Clock 으로 선택 하고 아래와 같이 설정
Parameter Settings 에서
Counter mode는 Up이고
Prescaler를 8999, ARR (AutoReload Resister = Counter Period)를 1249로 설정해 주었다.
너무 느리게 깜빡이면 답답하기 적당히 넣어준 값이다.
만약 시계를 구현하기 위해 1Hz를 뽑아낸다면,
90,000,000 / (Prescaler * ARR) = 1이 되도록 8999, 9999 로 설정하면 될 것 같다.
그리고 -1 한 이유는 카운터가 0부터 세기 때문이다. 8999 대신 9000-1 이런식으로 적어두면 더 직관적이다.
참고사진.
Prescaler 역할은 버스를 통해 공급되는 클락을 1~65,536 범위 내의 원하는 값으로 분주하는 것이고,
up 카운터의 경우 Counter(CNT)의 값이 계속 증가하다가 ARR(Auto-Reload Regiter)의 값과 동일해지면 Overflow 가 나서 인터럽트가 트리거되며 CNT의 값은 다시 0으로 돌아간다.
인터럽트를 쓸거기 때문에 TIM2의 파라미터 세팅 위의 NVIC 세팅에서 interrupt를 Enabled 해준다.
Generate Code 후 소스코드 작성하러 간다.
보드 실행시 바로 시작되는 Systick timer와 달리 다른 타이머는 Start 함수를 써주어야 한다. main 함수내의 MX_TIM2_Init(); 아래 위치한 USER CODE BEGIN 2 부분에 썼다.
타이머 인터럽트를 사용하기 때문에 HAL_TIM_Base_Start_IT( ) 함수를 사용했으며 인수로 들어간 &htim2는 MX툴에서의 Generate Code에 의해 상단에 구조체로 선언된 것을 확인할 수 있다.
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
//중략..
/* Initialize all configured peripherals */
MX_TIM2_Init();
//중략..
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
전역변수로 ClockFlag를 선언하고, main 함수 바깥(USER CODE BEGIN 0)에 HAL_TIM_PeriodElapsedCallback 함수를 썼다. 이 함수의 정의는 stm32f4xx_hal_tim.c 에 있으며 복붙으로 가져와 사용하면 된다.
MX에서 파라미터 세팅 해준 값에 따르면 90MHz/((8999+1)*( 1249+1)) = 8Hz 가 TIM2 의 동작 주파수가 되고, 이때마다 인터럽트가 발생해 이 콜백 함수가 호출된다.
/* USER CODE BEGIN PV */
uint8_t ClockFlag = 0;
/* USER CODE END PV */
// 중략
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
ClockFlag ^= 0x01;
}
/* USER CODE END 0 */
호출될 때 마다 ClockFlag를 0이면 1, 1이면 0으로 토글해준다.
그리고 while문에서는 이전글에서 main함수의 지역변수로 선언한 clock 토글시키는 부분이랑 HAL_Delay(500); 을 주석처리 해주고 대신 타이머 인터럽트에 의해 토글되는 전역변수 ClockFlag 를 카운터 함수의 인수로 전달하면 끝이다. 아주 잘 동작한다.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//clock ^= 1;
ttl7490(jkff, ClockFlag); // can use ClockFlag also and delete HAL_Delay.
for(int i=0; i<4 ; i++){
if(jkff[i].Q)
GPIOD->ODR |= (0x80 >>i);
else
GPIOD->ODR &= ~(0x80 >>i);
}
//HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
'임베디드 개발 > STM32 (ARM Cortex-M)' 카테고리의 다른 글
STM32 , UART 통신 ( 수신 ) 을 이용한 PWM 서보모터 ( SG90 ) 제어 + 펄스폭 찾아내는 팁 (3) | 2022.05.26 |
---|---|
STM32 , 난수 발생 회로 프로그래밍으로 구현 ( EXTI 사용 ) (0) | 2022.05.25 |
STM32 , 디지털 금고 프로그래밍으로 구현 ( 시프트 레지스터 응용 ) (0) | 2022.05.24 |
STM32 , 동기식 / 비동기식 상향/ 하향 카운터 프로그래밍으로 구현하기 ( JK 플립플롭 , IC 7490 / 7492 ) (0) | 2022.05.23 |
STM32 , 외부 인터럽트 ( EXTI ) 사용하기 (6) | 2022.05.22 |