이전 펌웨어 기본 동작 구현 2 에서

Timer 6을 이용해 LED 토글했었던 것을 이어서,

@+'1'~'4'를 입력하면 LED 주기를 (2초 1초 0.5초 0.25초..등) 변경해보는 것을 구현해봅니다.

시리얼 포트로 해당 문장도 같이 출력합니다.

해야할 것

  1. 주변 장치 타이머,gpio Init
    TIM6 Init
    LED Init
    UART Init
    주변 peripheral->stmf4xxxx_reference manual.pdf
  2. 인터럽트로 입력 받을 UART 핸들러 구현
    ->stmf4xxxx_reference manual.pdf
    ->programming manual.pdf
    이전 글 참고 및 필요한 문서들은 공지사항에 첨부해두었습니다.
  3. LED 주기마다 토글시킬 TIM6 핸들러 구현
  4. main에 while문안에 인터럽트 이후 동작 구현

인터럽트로 구현 - UART 시리얼 포트로 @+1~4 입력 시 LED 주기 변경

void LED_Init(void){
    RCC->AHB1ENR |= (0x1<<1);//GPIOB

    GPIOB->MODER &= ~(0x3<<7*2);//LED output mode
    GPIOB->MODER |= (0x01 <<7*2);

    GPIOB->BSRR=(0x01<<(7+16));
}

void TIM6_Init(void){
    //TIM6 clock 활성화
     RCC->APB1ENR |= 1<<4;

     //APB1 : 84MHz

     //(7:ARR preload enable,2:update request sources, 1: update enable, 0 : counter reset)
     TIM6->CR1=(0x1<<7 | 0x1<<2 | 0x0<<1 | 0x0<<0);
     //84000000->
     TIM6->PSC=8400-1;//10000 10kHz
    // TIM6->ARR=10-1;//
     TIM6->ARR=5000-1;//10000/5000=2Hz 0.5s

     TIM6->CNT=0;//0부터 시작

     TIM6->DIER=0x1<<0; //Interrupt enable
     //NVIC에 TIM6_DAC_IRQ 번호 등록하기
      NVIC->ISER[1]|=0x1<<22; //54번 IRQ. ISER[1] 32~63
      TIM6->CR1 |= 0x1<<0;


}

void Change_LEDTime(int t){
    switch(t){
        case 1:
            TIM6->ARR=5000-1;//0.5s
            break;
        case 2:
            TIM6->ARR=10000-1;//1s
            break;
        case 3:
            TIM6->ARR=20000-1;//2s
            break;
        case 4:
            TIM6->ARR=30000-1;//3s
            break;
        default:
            TIM6->ARR=5000-1;
    }

}

void TIM6_DAC_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
 if(TIM6->SR & (0x1)){
     TIM6->SR = ~(0x1);//rc_w0
     GPIOB->ODR ^=(0x1<<7);

 }}
void UART3_Init(void){
    RCC->AHB1ENR |= 1<<3;//GPIOD
    RCC->APB1ENR |= 1<<18;//USART3

    //PD8,9 AF모드
    GPIOD->MODER &= ~((0x3<< (2*8))| (0x3<<(2*9)));
    GPIOD->MODER |=((0x2<<(2*8)) | (0x2<<(2*9)));

    GPIOD->AFR[1]&= ~(0xf<<4 | 0xf<<0);//MUX PD8,9(AFRH 8~15)
    GPIOD->AFR[1] |= (0x7<<4 | 0x7<<0);//uart3

    USART3->CR1 =(1<<13 |1<<5| 1<<3 | 1<<2);//UE,TE,RE
    USART3->BRR=(22 << 4) | 13;//115200bps,42MHZ =356
      NVIC->ISER[1]|=0x1<<7; //39번 IRQ. ISER[1] 32~63

}

void UART3_Send(char c){
    while(!((USART3->SR>>7)&(0x1)));
    USART3->DR=c;
}
char UART3_Receive(void)
{
    while (!(USART3->SR & USART_SR_RXNE));
    return (char)(USART3->DR);
}

void UART3_Print(const char* str){
    while(*str){
        UART3_Send(*str++);
    }
}

char msg[100];
volatile int id = 0;
volatile int sended = 0;

void USART3_IRQHandler(void)
{

    if (USART3->SR & USART_SR_RXNE) {
        char c = (char)USART3->DR;

        if (c == '\r' || c == '\n') {
            msg[id] = '\0';
            sended = 1;
            id = 0;
            } 
        else if (id < 99) {
            msg[id++] = c;
        }
    }

}



int main(void)
{

  HAL_Init();
  UART3_Init();
   LED_Init();
   TIM6_Init();

  SystemClock_Config();

  while (1)
  {
  if(sended==1){
      sended=0;
      UART3_Print(msg);

    for(int i=0;msg[i]!='\0';++i){
             if(msg[i]=='@'){
                  int t=(int)(msg[i+1]-'0');
                  Change_LEDTime(t);
                  break;

               }}
    UART3_Print(msg);

  }

  }

}

+ Recent posts