Home > Study > C Language > ARM System Programming > [ex24] 디지털 피아노

[ex24] 디지털 피아노
Study Language

문제 설명


다음 요구하는 기능을 만족하는 코드를 작성하라

[요구 사항]

  • 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 습관화 필요