728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 예제 프로그램을 이용하여 USART에 있는 Interrupt을 사용해 보자.

 

example -> USART -> Interrupt 폴더에 들어가서 _CreateProject.bat를 실행.

Project가 만들어지면 MDK_ARMv5 폴더에 들어가서 Project_52367.uvprojx 더블 클릭 하여 실행

 

int main(void)
{
  HT32F_DVB_LEDInit(HT_LED1); //LED1 포트 셋팅
  HT32F_DVB_LEDInit(HT_LED2); //LED2 포트 셋팅

  gURRx_Ptr = gRx_Buffer; //gRx_Buffer주소를 gURRx_Ptr 포인트 변수에 입력

  UxART_Configuration(); //USART 포트 셋팅

  UxART_TxTest(); //USART 통신 포트를 이용하여 전송 시험

  while (1)
  {
    UxART_RxTest(); //UART 통신 포트를 이용하여 수신 시험.
  }
}

 

main함수 설명이다.

 

void UxART_Configuration(void)
{
  #if 0 // Use following function to configure the IP clock speed.
  // The UxART IP clock speed must be faster 16x then the baudrate.
  CKCU_SetPeripPrescaler(CKCU_PCLK_UxARTn, CKCU_APBCLKPRE_DIV2);
  #endif

  { /* Enable peripheral clock of AFIO, UxART                                                               */
    CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
    CKCUClock.Bit.AFIO                   = 1; //AFIO 클럭 공급
    CKCUClock.Bit.HTCFG_UART_RX_GPIO_CLK = 1; //Port A 클럭 공급
    CKCUClock.Bit.HTCFG_UART_IPN         = 1; //USART1 클럭 공급
    CKCU_PeripClockConfig(CKCUClock, ENABLE); //클럭 셋팅
  }

  /* Turn on UxART Rx internal pull up resistor to prevent unknow state                                     */
  GPIO_PullResistorConfig(HTCFG_UART_RX_GPIO_PORT, HTCFG_UART_RX_GPIO_PIN, GPIO_PR_UP); //UART1에 RX핀에 내부 Pull up 셋팅.

  /* Config AFIO mode as UxART function.                                                                    */
  AFIO_GPxConfig(HTCFG_UART_TX_GPIO_ID, HTCFG_UART_TX_AFIO_PIN, AFIO_FUN_USART_UART); //PA4 포트를 UART TX모드로 사용하도록 셋팅
  AFIO_GPxConfig(HTCFG_UART_RX_GPIO_ID, HTCFG_UART_RX_AFIO_PIN, AFIO_FUN_USART_UART); //PA5 포트를 UART RX모드로 사용하도록 셋팅

  {
    /* UxART configured as follow:
          - BaudRate = 115200 baud
          - Word Length = 8 Bits
          - One Stop Bit
          - None parity bit
    */

    /* !!! NOTICE !!!
       Notice that the local variable (structure) did not have an initial value.
       Please confirm that there are no missing members in the parameter settings below in this function.
    */
    USART_InitTypeDef USART_InitStructure = {0};
    USART_InitStructure.USART_BaudRate = 115200; //USART1 포트 속도는 115200bps로 셋팅
    USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B; //Data 크기는 8Byte로 셋팅
    USART_InitStructure.USART_StopBits = USART_STOPBITS_1; //Stop Bit는 1개로 설정
    USART_InitStructure.USART_Parity = USART_PARITY_NO; //Parity Bit는 없음 으로 설정.
    USART_InitStructure.USART_Mode = USART_MODE_NORMAL; //비동기 통신 방식으로 설정
    USART_Init(HTCFG_UART_PORT, &USART_InitStructure); //위 설정값 적용
  }

  /* Enable UxART interrupt of NVIC                                                                         */
  NVIC_EnableIRQ(HTCFG_UART_IRQn); //UART 인터럽트 활성

  /* Enable UxART Rx interrupt                                                                              */
  USART_IntConfig(HTCFG_UART_PORT, USART_INT_RXDR, ENABLE); //수신 인터럽트 활성

  /* Enable UxART Tx and Rx function                                                                        */
  USART_TxCmd(HTCFG_UART_PORT, ENABLE); //USART1에 Tx 포트 활성
  USART_RxCmd(HTCFG_UART_PORT, ENABLE); //USART1에 Rx 포트 활성
}

 

