문제 설명
TIM4 타이머를 이용하여 PWM 신호를 생성하고, UART로 입력된 숫자(0~9)에 따라 LED 밝기를 제어하는 프로그램을 작성하라.
- TIM4 채널을 사용하여 PWM 파형 출력
- 입력값 1~9는 듀티비로 적용되어 LED 밝기를 변경
- 입력값 0은 PWM 출력을 정지시켜 LED를 끔
- UART 입력을 통해 사용자와 상호작용하며, 현재 입력값을 UART로 다시 출력함
정답 코드
// timer.c
#define TIM4_FREQ (1000000) // 1MHz
#define TIM4_TICK (1000000/TIM4_FREQ) // usec
#define TIME4_PLS_OF_1ms (1000/TIM4_TICK)
void TIM4_Out_Init(void)
{
Macro_Set_Bit(RCC->APB1ENR, 2); // tim4
Macro_Set_Bit(RCC->APB2ENR, 3); // b port
Macro_Write_Block(GPIOB->CRH, 0xF, 0xE, 0); //1110 open drain
Macro_Write_Block(TIM4->CCMR2, 0xFF, 0x68, 0);
TIM4->CCER = (0<<9)|(1<<8);
}
void TIM4_Out_PWM_Generation(unsigned int freq, unsigned int duty)
{
// Down Counter, Repeat Mode
TIM4->CR1 = (1<<4)|(0<<3);
// Timer 주파수가 TIM4_FREQ가 되도록 PSC 설정
TIM4->PSC = (unsigned int)((TIMXCLK / (double)TIM4_FREQ) + 0.5) - 1; // 1KHz
// 요청한 주파수가 되도록 ARR 설정
TIM4->ARR = (int)((double)TIM4_FREQ/freq + 0.5) - 1;
// Duty Rate 50%가 되도록 CCR3 설정
TIM4->CCR3 = (int)(TIM4->ARR * (duty / 10.));
// Manual Update(UG 발생)
Macro_Set_Bit(TIM4->EGR, 0);
// Timer Start
Macro_Set_Bit(TIM4->CR1, 0);
}
void TIM4_Out_Stop(void)
{
Macro_Clear_Bit(TIM4->CR1, 0);
}
void TIM4_Change_Duty(unsigned int duty)
{
TIM4->CCR3 = (int)(TIM4->ARR * (duty / 10.));
}
// main.c
#include "device_driver.h"
static void Sys_Init(void)
{
Clock_Init();
LED_Init();
Uart_Init(115200);
Key_Poll_Init();
}
void Main(void)
{
Sys_Init();
TIM4_Out_Init();
char x;
int timer_run = 0;
TIM4_Out_PWM_Generation(1000, 0);
for(;;)
{
x = Uart1_Get_Pressed();
if (x != 0)
{
int n = x - '0';
Uart1_Printf("%d", n);
if (n == 0)
{
TIM4_Out_Stop();
timer_run = 0;
}
else
{
if (timer_run == 0)
{
TIM4_Out_PWM_Generation(1000, n);
timer_run = 1;
}
else
{
TIM4_Change_Duty(n);
}
}
}
}
}
메모
printf 내부의 \n 습관화 필요