문제 설명
다음 요구하는 기능을 만족하는 코드를 작성하라
[요구 사항]
- PC 터미널 프로그램에서 키보드로 1,2,3,4,5,6,7,8 을 누르면 도 부터 높은 도까지 음을 4분 음표로 연주하는 코드를 구현하라
- 1은 도 2는 레 3은 미 … 8은 높은 도가 4분 음표 길이(500msec) 연주되어야 한다.
- 하나의 음이 연주되는 동안 키보드 입력이 있는 경우 무시하면 된다.
- 인터럽트 사용 여부는 무관하며 여러 파일에 코드를 작성한 경우 작성한 코드 모두 복사하여 Bash 언어로 제출해야 한다.
[제출 요령]
- 코드를 완성하면 반드시 동작 확인을 받은후 강사 지시에 의하여 코드를 업로드해야 함
- 임의로 코드 제출시 해당 문항 0점 처리되므로 주의 바람
- 다른 파일에 있는 수업때 제공 또는 작성한 코드를 사용한 경우는 복사하여 제출할 필요 없음 (예) LED_Display 함수 등
- 작성 또는 기존 코드 변경한 파일의 내용(이 문제와 관련한 코드 부분만)을 모두 복사하여 제출해야 한다.
- 제출시에는 main.c 내용을 제일 위에 놓고 그 아래에 다른 파일의 코드를 제출하되 main.c 이외 파일은 반드시 파일명을 코드 위에 적고 복사하여 제출할 것
정답 코드
# if 1
// main.c
#include "device_driver.h"
static void Sys_Init(void)
{
Clock_Init();
LED_Init();
Uart_Init(115200);
Key_Poll_Init();
}
#define BASE (500) // 4분 음표 = 500ms
static void Play_Tone(unsigned short freq)
{
TIM3_Out_Freq_Generation(freq); // PWM 출력 시작
TIM2_Delay(BASE); // 500ms 유지
TIM3_Out_Stop();
}
volatile char dummy;
void Flush_UART_Buffer(void)
{
while (Macro_Check_Bit_Set(USART1->SR, 5)) {
dummy = USART1->DR;
}
}
void Main(void)
{
const unsigned short tone_value[] = {261, 293, 329, 349, 392, 440, 493, 523};
char input;
Sys_Init();
TIM3_Out_Init();
Uart1_Printf("[8323] C9\n");
while (1)
{
input = Uart1_Get_Char(); // 입력 대기
if (input >= '1' && input <= '8') {
int index = input - '1';
Play_Tone(tone_value[index]);
Flush_UART_Buffer();
}
}
}
# endif
# if 1
// timer.c
#define TIM3_FREQ 8000000
#define TIM3_TICK (1000000 / TIM3_FREQ)
#define TIME3_PLS_OF_1ms (1000 / TIM3_TICK)
#define TIM2_TICK 20
#define TIM2_FREQ (1000000 / TIM2_TICK)
#define TIME2_PLS_OF_1ms (1000 / TIM2_TICK)
void TIM3_Out_Init(void)
{
Macro_Set_Bit(RCC->APB1ENR, 1); // TIM3 enable
Macro_Set_Bit(RCC->APB2ENR, 3); // GPIOB enable
Macro_Write_Block(GPIOB->CRL, 0xf, 0xb, 0); // PB0: Alternate function output
Macro_Write_Block(TIM3->CCMR2, 0x7, 0x6, 4); // PWM mode 1
TIM3->CCER = (0 << 9) | (1 << 8); // Output enable
}
void TIM3_Out_Freq_Generation(unsigned short freq)
{
TIM3->PSC = (unsigned int)((TIMXCLK / (double)TIM3_FREQ) + 0.5) - 1;
TIM3->ARR = (unsigned int)((double)TIM3_FREQ / freq) - 1;
TIM3->CCR3 = TIM3->ARR / 2;
Macro_Set_Bit(TIM3->EGR, 0);
TIM3->CR1 = (1 << 4) | (0 << 3) | (0 << 1) | (1 << 0);
}
void TIM3_Out_Stop(void)
{
Macro_Clear_Bit(TIM3->CR1, 0);
Macro_Clear_Bit(TIM3->DIER, 0);
}
void TIM2_Delay(int time_ms)
{
Macro_Set_Bit(RCC->APB1ENR, 0);
TIM2->PSC = (unsigned int)((TIMXCLK / (double)TIM2_FREQ) + 0.5) - 1;
TIM2->ARR = TIME2_PLS_OF_1ms * time_ms;
Macro_Set_Bit(TIM2->EGR, 0);
Macro_Clear_Bit(TIM2->SR, 0);
Macro_Set_Bit(TIM2->DIER, 0);
Macro_Set_Bit(TIM2->CR1, 0);
while (Macro_Check_Bit_Clear(TIM2->SR, 0));
Macro_Clear_Bit(TIM2->CR1, 0);
Macro_Clear_Bit(TIM2->DIER, 0);
}
# endif
메모
printf 내부의 \n 습관화 필요