Chapter 09 - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki
STM32F439ZI์ TIM2 General-Purpose Timer๋ฅผ ์ด์ฉํด 1์ด ์ฃผ๊ธฐ(1 Hz) ๋ฅผ ๋ง๋ค๊ณ , 1์ด๋ง๋ค LD1(PB0)์ toggleํ๋ค.
์ด๋ฒ ์ฅ์ ํต์ฌ ํ๋ฆ:
16 MHz Timer Clock
โ
PSC = 1599
โ
10 kHz
โ
ARR = 9999
โ
1 Hz Update Event
โ
UIF = 1
โ
LED Toggle
์ฌ์ฉ register:
RCC->APB1ENR
TIM2->PSC
TIM2->ARR
TIM2->CNT
TIM2->CR1
TIM2->SR
Ch08์ SysTick์ Cortex-M core ๋ด๋ถ timer์๋ค.
TIM2๋ STM32๊ฐ ์ ๊ณตํ๋ peripheral timer๋ค.
SysTick
โ Cortex-M Core
TIM2
โ STM32 Peripheral
TIM2์ ์ฃผ์ register:
| Register | ์ญํ |
|---|---|
| PSC | ์ ๋ ฅ clock ๋ถ์ฃผ |
| ARR | Counter ์ต๋๊ฐ |
| CNT | ํ์ฌ counter value |
| CR1 | Timer control |
| SR | Status flag |
๊ฐ์ฅ ์ค์ํ ์ฐจ์ด:
SysTick
COUNTFLAG
vs
TIM2
UIF
์ด๋ค.
SysTick์ ARM Cortex-M ์ฝ์ด์ ํฌํจ๋ ๊ณตํต ํ์ด๋จธ์ด๊ณ , TIM2๋ STM32 ์ฃผ๋ณ์ฅ์น๋ค. ์ด๋ฒ ์ค์ต์์๋ TIM2์ Update Event ํ๋๊ทธ(UIF)๋ฅผ Pollingํ์ฌ LED๋ฅผ ํ ๊ธํ๋ค.
| ํญ๋ชฉ | SysTick | TIM2 |
|---|---|---|
| ์์ | Cortex-M ์ฝ์ด | STM32 Peripheral |
| Counter | 24-bit Down Counter | 32-bit Counter |
| ์ํ ํ์ | COUNTFLAG | UIF(Update Interrupt Flag) |
| ์ด๋ฒ ์ค์ต | SysTick Polling | TIM2 Update Event Polling |
TIM2๋ ์ด์ธ์๋ PWM, Input Capture, Output Compare ๋ฑ์ผ๋ก ํ์ฉํ ์ ์๋ค.
์๋ณธ ์ค์ต์ ๊ฐ์ : TIM2์ ๊ณต๊ธ๋๋ ์ค์ Timer Clock = 16 MHz.
f_update = f_TIM2 / ((PSC + 1) ร (ARR + 1))
PSC = 1599 โ 16,000,000 / 1600 = 10,000 Hz
ARR = 9999 โ 10,000 / 10000 = 1 Hz
๊ฒฐ๊ณผ: 1์ด๋ง๋ค Update Event ๋ฐ์
PSC/ARR์ 0๋ถํฐ ์ธ๊ธฐ ๋๋ฌธ์ ๋ถ์ฃผ์จ ๊ณ์ฐ์ +1์ด ๋ค์ด๊ฐ๋ค. ์ด ๊ณ์ฐ์ TIM2 Clock์ด 16 MHz๋ก ์ค์ ๋๋ค๋ ๊ฐ์ ์ ์์กดํ๋ค. MCU ์ฝ์ด ํด๋ญ์ด 16 MHz๋ผ๊ณ ํด์ ๋ชจ๋ APB Timer ์ ๋ ฅ ํด๋ญ์ด ์๋์ผ๋ก 16 MHz๊ฐ ๋๋ ๊ฒ์ ์๋๋ค.
TIM2 ๋ ์ง์คํฐ์ ์ ๊ทผํ๊ธฐ ์ RCC์ APB1 Peripheral Clock์ ํ์ฑํํ๋ค. ์๋ณธ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ๋นํธ 0์ ์ค์ ํ๋ค.
#define TIM2EN (1U << 0)
RCC->APB1ENR |= TIM2EN;์ด๊ฒ์ ํ์ด๋จธ๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํ๋ ํด๋ญ ๊ฒ์ดํธ ํ์ฑํ์ด๊ณ , ๋ณ๋๋ก CR1.CEN์ ์ค์ ํด์ผ ์นด์ดํฐ๊ฐ ๋์ํ๋ค.
TIM2->PSC๋ Timer ์
๋ ฅ Clock์ ๋๋๋ ๋ถ์ฃผ ๊ฐ์ ๋ณด์ ํ๋ค.
TIM2->PSC = 1600 - 1;16 MHz / 1600 = 10 kHz๊ฐ ๋๋ค. (์๋ณธ ์ค์ต ๊ฐ์ )
TIM2->ARR๋ ์นด์ดํฐ๊ฐ ์ฃผ๊ธฐ์ ์ผ๋ก ๋์๊ฐ ๊ธฐ์ค๊ฐ์ ์ง์ ํ๋ค.
TIM2->ARR = 10000 - 1;10 kHz์ Timer Count๋ฅผ 10,000๊ฐ ์ฌ์ฉํ๋ฏ๋ก Update Event ์ฃผ๊ธฐ๋ 1์ด๋ค.
TIM2->CNT๋ ํ์ฌ ์นด์ดํฐ ๊ฐ์ ๋ํ๋ธ๋ค. ์๋ณธ ์ค์ต์ ์ด๊ธฐ๊ฐ์ 0์ผ๋ก ์ค์ ํ๋ค.
TIM2->CNT = 0;Debugger์ Watch์์ CNT์ ์ฆ๊ฐ์ ์ฃผ๊ธฐ์ ์ธ Reload๋ฅผ ๊ด์ฐฐํ ์ ์๋ค.
CR1์ 0๋ฒ ๋นํธ์ธ CEN์ด ์นด์ดํฐ ์คํ์ ์ ์ดํ๋ค.
#define CR1_CEN (1U << 0)
TIM2->CR1 = CR1_CEN;์ค์ต์ ๋ค๋ฅธ CR1 ๋นํธ๋ค์ ๋ณ๋๋ก ๊ตฌ์ฑํ์ง ์์ ๊ธฐ๋ณธ ๋์์ ์ฌ์ฉํ๋ค.
Timer Update Event๊ฐ ๋ฐ์ํ๋ฉด TIM2->SR์ UIF ๋นํธ๊ฐ ์ค์ ๋๋ค. ์๋ณธ ์ฝ๋๋ ์ด ์ํ๋ฅผ Pollingํ๊ณ , ์ฒ๋ฆฌํ ๋ค Software์์ UIF๋ฅผ ์ง์ด๋ค.
#define SR_UIF (1U << 0)
while (!(TIM2->SR & SR_UIF)) { }
TIM2->SR &= ~SR_UIF;UIF๋ฅผ Clearํ์ง ์์ผ๋ฉด ๋ค์ ๋ฐ๋ณต์์ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ํต๊ณผํ ์ ์๋ค. ์ค์ TIM SR ๋นํธ๋ Write-0-to-Clear ์ฑ๊ฒฉ์ด๋ฏ๋ก, ์ค๋ฌด ์ฝ๋์์๋ ๋ค๋ฅธ Pending Flag๋ฅผ ์ฐ๋ฐ์ ์ผ๋ก ์ง์ฐ์ง ์๋๋ก ํด๋น MCU ๋ ํผ๋ฐ์ค ๋งค๋ด์ผ์ ๋ง์ถฐ Clear ๋ฐฉ์์ ์ ์คํ๊ฒ ์ ํด์ผ ํ๋ค.
RCC APB1 Clock Enable
โ
PSC = 1599
โ
ARR = 9999
โ
CNT = 0
โ
CR1.CEN = 1
โ
TIM2 Counting
โ
Update Event (UIF = 1)
โ
Software Polling / UIF Clear
โ
LD1 Toggle
๊ตฌํ ์์ ์ฃผ์: ์ ์์๋ ์๋ฆฌ ์ค๋ช ์ ๋ง์ถ ํ๋ฆ์ด๋ค. ์๋์ ๋ณด์กดํ ์๋ณธ
main.c์ฝ๋๋led_toggle()์ ๋จผ์ ์คํํ๊ณ UIF๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์์์ด๋ฏ๋ก, ์ต์ด Toggle์ 1์ด ๋ค๊ฐ ์๋๋ผ ์ด๊ธฐํ ์งํ ๋ฐ์ํ๋ค. ์๋ณธ ์ค์ต ์ฝ๋์ ์ค๋ช ์ ์ฐจ์ด๋ฅผ ์๋์ ์ผ๋ก ๋จ๊ฒจ ๋๋ค.
๋ณ๋ ๋ณด๊ด๋ Ch09 ์๋ณธ์์ ๋ช ์๋ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ค.
Ch09_tim/
โโโ Inc/
โ โโโ gpio.h
โ โโโ tim.h
โโโ Src/
โ โโโ gpio.c
โ โโโ tim.c
โ โโโ main.c
โโโ ๊ธฐํ ๊ณตํต Startup, Linker, CMSIS ํ์ผ
Ch04์์ ๋ค๋ฃฌ ๊ณตํต MCU Startup ๋ฐ Build ํ๊ฒฝ์ ์ด ์ฅ์์ ๋ฐ๋ณตํ์ง ์๋๋ค.
์๋ณธ ๋ณ๋ Ch09 TIM ์ค์ต ํ์ด์ง์ ์์ค ์ฝ๋๋ฅผ ๋ณด์กดํ๋ค.
#ifndef GPIO_H
#define GPIO_H
#include <stdbool.h>
/* ---- LED (PB0, LD1 ๋
น์) ---- */
void led_init(void);
void led_on(void);
void led_off(void);
/* ---- Push Button (PC13, B1) ---- */
void button_init(void);
bool get_btn_state(void);
void led_toggle(void); /* Ch08์์ ์ถ๊ฐ */
#endif /* GPIO_H */#include "stm32f4xx.h"
#include "gpio.h"
#define LED_PIN 0U /* PB0 = LD1 (๋
น์) */
#define BTN_PIN 13U /* PC13 = B1 */
void led_init(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
GPIOB->MODER &= ~(0x3UL << (LED_PIN * 2));
GPIOB->MODER |= (0x1UL << (LED_PIN * 2));
}
void led_on(void)
{
GPIOB->BSRR = (1UL << LED_PIN); /* Set */
}
void led_off(void)
{
GPIOB->BSRR = (1UL << (LED_PIN + 16)); /* Reset */
}
void button_init(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
GPIOC->MODER &= ~(0x3UL << (BTN_PIN * 2)); /* Input */
GPIOC->PUPDR &= ~(0x3UL << (BTN_PIN * 2)); /* No pull (๋ณด๋๊ฐ ์์ฒด ์ฒ๋ฆฌ) */
}
bool get_btn_state(void)
{
return (GPIOC->IDR & (1UL << BTN_PIN)) != 0U; /* active-HIGH */
}
void led_toggle(void)
{
GPIOB->ODR ^= (1UL << 0); /* PB0 = LD1 */
}#ifndef TIM_H_
#define TIM_H_
#include "stm32f4xx.h"
#define SR_UIF (1U << 0)
void tim2_1hz_init(void);
#endif /* TIM_H_ */#include "tim.h"
#define TIM2EN (1U << 0)
#define CR1_CEN (1U << 0)
void tim2_1hz_init(void)
{
RCC->APB1ENR |= TIM2EN;
TIM2->PSC = 1600 - 1; /* 16MHz -> 10kHz */
TIM2->ARR = 10000 - 1; /* 10kHz -> 1์ด */
TIM2->CNT = 0;
TIM2->CR1 = CR1_CEN;
}#include "gpio.h"
#include "tim.h"
int main(void)
{
led_init();
tim2_1hz_init();
while (1)
{
led_toggle();
while (!(TIM2->SR & SR_UIF)) { }
TIM2->SR &= ~SR_UIF;
}
}์๋ณธ ์ฝ๋ ์ดํด ์ ์ฃผ์์ฌํญ
-
์ฒซ ํ ๊ธ ์์ :
led_toggle()์ดwhile (!(TIM2->SR & SR_UIF))์์ ์์ด ์ฒซ LED ์ ํ์ ์ด๊ธฐํ ์งํ์ ๋ฐ์ํ๋ค. ๋ค์ ์ ํ๋ถํฐ Timer Event๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค. -
์ค์ Timer Clock:
PSC=1599,ARR=9999์์ 1 Hz๊ฐ ๋๋ ค๋ฉด TIM2์ ์ ๋ ฅ๋๋ Clock์ด 16 MHz์ฌ์ผ ํ๋ค. ๋ค๋ฅธ ์ค์ ์์๋ PSC/ARR ์ฌ๊ณ์ฐ์ด ํ์ํ๋ค. - UIF ์ด๊ธฐ ์ํ: Timer ์ด๊ธฐํ ๊ณผ์ ์ค Update Flag๊ฐ ์ด๋ฏธ ์ค์ ๋๋ฉด ์ฒซ ๋๊ธฐ ๋์์ด ์ฆ์ ์ข ๋ฃ๋ ์ ์๋ค. ์ฒซ ์ธํฐ๋ฒ์ ๋ณด์ฅํ๋ ค๋ฉด ์์ ์ Flag/Update Event ์ํ๋ฅผ ํ์ธํด์ผ ํ๋ค.
-
UIF Clear: ์๋ณธ์
TIM2->SR &= ~SR_UIF๋ฅผ ์ฌ์ฉํ๋ค. ๋ค๋ฅธ Flag์ ๋ณด์กด๊ณผ W0C ๋ ์ง์คํฐ ์ ์ฑ ๊น์ง ๊ฒํ ํ ๊ฐ์ ์ฝ๋๋ ๋ณ๋ ๋จ๊ณ์์ ์์ ํด์ผ ํ๋ค. -
Button ๊ด๋ จ ํจ์: GPIO ์์ค์ ๋ฒํผ ์ด๊ธฐํ/์ฝ๊ธฐ ํจ์๊ฐ ์ ์๋์ด ์์ผ๋ ์ด
main.c์์๋ ์ฌ์ฉํ์ง ์๋๋ค.
์ด ํ์ด์ง์ ์ค์ ์ฝ๋๋ ์ญ์ฌ์ ์ค์ต ์๋ณธ์ด๋ฉฐ, ์ ์ฃผ์์ฌํญ์ ํด๊ฒฐํด ์ ๋น๋/๋ณด๋ ์คํ์ ์๋ฃํ ์์ ์ฝ๋๋ผ๊ณ ์ฃผ์ฅํ์ง ์๋๋ค.
SysTick์ ๋จ์ timing์ ๋ง๋ค๊ธฐ์๋ ํธํ์ง๋ง general-purpose timer๋ ์ดํ ๋ ๋ค์ํ hardware ๊ธฐ๋ฅ์ผ๋ก ํ์ฅํ ์ ์๋ค.
TIM
โโโ Periodic Timing
โโโ PWM
โโโ Output Compare
โโโ Input Capture
โโโ Event Generation
๋ฐ๋ผ์ ์ด๋ฒ 1Hz ์ค์ต์ ์ดํ Timer peripheral ํ์ฉ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋จ๊ณ๋ค.
๊ธฐ์กด ์ค์ต ๊ฒฐ๊ณผ:
text = 764 bytes
data = 0 bytes
bss = 2560 bytes
Warning ์์ด build ์๋ฃ.
make clean
makeExpected:
Build PASS
text = 764
data = 0
bss = 2560
Debugger:
TIM2->PSC
Expected:
1599
๊ณ์ฐ:
16 MHz / 1600
=
10 kHz
Debugger:
TIM2->ARR
Expected:
9999
๊ณ์ฐ:
10 kHz / 10000
=
1 Hz
Watch:
TIM2->CNT
์คํ ์ค ๊ฐ์ด ์ฆ๊ฐํ๋ ๊ฒ์ ํ์ธํ๋ค.
0
โ
1
โ
2
โ
...
Breakpoint๋ฅผ ๋ค์ ์ค์ ๊ฑธ ์ ์๋ค.
TIM2->SR &= ~SR_UIF;1์ด๊ฐ ์ง๋ breakpoint์ ๋๋ฌํ๋ฉด:
TIM2->SR bit0
=
1
์ธ์ง ํ์ธํ๋ค.
๊ทธ๋ค์ clear ์ดํ:
UIF
=
0
์ผ๋ก ๋์๊ฐ๋์ง ํ์ธํ๋ค.
Expected:
LD1 Toggle
every 1 second
์ฆ:
LED ON โ ์ฝ 1์ด
LED OFF โ ์ฝ 1์ด
์ด๋ฏ๋ก ์์ ํ ON/OFF cycle์ ์ฝ:
2 seconds
์ด๋ค.
์ด ์ฅ์์๋ board ์ฌ์ง๋ณด๋ค debugger์์ timer register๊ฐ ์ค์ ๊ณ์ฐ๊ฐ๊ณผ ์ผ์นํ๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ์ค์ํ๋ค.
PSC = 1599
ARR = 9999
CNT = increasing
UIF = 0 โ 1
์ด ๋ค ๊ฐ์ง๋ฅผ ํ ํ๋ฉด์์ ํ์ธํ๋ฉด ์ข๋ค.
images/ch09_build.png
images/ch09_psc_arr.png
images/ch09_cnt.png
images/ch09_uif.png
images/ch09_led.gif
๊ฐ์ฅ ์ค์ํ ์ฆ๊ฑฐ:
PSC / ARR Register
+
CNT Counting
+
UIF Assert
+
1-second LED Toggle
16 MHz
โ
PSC + 1 = 1600
โ
10 kHz
โ
ARR + 1 = 10000
โ
1 Hz
โ
Update Event
โ
UIF
- TIM2๋ STM32์ General-Purpose Timer๋ค.
- TIM2๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ APB1 clock์ enableํ๋ค.
-
PSC๋ timer input clock์ ๋ถ์ฃผํ๋ค. -
ARR์ timer period๋ฅผ ๊ฒฐ์ ํ๋ค. -
CNT๋ ํ์ฌ counter value๋ฅผ ๋ํ๋ธ๋ค. - Update Event ์ฃผํ์๋
f_timer / ((PSC+1) ร (ARR+1))์ด๋ค. - 16MHz์์
PSC=1599,ARR=9999๋ก 1Hz๋ฅผ ๋ง๋ ๋ค. -
CR1.CEN์ setํ๋ฉด counter๊ฐ ๋์ํ๋ค. - Update Event๊ฐ ๋ฐ์ํ๋ฉด
SR.UIF๋ฅผ ํ์ธํ ์ ์๋ค. - ์ด๋ฒ ์ค์ต์ UIF polling ๋ฐฉ์์ด๋ค.
- ์ด๋ฒคํธ ์ฒ๋ฆฌ ํ UIF๋ฅผ clearํ๊ณ ๋ค์ ์ฃผ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค.