Bare metal C Ch09 TIM - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki
ํ ์ค ์์ฝ: TIM2๋ฅผ ์ฌ์ฉํด 1 Hz Update Event๋ฅผ ๋ง๋ค๊ณ , UIF ํ๋๊ทธ๋ฅผ ํด๋งํด LD1์ 1์ด ์ฃผ๊ธฐ๋ก ํ ๊ธํ๋ค.
Ch08์ SysTick์ Cortex-M ์ฝ์ด์ ํฌํจ๋ ๊ณตํต ํ์ด๋จธ์ด๊ณ , TIM์ STM32๊ฐ ์ ๊ณตํ๋ ๋ฒค๋ ์ฃผ๋ณ์ฅ์น๋ค. STM32F439์๋ ์ฌ๋ฌ ๊ฐ์ TIM์ด ์กด์ฌํ๋ฉฐ, ์ผ๋ฐ์ ์ธ delay๋ฟ ์๋๋ผ PWM, Input Capture, Output Compare, Encoder ๋ฑ์ ๊ธฐ๋ฅ์ผ๋ก ํ์ฅํ ์ ์๋ค.
ํญ๋ชฉ | SysTick | TIM2 -- | -- | -- ์์ | Cortex-M ์ฝ์ด | STM32 peripheral ๊ฐ์ | 1๊ฐ | ์ฌ๋ฌ TIM ์ฌ์ฉ ๊ฐ๋ฅ ์นด์ดํฐ | 24-bit down counter | TIM2๋ 32-bit ์ํ ํ๋๊ทธ | COUNTFLAG | UIF ์ด๋ฒ ์ค์ต | SysTick polling | TIM2 Update Event pollingNotion ์ ๋ฆฌ์์๋ APB1 timer clock์ 16 MHz๋ก ๋๊ณ ๋ค์ ๊ฐ์ ์ฌ์ฉํ๋ค.
UEV frequency
= Timer Clock / ((PSC + 1) ร (ARR + 1))
PSC = 1599
ARR = 9999
16,000,000 / (1600 ร 10000)
= 1 Hz
PSC์ ARR ๋ชจ๋ 0๋ถํฐ ์ธ๋ฏ๋ก ๊ณ์ฐ์๋ +1์ด ๋ค์ด๊ฐ๋ค.
TIM์ UIF๋ ํ ๋ฒ set๋ ๋ค ์ํํธ์จ์ด๊ฐ ์ง์ clearํด์ผ ํ๋ค.
TIM2->SR &= ~SR_UIF;
์ด๋ฅผ ์๋ตํ๋ฉด ์ฒซ Update Event ์ดํ while (!(TIM2->SR & SR_UIF))๊ฐ ๊ณ์ ๋ฐ๋ก ํต๊ณผํ๋ค.
RCC->APB1ENR
โ
โโ TIM2 clock enable
โ
โผ
PSC = 1599
โ
โผ
ARR = 9999
โ
โผ
CEN = 1
โ
โผ
TIM2 counting
โ
โผ
Update Event ๋ฐ์
โ
โผ
UIF = 1
โ
โผ
LED toggle
โ
โผ
UIF ์ง์ clear
Ch09_tim/
โโโ Inc/gpio.h
โโโ Src/gpio.c
โโโ Inc/tim.h
โโโ Src/tim.c
โโโ Src/main.c
syscalls.c,sysmem.c, startup file, linker script, CubeIDE metadata/build output์ Ch04์์ ๋ค๋ฃฌ ๊ณตํต ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ด ํ์ด์ง์์๋ ๋ฐ๋ณตํ์ง ์๋๋ค. ์๋์๋ ์ด chapter ๊ธฐ๋ฅ ๊ตฌํ์ ์ง์ ์ฌ์ฉํ source/header๋ฅผ ์ ๋ถ ๊ธฐ๋กํ๋ค.
#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;
}
}
Notion ๊ธฐ๋ก ๊ธฐ์ค:
text = 764 bytes
data = 0 bytes
bss = 2560 bytes
warning ์์
์ด ํ์ด์ง์ Notion ๊ธฐ๋ก์๋ build ๊ฒฐ๊ณผ๊ฐ ์ ๋ฆฌ๋์ด ์์ผ๋ฉฐ, ๋ณ๋์ ์ค์ ๋ณด๋ ๋์ ๊ฒฐ๊ณผ ๋ฌธ๊ตฌ๋ ๊ธฐ๋ก๋์ด ์์ง ์๋ค.
TIM ์ฃผ๊ธฐ๋
Timer Clock / ((PSC+1)*(ARR+1))๋ก ๊ณ์ฐํ๋ค.TIM์
UIF๋ software์์ ์ง์ clearํ๋ค.TIM์ SysTick๊ณผ ๋ฌ๋ฆฌ STM32 peripheral์ด๋ฉฐ ์ฌ๋ฌ timer์ PWM/Input Capture ๊ธฐ๋ฅ์ผ๋ก ํ์ฅ๋๋ค.