USART 설정에 대한 설명이다.

 

void UxART_TxTest(void)
{
  gIsTxFinished = FALSE; //전송을 위해 현재 전송이 끝나지 않았다고 변수에 저장
  gURTx_Ptr = (u8 *)gHelloString; //gHelloString 변수 주소를 gURTx_Ptr라는 포인터 변수에 저장
  gURTx_Length = sizeof(gHelloString) - 1; //gHelloString 배열의 크기를 gURTx_Length 변수에 저장
  USART_IntConfig(HTCFG_UART_PORT, USART_INT_TXDE | USART_INT_TXC, ENABLE); //USART1 송신 변수가 비여있으면 인터럽트 발생하게 셋팅

  while (gURTx_Length != 0);      // Latest byte move to UxART shift register, but the transmission may be on going. //송신데이터가 모두 송신 될때까지 대기
  while (gIsTxFinished == FALSE); // Set by TXC interrupt, transmission is finished. //송신이 완전히 끝나지 않았으면 대기
}

 

UxART_TxTest 함수에 대한 설명이다.

 

void UxART_RxTest(void)
{
  u32 i;
  u32 uLength;

  /* Waiting for receive 5 data                                                                             */
  if (gURRx_Length >= 5) //gURRx_Length(수신 받은 데이터 수량)값이 5이상이면 아래 실행
  {
    // Process Rx data by gRx_Buffer[] and gURRx_Length here
    // .....

    uLength = gURRx_Length; //데이터 수량을 uLength에 저장
    for (i = 0; i < uLength; i++)
    {
      gTx_Buffer[i] = gRx_Buffer[i]; //gRx_Buffer 변수에 있는 데이터를 gTx_Buffer로 복사 (에코 기능)
    }

    #if 1 // Loop back Rx data to Tx for test
    gIsTxFinished = FALSE; //전송을 위해 현재 전송이 끝나지 않았다고 변수에 저장
    gURTx_Ptr = gTx_Buffer; //보낼 데이터가 있는 변수 주소를 gURTx_Ptr이라는 포인트 변수에 넣음.
    gURTx_Length = uLength; //수신 받은 수량을 송신할 수량에 복사
    USART_IntConfig(HTCFG_UART_PORT, USART_INT_TXDE | USART_INT_TXC, ENABLE); //USART1 송신 변수가 비여있으면 인터럽트 발생하게 셋팅
    #endif

    gURRx_Length = 0; //수신 받은 데이터 수량 초기화
  }
}

UxART_RxTest 함수에 대한 설명이다.

 

 

ht32f5xxxx_01_it.c 파일로 가면 송신 및 수신하는 인터럽트 함수가 있다.

void HTCFG_UART_IRQHandler(void)
{
  extern uc8  *gURTx_Ptr;
  extern vu32  gURTx_Length;
  extern u8   *gURRx_Ptr;
  extern vu32  gURRx_Length;
  extern vu32 gIsTxFinished;

#if (DEBUG_IO == 1)
  #define DBG_IO1_LO()    HT32F_DVB_LEDOn(HT_LED1)
  #define DBG_IO1_HI()    HT32F_DVB_LEDOff(HT_LED1)
  #define DBG_IO2_LO()    HT32F_DVB_LEDOn(HT_LED2)
  #define DBG_IO2_HI()    HT32F_DVB_LEDOff(HT_LED2)
#else
  #define DBG_IO1_LO(...)
  #define DBG_IO1_HI(...)
  #define DBG_IO2_LO(...)
  #define DBG_IO2_HI(...)
#endif

  /* Rx: Move data from UART to buffer                                                                      */
  if (USART_GetFlagStatus(HTCFG_UART_PORT, USART_FLAG_RXDR)) //수신된 데이터가 있는지 확인
  {
    DBG_IO1_LO();
    gURRx_Ptr[gURRx_Length++] = USART_ReceiveData(HTCFG_UART_PORT); //수신 받은 데이터를 gRx_Buffer에 넣어라.
    DBG_IO1_HI();

    #if 0
    if (gURRx_Length == 128)
    {
      while (1) {}; // Rx Buffer full
    }
    #endif
  }

  /* Tx, move data from buffer to UART                                                                      */
  if (USART_GetIntStatus(HTCFG_UART_PORT, USART_INT_TXDE) && //송신 인터럽트가 발생 했는지 확인
      USART_GetFlagStatus(HTCFG_UART_PORT, USART_FLAG_TXDE)) //송신 인터럽트중 송신 버퍼가 비였다는 인터럽트가 발생했는지 확인
  {
    DBG_IO2_LO();
    if (gURTx_Length > 0) //보낼 데이터가 있으면 실행
    {
      USART_SendData(HTCFG_UART_PORT, *gURTx_Ptr++); //gTx_Buffer에 있는 데이터를 하나씩 순서대로 전송
      gURTx_Length--; //보낼 데이터 하나 감소
      if (gURTx_Length == 0) //보낼 데이터가 없는지 확인
      {
        USART_IntConfig(HTCFG_UART_PORT, USART_INT_TXDE, DISABLE); //보낼 데이터가 없으면 송신 버퍼가 비여있으면 인터럽트 발생되는것을 비활성 시킴
      }
    }
    DBG_IO2_HI();
  }

  if (USART_GetIntStatus(HTCFG_UART_PORT, USART_INT_TXC) && //송신 인터럽트가 발생 했는지 확인
      USART_GetFlagStatus(HTCFG_UART_PORT, USART_FLAG_TXC)) //송신 버퍼에 들어 있던 데이터를 보냈는지 확인
  {
    USART_IntConfig(HTCFG_UART_PORT, USART_INT_TXC, DISABLE); //송신 버퍼에 들어 있던 데이터를 보냈다면 송신 인터럽트 비활성 시킴
    gIsTxFinished = TRUE; //송신이 끝났다고 변수에 저장
  }
}

 

송신과 수신이 인터럽트로 처리 되는 부분을 적어놓음.

TEST를 하다보니 버그가 있다.

5글자를 PC에서 보내면 5글자가 오는데 6글자를 보내면 마지막 한글자가 다음에 나오는 현상이 있음.

예제에 있는 버그다.

 

 

 

Interrupt.zip
4.88MB

 

 

 

 

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 예제 프로그램을 이용하여 NVIC(Nested Vectored Interrupt Controller) 에 있는 System_Exception (예외) 를 사용해 보자.

 

example -> NVIC -> System_Exception 폴더에 들어가서 _CreateProject.bat를 실행.

Project가 만들어지면 MDK_ARMv5 폴더에 들어가서 Project_52367.uvprojx 더블 클릭 하여 실행

main이 다음과 같이 되어 있다.

int main(void)
{
  /* Initialize LEDs                                                                                        */
  HT32F_DVB_LEDInit(HT_LED1); //LED1 포트 셋팅
  HT32F_DVB_LEDInit(HT_LED2); //LED2 포트 셋팅
  HT32F_DVB_LEDInit(HT_LED3); //LED3 포트 셋팅

  /* Configure the Exception Handler Interrupts Priority                                                    */
  NVIC_SetPriority(PendSV_IRQn, 0); //PendSV 인터럽트 중요도 할당
  NVIC_SetPriority(SysTick_IRQn, 1); //SysTick 인터럽트 중요도 할당
  /* Set pending bits at the same time                                                                      */
  NVIC_SetPendingSystemHandler(SYSTEMHANDLER_NMI | SYSTEMHANDLER_PSV | SYSTEMHANDLER_SYSTICK); //NMI, PSV, SYSTICK 인터럽트를 보류로 설정한다.

  /* Check on the LEDs flash sequence                                                                       */
  while (1);
}

 

PendSV가 무엇인지 찾아 보았는데 모든 인터럽트가 모두 처리된후 가장 낮은 순위로 처리 되는 인터럽트라고 나와 있다.

프로그램을 실행 해보면 LED1은 계속 켜 있고 LED2가 켜졌다가 꺼졌다가 하고 LED3포트에 스코프를 연결해서 보면 LED2가 꺼졌을때 조금 후에 LED3 Port가 High 신호가 나온다.

여러 자료를 찾아보니 PendSV 인터럽트는 MCU가 1개의 명령을 실행하고 인터럽트가 있는지 확인을 하는데 아무런 인터럽트가 없을때 동작 한다고 한다.

 

System_Exception.zip
4.86MB

728x90
반응형

+ Recent posts