728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 CodeConfig 프로그램을 이용하여 DAC에 Sine wave를 출력 해보자.

New 버튼을 눌러 SelectMCU 창이 나오면 아래로 스크롤 하여 HT32F52367을 확장한다음 LQFP80을 선택후 OK 버튼을 눌러주자.

바로 뜨는창은 내부 클럭으로 최대 Clock으로 셋팅된 화면이 나온다.

변경 없이 AFIO 탭을 선택 하고 스크롤 하여 아래로 내리면 DAC 포트는 PC3, PB8 두개가 있다.

DAC0_OUT 글씨를 마우스 왼쪽 버튼으로 더블 클릭 해주자. DAC1_OUT도 더블 클릭 해주자.

 

타이머를 하나 써야 합니다.

기존에 BFTM0 가 자동으로 셋팅이 되어 있어 있다.

Datasheet를 확인하면 BFTM은 APB Clock을 받는다. APB Clock은 60MHz이다.

Timer 탭에 보면 BFTM0가 체크 되어 있다.

ADC/DAC 탭에서 Enable Interrupt 체크박스를 해제 해주자.

F7을 눌러 파일을 생성할 위치를 지정해 주고 확인을 누르자.

필자 같은 경우는 DAC 폴더를 만들어서 그곳을 클릭후 확인을 눌러 주었다.

생성이 완료 되면 Open Project를 눌러서 파일을 열어 보자.

F7을 눌러 Build하면 에러가 발생한다.

에러를 찾아가면 DAC_Configuration 안에 있다.

void DAC_Configuration(void)
{
  CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  CKCUClock.Bit.DAC   = 1;  //DAC 클럭 공급
  CKCUClock.Bit.AFIO  = 1;  //AFIO 클럭 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //클럭 셋팅

 

  AFIO_GPxConfig(GPIO_PC, AFIO_PIN_3, AFIO_FUN_DAC); //PC3 포트를 DAC로 동작 변경 하는것.
  AFIO_GPxConfig(GPIO_PB, AFIO_PIN_8, AFIO_FUN_DAC); //PB8 포트를 DAC로 동작 변경 하는것.

  DAC_ModeConfig(ASYNC_MODE);   //DAC 비동기 모드로 동작
  DAC_ReferenceConfig(DAC_CH0, DAC_REFERENCE_VDDA); //DAC CH0에 기준 전압은 VDDA(3.3V)로 설정
  DAC_ResolutionConfig(DAC_CH0, DAC_RESOLUTION_12BIT);  //DAC 분해능은 12Bit (2^12Bit = 0 ~ 4095단계)
  DAC_OutBufCmd(DAC_CH0, ENABLE);   //DAC CH0 출력 버퍼 활성
  //DAC_IntConfig(DAC_INT_DOR0IE,ENABLE); //DAC CH0에 대한 인터럽트 활성인데 홀텍사에 확인하니 인터럽트를 지원 안한다고 한다. Skip 해주자.
  DAC_SetData(DAC_CH0,0);   //DAC CH0(PC3) 초기 출력은 0V

  DAC_ReferenceConfig(DAC_CH1, DAC_REFERENCE_VDDA); //DAC CH1에 기준 전압은 VDDA(3.3V)로 설정
  DAC_ResolutionConfig(DAC_CH1, DAC_RESOLUTION_12BIT);  //DAC 분해능은 12Bit (2^12Bit = 0 ~ 4095단계)
  DAC_OutBufCmd(DAC_CH1, ENABLE);   //DAC CH1 출력 버퍼 활성
  //DAC_IntConfig(DAC_INT_DOR1IE,ENABLE); //DAC CH1에 대한 인터럽트 활성인데 홀텍사에 확인하니 인터럽트를 지원 안한다고 한다. Skip 해주자.
  DAC_SetData(DAC_CH1,0);   //DAC CH1(PB8) 초기 출력은 0V

  DAC_Cmd(DAC_CH0,ENABLE);  //Enable DAC0
  DAC_Cmd(DAC_CH1,ENABLE);  //Enable DAC1
}

 

 

//DAC_IntConfig(DAC_INT_DOR0IE,ENABLE); 

//DAC_IntConfig(DAC_INT_DOR1IE,ENABLE);

위 우개에 인터럽트 설정이 있는데 Skip을 해주어야 한다. (홀텍사에서 인터럽트가 없어졌단다..)

 

  AFIO_GPxConfig(GPIO_PC, AFIO_PIN_3, AFIO_FUN_DAC); //PC3 포트를 DAC로 동작 변경 하는것.
  AFIO_GPxConfig(GPIO_PB, AFIO_PIN_8, AFIO_FUN_DAC); //PB8 포트를 DAC로 동작 변경 하는것.

포트 셋팅도 안해주어서 추가 해주어햐 한다. CodeConfig에서 이부분을 만들어주지 않는다. 

그렇지 않으면 DAC 동작을 못한다.


#include "BFTM0.h"

//-----------------------------------------------------------------------------
#define BFTM0_TIMER_BASE            ((long long)SystemCoreClock * 10/1000)
#define DAC_SINE_WAVE_SAMPLES 500 //500포인트로 잡을 예정임.
//-----------------------------------------------------------------------------
vu32 bftm0_ct;
extern uint16_t sine_wave[DAC_SINE_WAVE_SAMPLES]; //main.c 파일에서 사용중인 변수를 사용하기 위해 extern을 해준다.
//-----------------------------------------------------------------------------
void BFTM0_Configuration(void)
{
  CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
  CKCUClock.Bit.BFTM0      = 1; //BFTI0에 클럭 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //클럭 셋팅

  NVIC_EnableIRQ(BFTM0_IRQn);   // interrupt enable
  BFTM_IntConfig(HT_BFTM0, ENABLE); //BFTM0 인터럽트 활성화

  BFTM_SetCompare(HT_BFTM0, BFTM0_TIMER_BASE); //BFTM0 인터럽트 발생할 카운터값 설정
  BFTM_SetCounter(HT_BFTM0, 0); //BFTM0 카운터값을 초기화
  //BFTM_EnaCmd(HT_BFTM0, ENABLE);
}
BFTM셋팅이다. 마지막에 BFTM_EnaCmd(HT_BFTM0, ENABLE); 이부분을 Skip 해주자.

DAC가 셋팅이 안되었는데 인터럽트가 걸려서 DAC_SetData 명령을 수행 하면 HardFault_Handler 에러가 발생한다.

void BFTM0_IRQHandler(void)
{
static uint16_t index =0; //지워지지 않는 변수이다.
  BFTM_ClearFlag(HT_BFTM0);
  bftm0_ct++;
DAC_SetData(DAC_CH0, sine_wave[index]); //DAC_CH0 출력을 변경한다.
  DAC_SetData(DAC_CH1, sine_wave[index]); //DAC_CH1 출력을 변경한다.
index++; //읽어올 sine_wave 배열 변수를 증가한다.
index %= DAC_SINE_WAVE_SAMPLES; //index값이 500이 돼면 0으로 해준다.
}
BFTM0 인터럽트에서 위와 같이 추가 해준다.

 

main.c 파일에 있는 내용이다.

#include "ht32.h"
#include "BFTM0.h"
#include "DAC.h"
#include "math.h" //rint와 sintf를 사용하기 위해 포함.

#define PI 3.141592 //추가
#define DAC_SINE_WAVE_SAMPLES 500 //500포인트로 잡을 예정임.
uint16_t sine_wave[DAC_SINE_WAVE_SAMPLES] = { 0 }; //Sine wave 값을 저장하기 위한 변수 추가
uint16_t sine_wave_idx = 0; //Sine wave를 만들때 카운터로 사용할 변수 추가
//-----------------------------------------------------------------------------
int main(void)
{
uint16_t i, alpha, beta; //변수 추가
BFTM0_Configuration(); //BFTM0 셋팅
DAC_Configuration(); //DAC 셋팅

///////////// Sine wave를 만들어주는 부분
alpha = 255;
beta = 100;
for (i = 0; i < DAC_SINE_WAVE_SAMPLES; i++)
{
sine_wave[i] = (uint16_t)rint((sinf(((2 * PI) / DAC_SINE_WAVE_SAMPLES) * i) + 1) * alpha) + beta;
if (sine_wave[i] >= 4095) sine_wave[i] = 4095;
}
BFTM_EnaCmd(HT_BFTM0, ENABLE); //BFTM0 동작 시작
while (1)
{
if (HT_CKCU->APBCCR1 & (1 << 4)) //와치독 클럭이 공급 되고 있는지 확인
WDT_Restart(); //와치독 카운터 초기화
//DAC_test();  //Can be removed

}
}

 

이렇게 프로그램을 작성하고 실행하면 다음과 같은 DAC 출력을 확인 할수 있다.

 

주파수가 너무 낮게 나온다. 주파수를 높일려면 BFTM0에 인터럽트 발생 시간을 줄여주면 된다.

BFTM0.C에 가면 현재 10mSEC 인터럽트가 발생 하게 되어 있다.

#define BFTM0_TIMER_BASE            ((long long)SystemCoreClock * 10/1000)

이부분에서 10을 0.1로 변경하면 10mSEC에서 0.1mSEC가 되어 주파수가 100배는 빨라 질것이다.

#define BFTM0_TIMER_BASE            ((long long)SystemCoreClock * 0.1/1000)

이렇게 변경한 파형이다.

 

 

 

주파수가 약 20Hz 나오는것을 확인 할수 있다.

DAC.zip
6.96MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 CodeConfig 프로그램을 이용하여 DAC에 Sine wave를 출력 해보자.

New 버튼을 눌러 SelectMCU 창이 나오면 아래로 스크롤 하여 HT32F52367을 확장한다음 LQFP80을 선택후 OK 버튼을 눌러주자.

바로 뜨는창은 내부 클럭으로 최대 Clock으로 셋팅된 화면이 나온다.

변경 없이 AFIO 탭을 선택 하고 스크롤 하여 아래로 내리면 DAC 포트는 PC3, PB8 두개가 있다.

DAC0_OUT 글씨를 마우스 왼쪽 버튼으로 더블 클릭 해주자. DAC1_OUT도 더블 클릭 해주자.

 

타이머를 하나 써야 합니다.

기존에 BFTM0 가 자동으로 셋팅이 되어 있어 있다.

Datasheet를 확인하면 BFTM은 APB Clock을 받는다. APB Clock은 60MHz이다.

 

Timer 탭에 보면 BFTM0가 체크 되어 있다.

새로 생긴 ADC/DAC 탭을 클릭하니 위와 같이 나와 있다.

F7을 눌러서 파일을 생성할 위치를 지정해 주고 확인을 누르자.

필자 같은 경우는 DAC 폴더를 만들어서 그곳을 클릭후 확인을 눌러 주었다.

생성이 완료 되면 Open Project를 눌러서 파일을 열어 보자.

F7키를 눌러 컴파일 해주니 에러가 발생 했다.

CodeConfig로 그냥 만들기만 했는데..... 아직은 문제가 있다.

 

void DAC_Configuration(void)
{
  CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  CKCUClock.Bit.DAC   = 1;  //DAC 클럭 공급
  CKCUClock.Bit.AFIO  = 1;  //AFIO 클럭 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //클럭 셋팅

  DAC_ModeConfig(ASYNC_MODE);   //DAC 비동기 모드로 동작
  DAC_ReferenceConfig(DAC_CH0, DAC_REFERENCE_VDDA); //DAC CH0에 기준 전압은 VDDA(3.3V)로 설정
  DAC_ResolutionConfig(DAC_CH0, DAC_RESOLUTION_12BIT);  //DAC 분해능은 12Bit (2^12Bit = 0 ~ 4095단계)
  DAC_OutBufCmd(DAC_CH0, ENABLE);   //DAC CH0 출력 버퍼 활성
  DAC_IntConfig(DAC_INT_DOR0IE,ENABLE); //DAC CH0에 대한 인터럽트 활성


  DAC_SetData(DAC_CH0,0);   //DAC CH0 초기 출력은 0V

  DAC_ReferenceConfig(DAC_CH1, DAC_REFERENCE_VDDA); //DAC CH1에 기준 전압은 VDDA(3.3V)로 설정
  DAC_ResolutionConfig(DAC_CH1, DAC_RESOLUTION_12BIT);  //DAC 분해능은 12Bit (2^12Bit = 0 ~ 4095단계)
  DAC_OutBufCmd(DAC_CH1, ENABLE);   //DAC CH1 출력 버퍼 활성
  DAC_IntConfig(DAC_INT_DOR1IE,ENABLE); //DAC CH1에 대한 인터럽트 활성


  DAC_SetData(DAC_CH1,0);   //DAC CH1 초기 출력은 0V

  NVIC_EnableIRQ(COMP_DAC_IRQn);    //DAC 인터럽트 활성

  DAC_Cmd(DAC_CH0,ENABLE);  //Enable DAC0
  DAC_Cmd(DAC_CH1,ENABLE);  //Enable DAC1
}

 

DAC 설정부분 설명입니다.

 

void COMP_DAC_IRQHandler(void)
{
  if (DAC_GetFlagStatus(DAC_FLAG_DOR0IF) ==  SET)
  {
    DAC_ClearFlag(DAC_FLAG_DOR0IF); //DAC CH0 인터럽트 플래그 0으로 셋팅
  }
  if (DAC_GetFlagStatus(DAC_FLAG_DOR1IF) ==  SET)
  {
    DAC_ClearFlag(DAC_FLAG_DOR1IF); //DAC CH1 인터럽트 플래그 0으로 셋팅
  }
}

인터럽트 부분 설명입니다.

 

현재 HT32 Codeconfig에서 정상적으로 만들어 주지 못한다.

DAC Sine wave는 다시 올리겠습니다.

 

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사 예제 프로그램을 사용해서 Motor Control Timer (MCTM0)를 사용하여 PWM 출력을 확인해 보자.

사용자 메뉴얼 보면 MCTM으로 검색하면 위와 같은 그림이 있다.

3상 BLDC Motor를 구동하기 위한 기능은 모두 있는거 같다.

example -> MCTM -> ComplementaryOutput 폴더에가서 _CreateProject.bat를 실행 해서 프로젝트를 만들자.

프로젝트가 만들어지면 MDK_ARMv5 폴더에 들어가서 프로젝트를 실행 하자.

 

int main(void)
{
  MCTM_Configuration(); //MCTM0 셋팅

  while (1);
}

main에는 달랑 2줄 써있다.

 

다음은 중요한 타이머 셋팅 부분이다.

void MCTM_Configuration(void)
{
  /* !!! 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.
  */
  TM_TimeBaseInitTypeDef MCTM_TimeBaseInitStructure;
  TM_OutputInitTypeDef MCTM_OutputInitStructure;
  MCTM_CHBRKCTRInitTypeDef MCTM_CHBRKCTRInitStructure;

  CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
  CKCUClock.Bit.AFIO       = 1; //AFIO Clock 공급
  CKCUClock.Bit.MCTM0      = 1; //MCTM0 Clock 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //AHB, APB, AFIO, MCTM0에 클럭 공급 셋팅 하라는것.

  /* Configure MCTM Channel 0 output pin                                                                    */
  AFIO_GPxConfig(HTCFG_MCTM_CH0_GPIO_ID, HTCFG_MCTM_CH0_AFIO_PIN, AFIO_FUN_MCTM_GPTM);  //PA14번 핀을 MCTM0에 CH0 PWM으로 동작하게함.
  AFIO_GPxConfig(HTCFG_MCTM_CH0N_GPIO_ID, HTCFG_MCTM_CH0N_AFIO_PIN, AFIO_FUN_MCTM_GPTM);    //PA15번 핀을 MCTM0에 CH0N PWM으로 동작 하게함.
  /* Configure MCTM Channel 1 output pin                                                                    */
  AFIO_GPxConfig(HTCFG_MCTM_CH1_GPIO_ID, HTCFG_MCTM_CH1_AFIO_PIN, AFIO_FUN_MCTM_GPTM);  //PB0번 핀을 MCTM0에 CH0 PWM으로 동작하게함.
  AFIO_GPxConfig(HTCFG_MCTM_CH1N_GPIO_ID, HTCFG_MCTM_CH1N_AFIO_PIN, AFIO_FUN_MCTM_GPTM);    //PB1번 핀을 MCTM0에 CH0N PWM으로 동작 하게함.
  /* Configure MCTM Channel 2 output pin                                                                    */
  AFIO_GPxConfig(HTCFG_MCTM_CH2_GPIO_ID, HTCFG_MCTM_CH2_AFIO_PIN, AFIO_FUN_MCTM_GPTM);  //PD1번 핀을 MCTM0에 CH0 PWM으로 동작하게함.
  AFIO_GPxConfig(HTCFG_MCTM_CH2N_GPIO_ID, HTCFG_MCTM_CH2N_AFIO_PIN, AFIO_FUN_MCTM_GPTM);    //PD2번 핀을 MCTM0에 CH0N PWM으로 동작 하게함.
  /* Configure MCTM Break pin                                                                               */
  AFIO_GPxConfig(HTCFG_MCTM_BREAK_GPIO_ID, HTCFG_MCTM_BREAK_AFIO_PIN, AFIO_FUN_MCTM_GPTM);  //PB4번 핀을 MCTM0에 Break 핀으로 연결 이핀에 신호가 들어오면 PWM 모두 정지 하고 LOW 신호를 출력한다.

  /* MCTM Time Base configuration                                                                           */
  MCTM_TimeBaseInitStructure.CounterReload = HTCFG_MCTM_RELOAD - 1; //HTCFG_MCTM_RELOAD값이 60000000/2000 이라고 되어 있다. (CRR 값임.) 60000000값은 MCTM Count Clock값이고 2000은 MCTM Reload 값이다. 이렇게 셋팅하면 주파수가 2KHz가 나옴.
  MCTM_TimeBaseInitStructure.Prescaler = 0; //PSC Prescaler값이다. 클럭이나 트리거 신호를 받았을때 이값이 0이 아니면 해당하는 숫자(Prescaler + 1)값 만큼 나누어져서 출력이 나온다.
  MCTM_TimeBaseInitStructure.RepetitionCounter = 0; //One Plus 방식이 아니므로 값은 0로 설정
  MCTM_TimeBaseInitStructure.CounterMode = TM_CNT_MODE_UP;  //카운트 방식 설정, 현재 증가 카운터로 설정함.
  MCTM_TimeBaseInitStructure.PSCReloadTime = TM_PSC_RLD_IMMEDIATE;  //소프트웨어적으로 트리거를 설정 할수 있는데 즉시 적용하는것으로 설정 (Update event 발생시에 적용할수도 있다.)
  TM_TimeBaseInit(HT_MCTM0, &MCTM_TimeBaseInitStructure);   //MCTM0 타이머 설정

  /* MCTM Channel 0, 1, 2 output configuration                                                              */
  MCTM_OutputInitStructure.Channel = TM_CH_0;   //MCTM0에 CH0을 뜻한다.
  MCTM_OutputInitStructure.OutputMode = TM_OM_PWM1; //PWM 출력 방식은 PWM1 방식으로 출력 한다.
  MCTM_OutputInitStructure.Control = TM_CHCTL_ENABLE;   //MCTM0에 CH0 출력을 사용 하게 한다.
  MCTM_OutputInitStructure.ControlN = TM_CHCTL_ENABLE;  //MCTM0에 CH0N 출력을 사용 하게 한다.
  MCTM_OutputInitStructure.Polarity = TM_CHP_NONINVERTED;   //High 또는 Rising Edge로 설정
  MCTM_OutputInitStructure.PolarityN = TM_CHP_NONINVERTED;  //High 또는 Rising Edge로 설정
  MCTM_OutputInitStructure.IdleState = MCTM_OIS_LOW;    //동작 중이 아닐때 CH0는 Low를 출력 한다.
  MCTM_OutputInitStructure.IdleStateN = MCTM_OIS_HIGH;  //동작 중이 아닐때 CH0N은 High를 출력 한다.
  MCTM_OutputInitStructure.Compare = HTCFG_MCTM_RELOAD * 3 / 4; //MCTM0에 CH0CCR값과 비교 값  (CH0 : 75%, CH0N : 25%)
  MCTM_OutputInitStructure.AsymmetricCompare = 0;   //MCTM0 CH0가 비대칭 PWM 모드로 구성되고 카운트다운 중일때 AsymmetricCompare값과 비교 된다고 한다..
  TM_OutputInit(HT_MCTM0, &MCTM_OutputInitStructure);   //MCTM0에 CH0,CH0N 셋팅

  MCTM_OutputInitStructure.Channel = TM_CH_1;   //MCTM0에 CH1을 뜻한다.
  MCTM_OutputInitStructure.Compare = HTCFG_MCTM_RELOAD * 1 / 2; //MCTM0에 CH1CCR값과 비교 값  (CH1 : 50%, CH1N : 50%)
  TM_OutputInit(HT_MCTM0, &MCTM_OutputInitStructure);   //MCTM0에 CH1, CH1N 셋팅

  MCTM_OutputInitStructure.Channel = TM_CH_2;   //MCTM0에 CH2을 뜻한다.
  MCTM_OutputInitStructure.Compare = HTCFG_MCTM_RELOAD * 1 / 4; //MCTM0에 CH2CCR값과 비교 값  (CH2 : 25%, CH2N : 75%)
  TM_OutputInit(HT_MCTM0, &MCTM_OutputInitStructure);   //MCTM0에 CH2, CH2N 셋팅

  /* MCTM Off State, lock, Break, Automatic Output enable, dead time configuration                          */
  MCTM_CHBRKCTRInitStructure.OSSRState = MCTM_OSSR_STATE_ENABLE;    //0x00200000
  MCTM_CHBRKCTRInitStructure.OSSIState = MCTM_OSSI_STATE_ENABLE;    //0x00100000
  MCTM_CHBRKCTRInitStructure.LockLevel = MCTM_LOCK_LEVEL_2; //0x00020000
  MCTM_CHBRKCTRInitStructure.Break0 = MCTM_BREAK_ENABLE;    //MCTM0에 Break0를 사용한다고함.
  MCTM_CHBRKCTRInitStructure.Break0Polarity = MCTM_BREAK_POLARITY_LOW;  //Break신호가 Low가 들어오면 MCTM0가 정지한다.
  MCTM_CHBRKCTRInitStructure.AutomaticOutput = MCTM_CHAOE_DISABLE;   //Break 신호가 Low 값이 들어와서 출력이 안나오다가 Break 신호가 High 신호가 들어오면 정상동작을 해라.
  MCTM_CHBRKCTRInitStructure.DeadTime = HTCFG_MCTM_DEAD_TIME;   //CHx와 CHxN간에 동시에 변화 하지 않고 HTCFG_MCTM_DEAD_TIME값 만큼 지연시간을 준다.
  MCTM_CHBRKCTRInitStructure.BreakFilter = 0;   //Break 입력 필터 셋팅으로 값이 0이면 필터를 사용하지 않음.
  MCTM_CHBRKCTRConfig(HT_MCTM0, &MCTM_CHBRKCTRInitStructure);   //필터 설정

  /* MCTM counter enable                                                                                    */
  TM_Cmd(HT_MCTM0, ENABLE);     //MCTM0 카운터 동작함.

  /* MCTM Channel Main Output enable                                                                        */
  MCTM_CHMOECmd(HT_MCTM0, ENABLE);  //MCTM0에 채널 동작함.
}

위 프로그램을 실행후 출력 파형은 다음과 같다.

위에 파형사진에서 위쪽 파형이 PA14번 포트에서 측정 한 MCTM0에 CH0 파형이다. 2KHz에 약 74.7%가 잘 나온다.

아래쪽 파형은 PA15번 포트에서 측정한 MCTM0에 CH0N 파형이다. 2KHz에 약 24.7%가 나오는것을 확인 할수 있다.

정확히 75%나 25%가 안나오는 이유는 PWM Dead Time이 포함 되어 있기 때문이다. 프로그램상에 90만큼 Dead Time이 설정 되어 있다.

위에 파형사진에서 위쪽 파형이 PB0번 포트에서 측정 한 MCTM0에 CH1 파형이다. 2KHz에 약 49.7%가 잘 나온다.

아래쪽 파형은 PB2번 포트에서 측정한 MCTM0에 CH1N 파형이다. 2KHz에 약 49.7%가 나오는것을 확인 할수 있다.

정확히 50%나 50%가 안나오는 이유는 PWM Dead Time이 포함 되어 있기 때문이다. 프로그램상에 90만큼 Dead Time이 설정 되어 있다.

위에 파형사진에서 위쪽 파형이 PD1번 포트에서 측정 한 MCTM0에 CH2 파형이다. 2KHz에 약 24.7%가 잘 나온다.

아래쪽 파형은 PD2번 포트에서 측정한 MCTM0에 CH2N 파형이다. 2KHz에 약 74.7%가 나오는것을 확인 할수 있다.

정확히 25%나 75%가 안나오는 이유는 PWM Dead Time이 포함 되어 있기 때문이다. 프로그램상에 90만큼 Dead Time이 설정 되어 있다.

위에 파형은 MCTM0에 CH0과 CH1을 같이 측정한 사진이다.

CH0는 약 75%, CH1은 약 50% 나오는것을 확인 할수 있다.

위에 파형은 MCTM0에 CH0과 CH2을 같이 측정한 사진이다.

CH0는 약 75%, CH2은 약 25% 나오는것을 확인 할수 있다.

 

ComplementaryOutput.zip
5.04MB

728x90
반응형
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) 에 있는 Vector Table Offset을 사용해 보자.

 

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

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

 

int main(void)
{
  /* Initialize LEDs                                                                                        */
  HT32F_DVB_LEDInit(HT_LED1); //LED1 Port Setting
  HT32F_DVB_LEDInit(HT_LED2); //LED2 Port Setting
  HT32F_DVB_LEDInit(HT_LED3); //LED3 Port Setting

  InitVector(); //Vector 변경 설정

  // Must be 64 word (256 Bytes) aligned, 0x00 (0), 0x100 (256), 0x200 (512)
  NVIC_SetVectorTable(NVIC_VECTTABLE_RAM, VECTOR_BASED_ADDRESS); //Vector주소가 Flash에서 Ram영역으로 변경

  /* Generate SysTick Interrupt                                                                             */
  SysTick_Config(0xFFFFFF); //SYSTICK 설정

  while (1);
}

main에 대한 해석이다.

 

void InitVector(void)
{
  s32 i = 0;

  for( i = TOTAL_VECTOR - 1; i >= 0; i--)
  {
    RAMVector[i] =  rw(i * 4); //Byte씩 Ram영역으로 데이터 전송
  }

  RAMVector[SYSTICK_VECTOR_COUNT] = (u32)&SysTick_HandlerExtra; //SysTick_HandlerExtra 펑션을 RAM Vector로 전송
}

 

InitVector 펑션에 대한 설명이다.

 

void SysTick_HandlerExtra(void)
{
  /* Toggle LEDs */
  HT32F_DVB_LEDToggle(HT_LED1); //LED1 포트 토글
  HT32F_DVB_LEDToggle(HT_LED2); //LED2 포트 토글
  HT32F_DVB_LEDToggle(HT_LED3); //LED3 포트 토글
}

 

SysTick_HandlerExtra 펑션에 대한 설명이다.

 

이번 프로그램은 Keil에서 F10키를 눌러 한단계씩 실행하다 Vector 주소가 Ram 영역으로 넘어가면 그냥 실행 된다.

동작은 LED1, 2가 깜빡 거린다.

 

 

Vector_Table_Offset.zip
4.86MB

 

 

 

 

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
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 예제 프로그램을 이용하여 WDT (Watchdog Timer)를 사용해 보자.

 

와치독 타이머는 MCU 사용할때 특별한 사유가 없으면 항상 사용해주는것이 좋다.

MCU가 갑자기 멈추거나 프로그램에서 버그가 있어서 무한 루프로 빠지거나 할때 일정 시간안에 카운터를 초기화 안해주면  Reset을 걸어서 다시 시작 할수 있도록 해준다.

example -> WDT -> Auto_Enable 폴더에 _CreateProject.Bat를 실행하여 소스가 만들어지면 MDK_ARMv5폴더에서실행파일을 실행해 주자.

F7눌러 Build 해주고 Ctrl+F5를 눌러 디버깅 모드로 들어간후 천천히 F10키를 여러번 눌러 실행하면 LED2이 깜빡이는것을 확인 할수 있다.

이때 EVM에 하드웨어 리셋을 누르면 LED1이 점등 한다.

int main(void)
{
  /* Enable WDT APB clock                                                                                   */
  CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  CKCUClock.Bit.WDT = 1; //와치독 타이머에 클럭 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //클럭 셋팅

  RETARGET_Configuration();           /* Retarget Related configuration                                     */
  HT32F_DVB_LEDInit(HT_LED1); //LED1 Port Setting
  HT32F_DVB_LEDInit(HT_LED2); //LED2 Port Setting

  if(RSTCU_GetResetFlagStatus(RSTCU_FLAG_WDTRST) == SET) //MCU가 무엇때문에 리셋이 되었는지 확인.
  {
    /* WDT generates a reset request and then turns on LED2.                                                */
    HT32F_DVB_LEDOn(HT_LED2); //MCU가 와치독 때문에 리셋되었다면 LED2를 켜라.
  }
  else
  {
    /* Other functions generate a reset request and then turns on LED1.                                     */
    HT32F_DVB_LEDOn(HT_LED1); //MCU가 와치독 때문에 리셋된것이 아니라면 LED1을 켜라.
  }
  RSTCU_ClearAllResetFlag();          /* Clear reset flag                                                   */ //MCU에 저장되어 있는 리셋 플래그를 삭제

  /* Enable the Auto_WDT                                                                                    */
  if(AutoWDT_Cmd(ENABLE) == ERROR) //와치독을 켜고 에러가 없는지 확인
  {
    /* Fail, Turn off LED1 and LED2.                                                                        */
    HT32F_DVB_LEDOff(HT_LED1); //와치독을 켜고 에러가 발생되면 LED1 Off
    HT32F_DVB_LEDOff(HT_LED2); //와치독을 켜고 에러가 발생되면 LED2 Off
  }

  while (1)
  {
    WDT_Restart();          /* Reload Counter as WDTV Value                                                 */ //와치독 카운터를 초기화 해라.
  }
}

LED2가 점등되는 상황이 잘 안나온다면 디버깅 모드를 나간후 다시 들어와서 실행하지 않고 약 8초 정도 기다려 주면 LED2가 점등 되는것을 확인 할수 있다. 이때 EVM에 Reset 버튼을 누르면 LED1이 점등 된다.

Auto_Enable.zip
4.87MB

728x90
반응형
728x90
반응형

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

사용자 메뉴얼에 보면 나와 있는 부분이다.

 

BOD (Brown Out Detect)란?

MCU 인가 전압이 순간 흔들려서 일정 전압 이하로 떨어지면 일정 전압 이상 될때까지 MCU를 Reset 시켜주는 기능

 

LVD (Low Voltage Detection)란?

초기 MCU 인가 전압이 일정 전압 이하일경우 MCU를 RESET 시켜 주는 기능

 

위 기능을 사용하는 이유는 MCU동작 보다 다른 주변 장치가 전원이 먼저 들어가서 정상 동작하는데 유리하다.

만약 MCU가 먼저 동작을 하고 있는데 주변 장치가 동작을 하면 MCU가 제어하는데 오류가 발생 할수 있다.

 

위 기능이 있는 MCU는 기능을 사용하여 제품 신뢰성을 높이도록 하자.

 

example -> PWRCU -> BOD_LVD 폴더에 _CreateProject.Bat를 실행하여 소스가 만들어지면 MDK_ARMv5폴더에서실행파일을 실행해 주자.

F7눌러 Build 해주고 Ctrl+F5를 눌러 디버깅 모드로 들어간후 F5키를 눌러 실행하면 LED1이 깜빡이는것을 확인 할수 있다.

EVM Kit에서 확인 하기 위해서는 USB를 제거하고 외부에서 3.3V 전원을 보드에 직접 인가후 전압을 내려봐야 하는데

현재 여건이 안되어서 프로그램 설명만 넣고 마무리 함. USB 케이블을 빠르게 살짝 뺏다 껴면 LED2가 켜지는것을 확인 할수도 있다.

int main(void)
{
  /* Enable RTC clock                                                                                       */
  CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  CKCUClock.Bit.BKP        = 1; //APBCCR1 레지스터에 BKPREN (RTC Colock)을 1로 해서 RTC에 Clock 공급
  CKCU_PeripClockConfig(CKCUClock, ENABLE); //Clock Setting

  /* Wait for De-isolation, then backup domain could be accessed                                            */
  #if !defined(LIBCFG_NO_PWRCU_TEST_REG)
  if (PWRCU_CheckReadyAccessed() != PWRCU_OK) //현재 MCU 전원 상태를 읽어 오는 부분
  {
    while (1); //MCU 전원 상태가 이상하면 무한 루프에 걸림
  }
  #endif
  /* Init LED1, LED2 used to output state                                                                   */
  HT32F_DVB_LEDInit(HT_LED1); //LED1 Port Setting
  HT32F_DVB_LEDInit(HT_LED2); //LED2 Port Setting
  HT32F_DVB_LEDInit(HT_LED3); //LED3 Port Setting

  /* Enable NVIC LVD interrupt                                                                              */
  NVIC_EnableIRQ(LVD_BOD_IRQn); //LVD_BOR 인터럽트를 활성화 시켜줌

  /* Enable BOD reset. For the BOD voltage, please refer to the datasheet.                                  */
  PWRCU_BODRISConfig(PWRCU_BODRIS_RESET); //BODRIS Bit를 Reset하라는 명령 (MCU 인가 전압이 이상하면 RESET 하라는 명령)
  PWRCU_BODCmd(ENABLE); //Brown-Out 감지 하라는 명령

  /* Enable LVD. The LVD level is configured around 3.0V.
     The interrupt service routine will toggle LED2 till the VDD33 above 3.0V */
  PWRCU_SetLVDS(HTCFG_PWRCU_LVDS); //MCU에 공급 되는 전압이 2.95V가 되면 LVD가 활성화 된다.
  PWRCU_LVDIntWakeupConfig(ENABLE); //MCU에 공급 되는 전압이 2.95V가 되면 인터럽트가 발생 하라는 명령
  PWRCU_LVDCmd(ENABLE); //LVD 동작 하라는 명령

  /* Toggle LED1 in an infinite loop                                                                        */
  while (1)
  {
    HT32F_DVB_LEDToggle(HT_LED1); //LED1 점멸
    delay(1000000); //시간 지연
  }
}

 

Main 부분 프로그램 설명이다.

 

void LVD_BOD_IRQHandler(void)
{
  HT32F_DVB_LEDOff(HT_LED1); //LED1 꺼짐
  /* Wait till the VDD33 above HTCFG_PWRCU_LVDS */
  while (PWRCU_GetLVDFlagStatus() != RESET) //
  {
    HT32F_DVB_LEDOn(HT_LED2); //LED2 켜짐.
    delay(3000000); //지연시간
    HT32F_DVB_LEDOff(HT_LED2); //LED2 꺼짐.
    delay(3000000); //지연시간
  }
}

ht32f5xxxx_01_it.c 파일에 있는 LVD 와 BOD 가 해당할경우 실행하는 부분이다.

 

BOD_LVD.zip
4.87MB

 

 

728x90
반응형

'프로그램 > Holtek 32Bit' 카테고리의 다른 글

NVIC에 System_Exception 예제 실행  (0) 2023.08.05
WDT (Watchdog Timer) 예제 실행  (0) 2023.08.02
PWM 예제 실행  (0) 2023.08.02
Flash Program 예제 실행  (0) 2023.08.02
SYSTICK 예제 사용하기  (0) 2023.08.01
728x90
반응형

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

example -> TM -> PWM 폴더에 들어가서 _CreateProject.bat 실행

자동으로 프로젝트가 만들어지면 프로젝트 실행.

F7을 눌러서 Build한후 Ctrl+F5를 눌러 디버깅 모드로 들어간후 F10 키를 한번씩 누르면 한줄 한줄 실행이 됩니다.

화면상에 첫번째 Delay(500); 실행 단계일때 오실로 스코프로 파형을 관찰 해 보자.

  PWM_Init(); //PWM 초기 셋팅

  PWM_UpdateDuty(PWM_CH0, PWM_DUTY_50); //PWM CH0 듀티값 50% 셋팅
  PWM_UpdateDuty(PWM_CH1, PWM_DUTY_25); //PWM CH1 듀티값 25% 셋팅
  PWM_Cmd(ENABLE); //PWM 동작 시작

이부분을 실행 했을 경우 입니다.

스코프상에서 위에 선이 PWM CH0 파형이다. 화면 오른쪽에 보면 C1에 주파수가 50KHz 이고 Duty는 50%에 가까운것을 알수 있다.

스코프상에 아래 선이 PWM CH1 파형이다. 화면 오른쪽에 보면 C2에 주파수가 50KHz이고 Duty는 25%에 가까운것을 알수 있다.

Keil에서 F10키를 눌러 다음 Delay(500);까지 이동하자

  PWM_UpdateDuty(PWM_CH0, PWM_DUTY_0); //PWM CH0 듀티값 0% 셋팅 (Low 출력)
  PWM_UpdateDuty(PWM_CH1, PWM_DUTY_75); //PWM CH2 듀티값 75% 셋팅

이부분 실행 입니다.

PWM CH0는 LOW 뜨는것을 확인 할수 있으며 PWM CH1은 50KHz에 듀티는 75%에 셋팅된것을 확인 할수 있다.

화면상에 C1에 값이 나오는데 이부분은 노이즈에 의한 값으로 무시 해야 합니다.

Keil에서 F10키를 눌러 다음 Delay(500);까지 이동하자

  PWM_Cmd(DISABLE); //PWM 동작 정지

이부분 실행 입니다.

스코프 상에서 PWM이 꺼진것을 확인 할수 있다.

Keil로 가서 F5를 눌러 나머지를 모두 실행 합니다.

  PWM_SetFreq(PWM_FREQ_12K); //PWM 주파수 12KHz로 변경
  PWM_UpdateDuty(PWM_CH0, PWM_FREQ_12K * 0.25); //PWM CH0 듀티 25% 셋팅
  PWM_UpdateDuty(PWM_CH1, PWM_FREQ_12K * 0.75); //PWM CH1 듀티 75% 셋팅
  PWM_Cmd(ENABLE); //PWM 동작 시작

이부분 실행 입니다.

프로그램한데로 주파수는 12KHz로 변경 되었고 PWM CH0는 25%, PWM CH1은 75%로 측정 되는것을 확인 할수 있다.

PWM.zip
4.99MB

 

728x90
반응형
728x90
반응형

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

example -> FMC -> FLASH_Program 폴더에 들어가서 _CreateProject.bat 실행.

자동으로 프로젝트가 만들어지면 프로젝트 실행.

사용자 메뉴얼을 보면 위 표가 있다. Flash에 데이터를 지우고 쓸때는 Page 단위로만 가능하다. 즉 Page 254를 보면 Address가 0x0003_F800 ~ 0x0003_FBFF 까지 라고 되어 있는데 0x0003_F802 라는 하나에 주소만 삭제 하거나 쓸수는 없고 0x0003_F800 주소부터 0x0003_FBFF 주소까지 모두 한번에 지우고 써야 한다는 이야기 이다.

데이터를 쓸때는 꼭 먼저 지우고 써야 한다.

만약 변경 되면 안되는 데이터가 있다면 먼저 읽어와서 변수에 보관하다가 해당 영역을 지우고 쓸때 읽어온 데이터를 써줘야 한다.

프로그램 소스를 보면 main함수 위에 다음과 같이 선언되어 있다.

#define StartAddress    (1024 * 4) //Flash에 데이터 삭제 및 삽입 시작 주소 : 4096
#define EndAddress      (1024 * 8) //Flash에 데이터 삭제 및 삽입 마지막 주소 : 8192

#define TEST_DATA       (0x12345678) //Flash에 쓸 데이터 및 확인 데이터

메모리 영역에서 4096(4Kbyte) 만큼 쓰고 지우겠다는 이야기로 짐작된다.

int main(void)
{
  /* Erase Flash pages before program data                                                                  */
  FLASH_Erase(); //Flash에 해당 영역 삭제
  /* Program Word data                                                                                      */
  FLASH_Program(); //Flash에 데이터 쓰기
  /* Check Flash data                                                                                       */
  FLASH_Check(); //Flash에 쓴 데이터가 맞는지 확인
  if (err != 0)
  {
    while (1); /* Test Failed                                                                               */
  }

  while (1); /* Test Passed                                                                                 */
}

메인을 보면 한번만 실행 되게 되어 있는데 주의 할것은 무한 반복 하게 되면 MCU가 먹통이 될수 있으니 항상 주의 하자.

여기서 보게 되면

1. 지운다.

2. 데이터를 쓴다.

3. 확인한다.

위 순서로 되어 있는것을 알수 있다.

먼저 지우는 영역을 보면 다음과 같다.

void FLASH_Erase(void)
{
  u32 Addr;
  FLASH_State FLASHState;
  for (Addr = StartAddress; Addr < EndAddress; Addr += FLASH_PAGE_SIZE) //FLASH_PAGE_SIZE는 1024가 기본이다. Flash 영역 4096부터 8192까지 지워진다.
  {
    FLASHState = FLASH_ErasePage(Addr); //Flash 해당 영역 삭제 명령
    if (FLASHState != FLASH_COMPLETE) //만약 정상적으로 삭제가 안되었으면 err변수에 +1을 해주라는것.
    {
      err++;
    }
  }
}

삭제할때 FLASH_ErasePage(Addr); 명령으로 삭제를 하는데 Addr값은 1024단위로 시작 주소만 넣어주면 시작주소부터 1024Byte가 삭제 된다.

void FLASH_Program(void)
{
  u32 Addr;
  FLASH_State FLASHState;
  for (Addr = StartAddress; Addr < EndAddress; Addr += 4) //word(4Byte) 단위로 쓰기 주소가 증가 한다.
  {
    FLASHState = FLASH_ProgramWordData(Addr, TEST_DATA); //1024주소부터 4Byte씩 데이터를 삽입한다.
    if (FLASHState != FLASH_COMPLETE) //데이터 삽입이 정상 적으로 안되면 err변수에 +1을 해준다.
    {
      err++;
    }
  }
}

Flash에 데이터를 삽입 하는 부분이다.

FLASH_ProgramWordData(Addr, TEST_DATA); 이부분이 데이터를 쓰는 부분인데 Addr에 데이터를 넣을 주소를 넣고 TEST_DATA자리에 4Byte에 데이터를 넣어주면 된다. 혹 1Byte만 데이터를 넣겠다 하면 변수는 4Byte이나 데이터만 1Byte를 넣어 주면 된다.

void FLASH_Check(void)
{
  u32 Addr;

  for (Addr = StartAddress; Addr < EndAddress; Addr += 4) //word(4Byte) 단위로 시작 주소가 증가 한다.
  {
    if (rw(Addr) != TEST_DATA) //Flash에 Addr주소부터 4Byte를 읽어 와서 TEST_DATA와 같은지 확인을 하고 다르면 err변수에 +1을 해준다.
    {
      err++;
    }
  }
}

Flash에 삽입한 데이터가 맞는지 확인 하는 부분이다. 만약 삽입한 데이터가 다르면 err값이 증가 한다.

디버깅 모드로 확인을 해보겠다.

Keil에서 F7을 눌러 Build를 해주고 Ctrl+F5 키를 눌러 디버깅 모드로 들어가자

오른쪽 하단에 Memory1 글씨를 눌러서 Address: 글씨 옆에 0x1000이라고 넣어준다. 만약 위 화면처럼 모두 FF로 표시 되면 삭제 되었는지 확인이 안되기 때문에 F5를 눌러서 데이터를 넣어주고 Ctrl+F5를 눌러 디버깅 모드를 종료 한다.

 

다시 Ctrl+F5를 눌러 디버깅 모드로 들어가면 위 화면 처럼 데이터가 삽입 되어 있는것을 알수 있다.

여기서 부터는 F11키와 F10키를 반복적으로 눌러 가면서 확인을 해야 한다.

F11키를 한번씩 누르면 FLASH_ErasePage(Addr); 명령이 실행 될때마다 1024Byte씩 삭제 되는것을 확인 할수 있다.

삭제가 모두 완료 되면 FLASH_ProgramWordData(Addr, TEST_DATA); 이부분에서 4Byte씩 데이터가 삽입 되는것을 확인 할수 있다.

 

FLASH_Program.zip
4.83MB

 

 

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek 사에 예제 프로그램을 이용하여 SYSTICK (System Tick Time)을 사용해 보자.

example -> SYSTICK -> Period_DownCounting 폴더에 들어가서 _CreateProject.bat를 실행하자.

자동으로 프로젝트가 만들어지면 프로젝트 실행.

회로도에는 LED가 3개 있지만 제어 가능한것은 2개 인것을 알고 있다.

PE3, PA6에 LED가 연결 되어 있고 하나는 Power 인가시 들어오는 LED로 알고 있다.

현재 프로그램상에서 3개로 표시 되어 있는데 확인을 위해 HT_LED1을 더블 클릭후 F12를 클릭 하여 선언된 곳으로 가보자.

선언된 곳으로 가니 HT_LED1 = 0, 이라고 되어 있는 부분이다.

조금 위에 보면 선언된 문장을 보고 다음과 같은지 확인 하고 다르다면 변경해주자.

#define LED1_GPIO_ID                (GPIO_PE)
#define LED1_GPIO_PIN               (GPIO_PIN_3)
#define LED1_AFIO_MODE              (AFIO_FUN_GPIO)

#define LED2_GPIO_ID                (GPIO_PA)
#define LED2_GPIO_PIN               (GPIO_PIN_6)
#define LED2_AFIO_MODE              (AFIO_FUN_GPIO)

#define LED3_GPIO_ID                (GPIO_PB)
#define LED3_GPIO_PIN               (GPIO_PIN_7)
#define LED3_AFIO_MODE              (AFIO_FUN_GPIO)

 

LED3_GPIO_ID는 Port B로 연결 되어 있으니 LED 켜지고 꺼지는것과는 관계가 없음을 생각할수 있다.

SYSTICK_SetReloadValue(SystemCoreClock / 8 / 1000); // (CK_AHB/8/1000) = 1ms on chip

이부분에서 8이 들어간 이유는 Datasheet를 보고 확인 할수 있다.

Datasheet를 보면 Systick Clock은 CK_AHB 클럭에 8로 나눈값으로 동작 한다는것을 알수 있다.

Delay(500); 이 실행 되는 문장 설명함.

void Delay(u32 nTime) 펑션에있는 DelayTime이 어디서 0이 되게 해주는지 나와 있는 부분임.

ht32f5xxxx_01_it.c 파일 밑에 보면 void SysTick_Handler(void) 펑션에 TimingDelay 펑션을 실행 해주는 부분이 있다.

SysTick_Handler펑션은 1msec마다 실행 하게 앞에서 설정 했다.

Ctrl + F5를 눌러 디버깅 모드에 들어간후 F5를 눌러서 실행을 하자.

 

 

 

Period_DownCounting.zip
4.85MB

LED가 500msec마다 깜빡이는것을 확인 할수 있다.

 

 

 

 

728x90
반응형
728x90
반응형

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

사용자 메뉴얼에 PDMA라고 설명 되어 있는 부분이다.

대충 주변 장치에서 메모리로, 메모리에서 주변 장치로, 메모리에서 메모리로 데이터 전송이 된다고 한다.

그리고 독립적으로 동작을 한다고 하며 6개에 단방향 채널을 가지고 있다고 함.

연결 할수 있는 주변 장치는 위와 같다.

위 표를 보고 전에 했던 프로젝트들이 생각이 났다. DAC는 없네..

다운 받은 예제 파일중에 PDMA 폴더에 SoftwareTriger 폴더를 들어갑니다.

_CreateProject.bat를 실행 합니다.

MDK_ARMv5 폴더에 들어가서 Project_52367 Keil 파일을 더블 클릭 하여 실행 합니다.

주석을 확인 해주세요.

Ctrl + F5를 눌러서 디버깅 모드로 갑니다.

화면을 조금 내려서 PDMACH_InitStructure.PDMACH_SrcAddr   = (u32)(&PdmaCh0SrcBuf[0]); 이부분에서 PdmaCh0SrcBuf에 마우스 왼쪽버튼을 두번 클릭한후 선택하고 바로 마우스 오른쪽 버튼을 눌러서 위 사진처럼 Watch1에 넣어 주시기 바랍니다.

바로 밑에 PdmaCh0DstBuf도 동일한 방법으로 Watch1에 추가 해주세요.

눈으로 보기 편하기 위해서 Watch1 창 위를 마우스 왼쪽 버튼을 클릭 한 상태에서 움직이면 별도로 움직일수 있습니다. 보기 편하게 이동후 PdmaCh0SrcBuf, PdmaCh0DstBuf 앞에 +버튼을 클릭하여 모두 보이게 합니다.

아직 실행을 안해서 PdmaCh0SrcBuf에는 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08이 들어있고

PdmaCh0DstBuf에는 모두 0X00인것을 확인 할수 있다.

빠른 확인을 위해 사진을 보면 PDMA_SwTrigCmd(PDMA_CH0, ENABLE); 부분에 마우스 클릭 한번한후 F9 키를 누르면

앞에 빨간색에 원형 마크가 하나 생긴다.  Break Point 라고 하는것을 설정 한것이다.

F5키를 눌러 실행하자.

빨간 원형 포인트 위에 화살표가 생겼다. 다음 실행할 문장이라는 표시이다.

Watch1 창을 보면 데이터는 변경 된것이 없이 그대로 이다.

F10 키를 누르면 한줄이 실행 되고 Watch1 창에 데이터가 변경 된것을 확인 할수 있다.

SoftwareTrigger.zip
4.84MB

728x90
반응형
728x90
반응형

도구 -> NuGet 패키지 관리자 -> 솔루션용 NuGet 패키지 관리 클릭

찾아보기에서 Microsoft.office 입력후 검색누르면 Microsoft.Office.Interop.Excel이 나옴

Microsoft.Office.Interop.Excel 클릭하고 오른쪽에 프로젝트 체크후 설치 누르면 됨.

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해서 USB로 데이터 보낸것을 UART로 데이터가 맞게 오는지 확인 및

UART로 보낸 데이터가 USB로 맞게 오는지 확인 해보자.

 

앞에서 USB Port로 데이터를 보내서 USART 포트로 데이터를 받았다.

이번에는 반대로 USART 포트로 데이터를 보내서 USB Port로 데이터를 수신 합니다.

ht32_usbd_class.c파일에서 skip 해주었던 //USBDCore_EPTWriteINData(USBD_EPT1, (u32 *)gInputDataBuffer, gEP3Len);

이부분을 복사합니다.

USART1.C 파일에 수신 인터럽트 부분에

USBDCore_EPTWriteINData(USBD_EPT1, (u32 *)rxd_scomm1.buffer, rxd_scomm1.write_pt);
rxd_scomm1.write_pt = 0;

이렇게 넣어 줍니다.

그리고 F7을 눌러 Build 해주면 에러가 발생할것입니다.

Error: L6218E: Undefined symbol USBDCore_EPTWriteINData (referred from usart1.o).

에러 내용을 보면 선언이 안되어 있다고 나옵니다.

USART1.C 파일 위에 그림과 같이 #include "ht32_usbd_core.h" 를 추가 하고 Build를 하면 에러가 없다고 나옵니다.

Ctrl + F5를 눌러 디버깅 모드에 들어간후 F5를 눌러 바로 실행 합니다.

 

ComPortMaster를 실행하여 Com10을 Open port를 클릭 합니다.

ComPortMaster를 하나 더 실행하여 COM3을 Open port 클릭 합니다.

Send 버튼을 눌러서 TEST가 COM10에서 나오는지 확인 합니다.

COM10에서 TEST가 나오는것을 확인 할수 있습니다.

 

반대로 COM10에서 Send버튼을 누르면 COM3에서 나오는것을 확인 할수 있습니다.

HT32F52367_LQFP80_3_USBCDCtoUART2.zip
6.21MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해서 USB로 데이터 보낸것을 UART로 데이터가 맞게 오는지 확인 및

UART로 보낸 데이터가 USB로 맞게 오는지 확인 해보자.

EVM Board로 데이터를 주고 받기 위해 PA4, PA5를 UART1으로 설정한다.

MISC에서 USB를 CDC로 설정 한다.

Generate Code (F7)을 눌러 파일을 만든다.

Keil 프로그램 실행 파일을 눌러 프로젝트를 실행한다.

 

위와 같이 main.c가 있다.

ht32_usbd_class.c 파일에 들어가면 static void USBDClass_EPT1INProcess(void) 부분에서 수정을 해주자.

USART1.C에 들어가서 아래로 내려가면 void USART1_tx_data(u8 *pt, u8 len) 이 부분이 UART1 TX 인터럽트를 통해 보내주는 부분이다. 이것을 이용해서 USB에서 받은 값을 UART로 보내줄수 있다.

ht32_usbd_class.c 파일로 가서 USBDCore_EPTWriteINData(USBD_EPT1, (u32 *)gInputDataBuffer, gEP3Len); 이부분 앞에 //를 넣어서 skip해준다음 USART1_tx_data(gInputDataBuffer, gEP3Len); 이부분을 추가 해준다.

그리고 Build (F7) 하면 아래와 같은 경고가 발생한다.

..\ht32_usbd_class.c(147): warning:  #223-D: function "USART1_tx_data" declared implicitly
   USART1_tx_data(gInputDataBuffer, gEP3Len); //USART1으로 전송
..\ht32_usbd_class.c: 1 warning, 0 errors

 

USART1_tx_data 이 암시적으로 선언 되었다고 나온다.

ht32_usbd_class.c 파일 제일 위에 #include "USART1.h" 글씨를 추가 해주고 Build 해주면  에러 및 경고가 없다고 나온다.

Ctrl + F5 키를 눌러 디버깅 모드로 들어간후에 F5키를 눌러 실행.

ComPortMaster를 실행하여 위와 같이 Device와 Baudrate를 설정후 Open port를 눌러 열어주고 DTR을 선택해주자.

COM3는 USART 데이터 임.

 

ComPortMaster를 하나 더 실행하여 위와같이 설정후 test 글씨를 넣고 Send를 클릭하자

COM3 Port로 test 글씨가 수신 된것을 확인 할수 있다.

HT32F52367_LQFP80_3_USBCDCtoUART1.zip
6.20MB

 

 

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해서 UART (Universal Asynchronous Receiver/Transmitter) / USART (Universal Synchronous/Asynchronous Receiver/Transmitter) 를 사용해 보자.

데모 키트 회로도에 보면 Debug Interface가 있다.

PA5와 PA4를 UART로 변경 해주자.

HT32_CodeConfig창에서 AFIO 글씨를 클릭하여 PA4, PA5를 USR1_TX, USR1_RX칸을 각각 더블클릭하자

새로 생긴 UART/USART 창에 가서 확인 한번 하고 F7를 눌러 Generator Code를 해주자.

새로 생긴 폴더 이름에 UART라고 표시를 했다.

//USART1_test(); //Can be removed 이문장에서 제일 앞에 //를 삭제 하자.

F7을눌러 Build 한후 Ctrl + F5 키를 눌러 디버깅 모드로 실행하자.

디버깅 모드로 들어왔으면 F5키를 눌러 실행하자.

전시간에 했던 테라텀을 이용하려고 했는데 잘 안되어서 ComPortMaster로 변경했다.

ComPortMaster를 다운 받아서 설치 하기 바랍니다.

Device를 COM3로 변경해주고 Baudrate를 115200으로 변경후 Open port를 눌러주자. 아무 반응이 없을것이다.

왼쪽에 DTR을 체크 하면 화면처럼 이상한 그림이 나오는것을 확인 할수 있다.

ASCII라고 쓰여 있는 버튼을 한번 눌러 Hex로 변경 하면 숫자가 나오는것을 확인 할수 있다.

현재 MCU에서 보내주는 신호값이다.

혹시 데이터가 안올라 오는 분은 아래 사진을 보면 JUMPER가 오른쪽 2개에 연결 되어 있다면 왼쪽 2개로 이동을 해주어야 한다.(DAP_Tx, PA5 에 연결)

HT32F52367_LQFP80_2_UART.zip
5.65MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해서 USB CDC (Universal Serial Bus Communication Device Class) 기능을 사용해 보자.

내부 클럭을 이용하고 USB 포트를 CDC 기능으로 설정해서 만들어보자.

화면에 MISC 글씨를 클릭후 Enable USB를 체크해준후 CDC를 선택

Generate Code를 눌르자

원하는 위치를 선택후 확인을 누르자

다른 프로젝트와 헛갈릴수 있어서 뒤에 이름을 변경 해 주었다.

전체 이름을 변경해도 관계는 없다.

장치 관리자 가서 포트 부분에 COM3포트가 잡혀 있는것을 확인 할수 있다. 이것은 Holtek 디버깅 포트에서 잡아주는 COM Port 이다.

Keil 프로젝트 파일이 있는곳에 가서 실행을 해주자.

 

실행후 F7을 눌러 Build 한후에 바로 Ctrl+F5를 눌러 실행하자

PC에서 장치가 잡혔다는 메시지가 뜨고 장치 관리자 가서 포트를 보면 COM10이라는 USB 직렬 장치가 잡혀 있는것을 확인 할수 있다.

디버깅 모드에서 확인을 하면 ht32_usbd_class.c 파일에

static void USBDClass_EPT1INProcess(void)

펑션에서 받은데이터를 다시 보내주는것을 확인 할수 있다.

HT32F52367_LQFP80_2_USBtoCDC.zip
6.06MB

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용하여 외부 Crystal을 사용해보자.

표시된 부분을 체크 및 선택 하면 외부 크리스탈 이용으로 변경 됩니다.

HSE에 주파수는 4MHz ~ 16MHz 까지 변경이 가능하나

LSE는 32.768KHz로 고정 되어서 변경이 불가능 하다.

 

 

선택후 Generate Code(F7)를 하게 되면 폴더 찾아보기가 나온다. 한번 했으면 경로가 저장 되면 좋은데 이 프로그램은 항상 찾아서 선택 해 주어야 한다.

 

CodeConfig 폴더 선택후 확인을 눌렀다.

 

 

위 그림을 보면 알겠지만 프로젝트가 덮어 써지는것이 아니라 새로 폴더를 만든후 새 프로젝트를 만드는것을 확인 했다.

프로그램을 실행후 main.c 파일을 열어 보았더니 화면과 같이 나와 있었다.

//Generated by HT32CodeConfig V1.0.2 Build 230411
//-----------------------------------------------------------------------------

#include "ht32.h"
#include "BFTM0.h"

//-----------------------------------------------------------------------------
int main(void)
{
  BFTM0_Configuration();

  while (1)
  {
    if(HT_CKCU->APBCCR1 & (1 << 4))
      WDT_Restart();

  }
}

 

우리는 HT32CodeConfig에서 BFTM0, 와치독 등등 설정한 적이 없는데

기본적으로 와치독 리셋과 BFTM0가 기본적으로 셋팅 되어 있다.

APBCCR1이 무엇인지 확인은 HT32F52357_67_UserManual에 나와 있다.

APBCCR1으로 검색하면 위와 같이 나와 있다.

이중 (1 << 4) 이므로 WDTREN Bit 임을 알수 있다.

좀더 내려서 확인을 하면 Watchdog Timer Clock Enable for Register Access 라고 쓰여 있다.

즉 와치독 타이머가 돌아가고 있으면 와치독 리셋을 하게끔 기본 프로그램이 되어 있다.

 

//Generated by HT32CodeConfig V1.0.2 Build 230411
//-----------------------------------------------------------------------------
#include "ht32.h"
#include "BFTM0.h"


//-----------------------------------------------------------------------------
int main(void)
{
  BFTM0_Configuration(); //내부 클럭 셋팅 및 BFTM0 셋팅

  while (1)
  {
    if(HT_CKCU->APBCCR1 & (1 << 4)) //와치독 클럭이 공급 되고 있으면 실행
      WDT_Restart(); //와치독 리셋

  }
}

 

프로그램 주석을 간단히 기입 해 놓았다.

 

외부 클럭을 받고 있는것이 맞는지 확인 하는 방법은 Board상에서 크리스탈을 제거 해볼수도 있겠지만

Keil에 디버깅 모드에서 확인을 하겠다.

우선 위 사진상 표시된 부분을 찾아보자.

HSE EN으로 UserManual에서 검색을 하니 HSE enable bit라고 표시 되어 있으며 (HSEEN) 이라고 되어 있다.

다시 검색으로 HSEEN을 검색하니 GCCR(Global Clock Control Register) 라고 표시 된 부분에 10번 비트라고 나온것을 확인(101page) 할수 있었다.

10번 비트(HSEEN)가 0이면 외부 크리스탈을 이용하지 않으며 1일경우에는 외부에 4 ~ 16MHz 크리스탈을 이용할수 있다고 되어 있다.

공부 하시는 분이라면 이것 말고도 위와 아래 있는 비트들을 잘 알아 주시는것이 좋을듯 합니다.

 

Keil에서 디버깅 모드로 들어가려면 Ctrl 키와 F5 키를 눌러 주거나 사진상에 마우스가 있는 부분에 돋보기 d 그림을 클릭 해줘도 된다.

그럼 위 사진과 같은 창들이 나온다.

F5키를 눌러서 실행을 한다.

다음 Stop을 눌러 정지 해준다.

Peripherals -> System Viewer -> CKCU 클릭

클럭 상태가 어떻게 되어 있는지 창이 나온다.

GCCR을 보면 PLLEN, HSEEN, HSIEN이 체크 되어 있고

CKST를 보면 CKSWST, PLLST, HSEST 값이 들어가 있는것을 확인 할수 있다.

Datasheet를 참고 하면 다음과 같다.

CKSWST 값이 0x01로 되어 있으니 Datasheet 확인결과 00x:CK_PLL clock out as system clock 부분에 해당한다.

PLL 출력을 System Clock으로 사용으로 설정 되어 있단다.

PLLST는 0x01이다 확인결과 xxx1:PLL is used by System Clock (CK_SYS) 부분에 해당한다.

PLL 출력을 System Clock으로 사용하라고 되어 있따.

HSEST는 0x02이다 확인결과 x1x:HSE is used by System PLL 부분에 해당한다.

HSE 클럭을 PLL System에 사용한다고 이해 하면 된다.

HT32F52367_LQFP80_1.zip
5.51MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해 보자.

윈도우 시작에서 HT32_CodeConfig 아이콘을 클릭 하여 실행

File에 New 글씨를 클릭 (단축키 Ctrl + N) 또는

위 그림처럼 아이콘 클릭

 

 

위 사진과 같이 SelectMCU 창이 열립니다.

아래로 스크롤 하여 HT32F52367에서 LQFP80을 선택후 OK 버튼을 눌러 줍니다.

 

위와 같이 클럭을 설정 할수 있는 창이 열립니다.

현재 내부 클럭 HSI RC(8MHz)를 사용하며

내부 LSI RC(32KHz)를 사용하게 되어 있습니다.

우선은 기본으로 되어 있는 상태로 진행 하겠습니다.

Tools에 Options... 를 클릭 하거나 Alt키 + F7키를 눌러 컴파일러를 확인 해줍니다.

위와 같은 Options 창이 열리면 MDK로 선택을 해줍니다. MDK는 Keil 컴파일러를 만드는것이고 IAR은 IAR 컴파일러를 만드는 것입니다.

참고로 다시 이야기 하면 IAR은 디바이스들이 별로 없습니다. 케일 사용하시는것이 좋을듯 합니다.

현재 기본 상태에서 Code를 만들려면 위 화면처럼 Generate Code를 누르거나 F7버튼 클릭 또는 Tools에 Generate Code를 클릭 하세요.

위와 같이 폴더 찾아보기가 화면에 나오면 저장할곳을 선택하여 확인을 눌러 줍니다.

저는 D 드라이브에 Holtek 방에 HT32F52367 폴더 안에 새 폴더 만들기 하여 CodeConfig 라는 폴더를 만들었습니다.

확인을 누르면 잠깐 파일을 만드는 창이 떴다가 위와 같은 창이 열립니다.

Open Project를 눌르면 Keil 컴파일러가 실행 되면서 프로젝트가 바로 열리나

위치 확인 할겸 Open Folder를 누릅니다.

그러면 아까 만들고 선택했던 CodeConfig 폴더 안에 HT32F52367_LQFP80 이라는 폴더 안에 프로젝트 파일들이 만들어져 있는것을 확인 할수 있습니다.

 

project 폴더 안에 main.c 등등 파일이 있는것을 확인 할수 있습니다.

MDK_ARMv5 폴더로 들어가서 project.uvprojx 파일을 더블 클릭 하여 Keil을 실행합니다.

위와 같이 Keil이 실행되고 프로젝트가 불러 들여진것을 확인 할수 있다.

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. Holtek사에 Code Generation 프로그램을 사용해 보자.

Holtek 홈페이지 상단에 MCU Tools 눌러 들어간후 ICE 글자를 클릭

 

 

 

화면을 밑으로 내리면 HT32_CodeConfig_V1.0.2 라는 글자가 있다. 클릭

https://www.holtek.com/ice 다운 받을수 있는 페이지로 링크를 연결. 파일 버전이 변경 될수 있어서 파일로 연결은 안할게요.

다운 받은 HT32_CodeConfig_V1.0.2.zip파일을 압축 해제 하여 실행 하자.

HT32_CodeConfig_Setup_V1.0.2.exe 파일을 실행 해주자. 아래 설치 화면 그냥 눈으로 보고 pass.

 

 

 

설치 완료 및 실행.

 

이런 창이 화면에서 열린다.

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. ADC (Analog to Digital Converter) 를 사용 해보자.

ADC 폴더에 Continuous_Potentiometer 예제를 이용합니다.

 

ADC 데이터 변화를 확인하기 위해 예제 프로그램은 Serial Port를 사용하였는데 편의를 위해 USB를 사용하겠습니다.

위 사진과 같이 USB 연결을 해줍니다.

Keil 프로젝트에서 ht32f5xxxx_conf.h 파일을 열어서 65번째 줄에 #define RETARGET_PORT 10 이 적혀 있는부분에 숫자 10을 지우고 RETARGET_USB 로 변경합니다.

 

무료 Serial 통신 프로그램을 다운받아 설치 합니다. 저는 무료 프로그램중 Tera Term - 다운로드 (softonic.kr) 테라텀을 다운 받아서 설치 하였습니다.

main.c 파일에 있는 설명입니다.

h32f5xxxx_01_it.c에 있는 설명 입니다.

ht32f5xxxx_conf.h 파일에 있는 설명 입니다.

ht32f5xxxx_01_it.c
0.01MB
ht32f5xxxx_conf.h
0.02MB
main.c
0.01MB

첨부된 파일을 덮어 쓰기 하셔도 됩니다.

PC에서 장치 관리자 들어가셔서 새로 잡힌 USB 직렬장치 (COMx)를 선택해서 테라텀에 넣고 115200 속도로 하면 위와 같이 확인이 가능 합니다.

변경 되는것을 바로 확인 하려면 보드에서 D4단자에 손가락으로 닿으면 변화가 있는것을 확인 됩니다.

 

동영상을 보면 1900대에서 변화가 크게 생겼을때가 손가락을 닿았을때 인데 EVM Board가 안좋은건지 예제가 문제가 있는건지 2000대에서 안내려옴... MCU RESET을 하면 내려옴.

 

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. BFTM (Basic Function Timer) 를 사용해 보자.

BFTM RepetitiveToggle 예제 를 진행 하겠습니다.

 

main.c 파일에 있는 내용

ht32f5xxxx_01_it.c에 있는 내용.

 

ht32f5xxxx_01_it.c
0.01MB
main.c
0.00MB

 

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. 외부 신호 인터럽트 (EXTI) 를 사용해보자.

EXTI_Key_LED 폴더를 예제 실험.

_ClearProject.bat 실행후 MDK_ARMv5 폴더 진입

Project_52367.uvprojx 실행

main에 EXTI_WAKE_Configuration 글씨를 더블 클릭하고 F12키를 누른다.

EXTI_WAKE_Configuration()에 대한 주석을 남겨 놓았다.

 

ht32f5xxxx_01_it.c 파일은 인터럽트 펑션들이 있다.

인터럽트 관련 주석을 달아놨으니 확인 하세요.

ht32f5xxxx_01_it.c
0.01MB
main.c
0.01MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. DAC (Digital to Analog Converter) 를 사용해보자

DAC 예제가 있는폴더에서 Async_2CH 폴더를 들어가서 _CreateProject.bat 파일을 더블 클릭하여 실행.

 

이번에는 선택 하는거 없이 바로 만들어지고 완료 되었다고 창이 열린다. 아무키나 눌러서 닫아 준다.

바로 MDK_ARMv5 폴더를 더블 클릭하여 들어간다.

Project_52367.uvprojx를 더블 클릭하여 실행해 준다.

실행하면 위와 같이 Keil이 열린다. 이상태에서 F7을 눌러 이상유무를 확인 해보자.

만약 이상이 있다면 Build Output 창에 메시지 내용을 보고 해결 하세요.

main.c 에 프로그램 설명을 붙였습니다.

 

Datasheet 31번 페이지에 75번핀(PC3), 78번핀(PB8) 각각 DAC0과 DAC1이 출력 할수 있다고 표가 있음.

 

PB8에 오실로 스코프를 연결하고 측정을 해보았다.

오실로 스코프에서 전압이 나오는것을 확인 할수 있는데 오실로 스코프에서는 조금 낮게 나왔다.

OSC에 GND 위치를 잘못 잡은듯 하다.

DMM (Digital Multi Meter)으로 확인시 GND를 바로 옆에 측정을 하니 1.63510V 측정이 되었다.

실제 사용할때는 필히 확인이 필요함.

PC3, PB8모두 동일하게 나왔다.

 

main.c
0.01MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. GPIO 입력과 출력을 확인해보자

회로도 상에 보면 PA6과 PA3 또는 PE2가 같이 붙어 있다. 이번에는 PA6의 출력 신호를 PE2로 받아서 받은 신호를 PE3에 출력 합니다.

앞에 사용했던 프로그램에 추가 하는 방법으로 진행 합니다.

 

void GPIO_Configuration(void) 문에서 PA6, PE3을 출력 모드로 해 놓았으니 이제 입력 포트를 만들어 보자

표시된 문장 4줄을 추가 하면 PE2를 입력 포트로 만든 것입니다. F7 키를 눌러서 Build한후 이상이 없는지 확인하자.

 

GPIO_SetOutBits 글자를 더블 클릭후 F12 키를 눌러서 어디에 선언 되어 있는지 확인 하자.

F12를 눌러 이동하니 ht32f5xxxx_gpio.c 파일에 선언이 되어 있다. 

마우스를 스크롤 하여 위로 가면 FlagStatus GPIO_ReadInBit(HT_GPIO_TypeDef* HT_GPIOx, u16 GPIO_PIN_n) 이라는 펑션이 있는데 이것을 사용하여 현재 PE2포트 상태를 알수 있다.

void GPIO_OutputBit(void) 펑션에 추가 한 내용이다. 추가후 F7을 눌러 Build를 해준후 F8 키를 눌러 다운로드 해주자.

 

 

void GPIO_OutputBit(void)
{
  GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_6); // PA6 = HIGH
  __Delay(500000);  //LED 변화를 확인하기 위한 시간 지연
  if (GPIO_ReadInBit(HT_GPIOE, GPIO_PIN_2) == 0)    //PE2에 입력이 LOW(0)이면 아래 실행
  {
      GPIO_ClearOutBits(HT_GPIOE, GPIO_PIN_3); //PE2에 입력이 LOW(0)이면 PE3에 출력을 LOW(0) 으로 하라는 명령
  }
  else
  {
      GPIO_SetOutBits(HT_GPIOE, GPIO_PIN_3); //PE2에 입력이 LOW(0)가 아니면 PE3에 출력을 HIGH(1)로 하라는 명령
  }
  __Delay(500000);  //LED 변화를 확인하기 위한 시간 지연
  GPIO_ClearOutBits(HT_GPIOA, GPIO_PIN_6); // PA6 = LOW
  __Delay(5000000);  //LED 변화를 확인하기 위한 시간 지연
  if (GPIO_ReadInBit(HT_GPIOE, GPIO_PIN_2) == 0)    //PE2에 입력이 LOW(0)이면 아래 실행
  {
      GPIO_ClearOutBits(HT_GPIOE, GPIO_PIN_3); //PE2에 입력이 LOW(0)이면 PE3에 출력을 LOW(0) 으로 하라는 명령
  }
  else
  {
      GPIO_SetOutBits(HT_GPIOE, GPIO_PIN_3); //PE2에 입력이 LOW(0)가 아니면 PE3에 출력을 HIGH(1)로 하라는 명령
  }
  __Delay(500000);  //LED 변화를 확인하기 위한 시간 지연
}

다운 로드가 완료 되면 PCB에 있는 버튼을 눌러 리셋 시키면 MCU가 동작 되는것을 확인 할수 있다.

PE2와 PA6을 연결하면 LED가 서로 반대로 켜지는것을 확인 할수 있다.

동영상에 핀셋은 PE2와 PA6을 연결하기 위한 도구로 사용했다.

 

 

main.c
0.01MB

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. LED를 켜보자.

GPIO_OutputBit(); 부분에서 영어 문장 부분을 마우스 왼쪽 버튼으로 두번 클릭한후 F12를 눌러서 해당 명령이 있는 부분으로 이동하자.

 

void GPIO_OutputBit(void)
{
  GPIO_SetOutBits(HT_GPIOB, GPIO_PIN_1); // GPIO = HIGH
  __Delay(500000);

  GPIO_ClearOutBits(HT_GPIOB, GPIO_PIN_1); // GPIO = LOW
  __Delay(5000000);
}

 

이부분중 GPIOB는 GPIOA로 GPIO_PIN_1은 GPIO_PIN_6으로 변경

void GPIO_OutputBit(void)
{
  GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_6); // GPIO = HIGH

//PA6에 HIGH를 출력 하라는 명령
  __Delay(500000);

//사람에 눈으로 LED가 변화 되는것을 확인할수 있게 시간 지연을 준것

  GPIO_ClearOutBits(HT_GPIOA, GPIO_PIN_6); // GPIO = LOW

//PA6에 LOW를 출력 하라는 명령
  __Delay(5000000);

//사람에 눈으로 LED가 변화 되는것을 확인할수 있게 시간 지연을 준것
}

이렇게 변경후 컴파일

에러나 경고가 발생하지 않았다.

이제 Ctrl + F5 키를 눌러서 디버깅 모드로 진입해서 확인을 해보자.

지금 창은 디버깅 모드 창으로 현재 명령을 실행 대기 중이다. 여기서 F11을 누르면 명령 하나씩 실행하고

F10을 누르면 불러오는 펑션은 들어가서 한단계씩 실행하는게 아니라 그안에 포함된 명령이 모두 실행 되고 다음줄 명령으로 이동한다.

여기서 F5 키를 누르면 F9 키를 눌러 Break Point를 잡아 놓지 않았다면 그냥 실행 되고 F9를 눌러 Break Point를 잡아 놓았다면 Break Point에서 멈춘다.

우선 F5를 눌러서 실행 해 보자.

LED가 켜지기는 하는데 꺼지지 않는다.

프로그램에서 왜 그러는지 찾아보자

Keil 창에서 왼쪽 위에 빨간 동그라미에 x표시가 있는 Stop 버튼을 눌러 보자.

현재 MCU가 어디를 실행 중인지 나온다.

현재 위치는 void HardFault_Handler(void) 함수에 있다.

프로그램이 어딘가에 문제가 있다는 이야기 이다.

우선 main.c 파일을 눌러서 Main으로 간다

 

main.첫줄에 마우스를 클릭하고 커서가 위치해 있으면 F9 키를 눌러서 Break Point를 설정한다.

그후 Keil 왼쪽 위에 RST 라고 써있는 버튼을 클릭 한다.

 

현재 MCU가 초기화 되어서 MCU 내부적으로 처음으로 실행 하는 부분에서 대기중이다.

 

키트를 보면 LED는 꺼져 있는것을 확인 할수 있다.

 

F5 키를 누르면 조금전에 Break Point 를 설정해놓은 부분에서 MCU 동작이 멈춰 있는 것을 알수 있다.

우선은 어디 함수에서 문제인지 알아야 하니 F10을 눌러서 한단계씩 진행을 해본다.

F10 눌러 GPIO_Configuration();은 모두 실행되고 멈춰 있으니 이상이 없는것을 확인 했다.

한번더 F10을 눌러 GPIO_OutputBit(); 를 실행해 보자.

GPIO_OutputBit(); 역시 이상없이 진행 되고 노란색 화살표가 GPIO_OutputData();실행 전에 멈춰 있다. .

한번더 F10을 눌러서 GPIO_OutputData(); 를 실행해 보자.

이번에는 다음으로 넘어가지 않고 그냥 계속 실행 되고 있다고 한다. 왼쪽 위에 적색 원형에 가운데 x가 들어있는 Stop Icon이 계속 활성화가 되어 있다.

정지를 누르면 void HardFault_Handler(void) 안에 있는것을 확인 할수 있다.

GPIO_OutputData();에 이상이 있다는 이야기 이다. GPIO_OutputData(); 펑션은 수정한적이 없다. 아직 사용을 안하기 때문에 //를 삽입하여 Skip을 해주고 다시 실행 해보자.

 

이 버튼을 눌러서 디버깅 모드를 종료 하자.

 main.c 파일로 가서 Gpio_OutputData(); 앞에 //를 넣어 주고 F7을 눌러 Build를 해서 이상유무를 확인.

이상이 없으면 Ctrol + F5 키를 눌러서 다시 다운로드후 디버깅 모드로 진입

정상적으로 들어왔으면 F5 키를 눌러서 실행.

정상 적이라면 다음과 같이 LED가 깜빡이는것을 알수 있다.

 

여기까지 GPIO 예제를 실행 해보았음.

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. LED를 켜보자.

Keil 프로그램에서 왼쪽에 Project 창에보면 HT32 폴더 밑에 User 폴더에 Main.c 파일이 있다. 

더블 클릭하여 파일을 열고 int main(void) 부분에 보면 GPIO_Configuration(); 부분이 있는데 이부분을 더블 클릭하고 난후에 F12 키를 누르면 해당 명령문이 있는 곳으로 이동할수 있다.

 

  { /* Enable peripheral clock                                                                              */
    CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
    CKCUClock.Bit.AFIO = 1;  //AFIO(Alternate Function Input/Output Control Unit) Clock을 켜줘야 GPIO가 정상 동작함.
    CKCUClock.Bit.PB = 1;    //Port B에 Clock을 공급 하라는 명령
    CKCU_PeripClockConfig(CKCUClock, ENABLE);    //AHB, APB Clock을 공급 하라는 명령
  }

이부분은 PB(Port B)에 클럭을 인가 하는 부분이다.

우리는 PE3과 PA6을 제어 하여야 하기때문에 수정이 필요함.

CKCUClock.Bit.PB = 1;  이줄을 삭제하고 PB(Port B는 현재 사용 안함)

이부분을

CKCUClock.Bit.PA = 1;

//Port A에 Clock을 공급 하라는 명령
CKCUClock.Bit.PE = 1;

//Port E에 Clock을 공급 하라는 명령

으로 수정을 하자.

  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PB, AFIO_PIN_1, AFIO_FUN_GPIO);

    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOB, GPIO_PIN_1, GPIO_PR_DOWN);

    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOB, GPIO_PIN_1, RESET);

    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOB, GPIO_PIN_1, GPIO_DIR_OUT);
  }

이부분 에서도 몇가지 수정을 해야함.

현재 사진처럼 GPIO_PB 글씨를 더블클릭후 F12번 키를 누르면 GPIO_PB가 어디에 선언 되어 있는지 알수 있다.

F12를 눌러 선언된 곳으로 이동하니 GPIO_PA, GPIO_PE가 있는것을 확인 했음.

밑으로 조금 내려보면 GPIO_PIN_0 부터 15번까지 또는 GPIO_PIN_ALL 까지 있는것을 확인 할수 있다.

  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PB, AFIO_PIN_1, AFIO_FUN_GPIO);

    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOB, GPIO_PIN_1, GPIO_PR_DOWN);

    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOB, GPIO_PIN_1, RESET);

    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOB, GPIO_PIN_1, GPIO_DIR_OUT);
  }

이부분을 복사하여 붙여넣기 하여 두개를 만들자. (방법은 많으나 설명에 편의를 위한 방법으로 함.)

  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PB, AFIO_PIN_1, AFIO_FUN_GPIO);

//이부분은 PB1(Port B에 1번핀)에 기능은 GPIO로 사용하겠다는 명령임.

    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOB, GPIO_PIN_1, GPIO_PR_DOWN);
//이부분은 PB1에 Pull Down 저항을 걸어 주겠다는 명령임.
    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOB, GPIO_PIN_1, RESET);
//이부분은 PB1에 출력을 Low(0)로 하겠다는 명령임.
    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOB, GPIO_PIN_1, GPIO_DIR_OUT);

//이부분은 PB1을 출력으로 하겠다는 명령임.
  }

  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PB, AFIO_PIN_1, AFIO_FUN_GPIO);

    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOB, GPIO_PIN_1, GPIO_PR_DOWN);

    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOB, GPIO_PIN_1, RESET);

    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOB, GPIO_PIN_1, GPIO_DIR_OUT);
  }

이렇게 복사 한후 위에것은 PB를 PA로 GPIOB를 GPIOA로 PIN_1을 PIN_6으로 변경하고

아래는 PB를 PE로 GPIOB를 GPIOE로 PIN_1을 PIN_3으로 변경 하자.

  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PA, AFIO_PIN_6, AFIO_FUN_GPIO);
//PA6을 GPIO기능으로 사용하겠다는 명령
    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOA, GPIO_PIN_6, GPIO_PR_DISABLE);
//PA6에 Pull-Up, Pull-Down 저항을 연결 하지 말라는 명령
    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOA, GPIO_PIN_6, SET);
//PA6에 HIGH(위에서 Pull-Up, Pull-Down을 연결하지 말라고 했으므로 Floating 상태) 출력을 하라는 명령
    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_6, GPIO_DIR_OUT);

//PA6을 출력 포트로 사용하라는 명령
  }
  { /* Configure GPIO as output mode                                                                        */

    /* Configure AFIO mode as GPIO                                                                          */
    AFIO_GPxConfig(GPIO_PE, AFIO_PIN_3, AFIO_FUN_GPIO);

    /* Configure GPIO pull resistor                                                                         */
    GPIO_PullResistorConfig(HT_GPIOE, GPIO_PIN_3, GPIO_PR_DISABLE);

    /* Default value RESET/SET                                                                              */
    GPIO_WriteOutBits(HT_GPIOE, GPIO_PIN_3, SET);

    /* Configure GPIO direction as output                                                                   */
    GPIO_DirectionConfig(HT_GPIOE, GPIO_PIN_3, GPIO_DIR_OUT);
  }

이렇게 변경 하면 초기 포트 셋팅은 완료 한것이다.

F7 키를 눌러 에러가 없는지 확인하자.

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음. LED를 제어 해보자.

앞서 GPIO 예제를 이용하여 위 그림상에 표시 되어 있는 LED를 제어 하겠습니다.

LED를 제어 하려면 MCU 어떤핀이 LED로 연결 되었는지  확인을 해야 해서 회로도를 다운 받습니다.

 

 

Holtek 홈페이지 (https://www.holtek.com/productdetail/-/vg/HT32F52357_67) 에서 Development Tools 글씨를 클릭 합니다.

사진처럼 Development Kit 라인에 ESK32-30510(EVM 모델 번호) 글씨를 클릭 합니다. HT32F52357이든 HT32F52367이든 관계 없습니다.

 

클릭 하면 사진과 같은 창이 하나 뜨는데 좌우 스크롤을 하여서 아래쪽으로 내려 갑니다.

Documentation에 보면 Starter Kit Schematics 글씨가 있는데 글씨를 마우스로 클릭 해줍니다.

 

그러면 화면 왼쪽 아래 다운로드가 된 파일이 하나 있습니다. 폴더 열기를 하여 해당 폴더로 이동합니다.

 

 

다운 받은 파일 선택후 마우스 오른족 버튼을 눌러  잘라내기 또는 복사를 클릭 해줍니다.

 

예제 파일이 있는 폴더로 가서 폴더 빈 공간에서 마우스 오른쪽 버튼을 눌러 붙여 넣기 해줍니다.

붙여 넣기 한 파일을 선택후 다시 마우스 오른쪽 버튼을 눌러 압축 풀기 해줍니다.

폴더 변경없이 그냥 압축 풀기 버튼 버튼을 클릭 합니다.

압축이 풀리고 화면과 같은 폴더가 열리면 폴더 안으로 들어갑니다.

폴더 안에 보시면 두개에 pdf 파일이 있습니다.

e-link32_Lite_V2.3.pdf는 그림상에 노란 박스로 표기된 다운로드 및 디버깅 부분 회로도 입니다.

그림에서 노란 박스를 해놓은 우리가 필요한 부분 회로도는 ESK32-30510_HT32F52367_SK_V1.0_20200319.pdf 파일입니다.

해당 파일을 더블 클릭 하여 열면 회로도가 열립니다.

회로도 왼쪽 아래 보시면 LEDs가 있습니다. 3개의 LED+ 핀은 모두 VDD33에 연결되어 있으며 D9 (Power)  LED- 핀은 R20번 어레이 저항에 연결되어 GND로 바로 연결 되어 있습니다. (불량이 아니라면 전원을 연결하면 항상 켜 있어야함.)

D7 (LED1)은 R20 저항을 통하여 MCU PE3(Port E에 3번핀)에 연결 되어 있으며

D8 (LED2)은 R20 저항을 통하여 MCU PA6(Port A에 6번핀)에 연결 되어 있음.

현재 회로 상으로 보면 Anode(+) Common으로 연결 되어 있어서 MCU상에서 PE3 또는 PA6번 핀을 Low신호를 보내줘야 LED가 켜지는것을 확인 했음.

 

EVM을 연결하고 전원을 넣으니 불이 켜졌다.

GPIO 예제 프로그램에서 왼쪽 Project 창에 HT32 글자 위에서 마우스 오른쪽 버튼을 누르면 Options for Target 'HT32'...

이라고 클릭을 해준다 (Keil 프로그램을 활성화 시킨후 키보드에서 Alt + F7 키를 동시에 눌러도 가능함)

위와 같은 창이 열리면 Debug 글씨를 클릭.

 

Use란에 CMSIS-DAP Debugger가 맞는지 확인후 Setting 버튼 클릭.

위와 같이 창이 열리고 Serial No나 IDCODE는 화면과 다르게 나와도 상관이 없으나 Device Nme은 ARM Core 글씨가 나와야 함.

그냥 OK를 눌러도 괜찮으나 이왕이면 Adapter를 맞춰 주고 OK를 클릭 하자.

728x90
반응형
728x90
반응형

Holtek사 MCU중 HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음.

압축을 해제한 폴더에 들어갑니다.

위 그림처럼 폴더가 있습니다. 그리고 example 폴더로 들어갑니다.

많은 예제중 GPIO 폴더로 들어갑니다.

입력도 있지만 우선 출력 먼저 해보겠습니다. Output 폴더로 들어갑니다.

폴더에 들어가면 파일이 4개가 있는데 _CreateProject.bat 파일을 더블 클릭하여 실행해 줍니다.

위와 같은 DOS 화면이 열리면 컴파일러를 어떤것을 사용할지 입력 해야 합니다.

우리는 Keil MDK-ARM V5를 선택 해야 하므로 키보드에서 숫자 1을 눌러 줍니다.

 

그럼 [1] 앞에 -표시가 *표시로 변경 됩니다. 그다음 키보드에서 N을 쳐주면 다음 화면으로 넘어갑니다.

이번에는 어떤 MCU인지 물어봅니다.

 

제가 사용할 MCU는 HT32F52367인데 앞에 HT32F는 빼고 MCU 뒷부분만 52367을 키보드를 눌러 줍니다. 

그리고 엔터키를 눌러 줍니다.

그러면 위에 화면처럼 Keil MDK-ARM v5를 선택 했고 IC Name은 52367이라는 표시와 계속 하려면 아무 키나 누르십시오 라는 문구가 나옵니다. 그냥 아무키나 눌러서 종료 해줍니다.

그리고 폴더를 보면 많은 파일이 생긴것을 확인 할수 있습니다. 여기서 MDK_ARMv5 폴더를 더블 클릭 하여 들어갑니다.

Project_52367.uvprojx 라는 Keil 프로그램 Icon이 있습니다. 더블 클릭 하여 실행 해 줍니다.

저처럼 처음 실행 하신분은 위 그림처럼 Pack Installer가 실행 되고 Pack Installer 창 오른쪽 아래 진행 Progress bar가 계속 변합니다. 처음에 생각 보다 시간이 많이 걸립니다. 화면에 OK버튼 누르시고  다른 것을 잠시 하시는것을 추천 드립니다.

왼쪽 Devices 창에서 Holtek 제품을 선택 하면 오른쪽 Packs 창에 Device Specific 아래 Holtek:HT32_DFP 라는 글자 옆에 Install 버튼이 활성화 되지 않고 있읍니다.

아직 기본 Pack이 모두 설치가 안되어서 그렇습니다. 모두 알아서 설치 될때까지 기다려 줍니다.

시간이 좀 지난후 화면을 보면 그림과 같은 창이 뜨고 Holtek MCU 관련 Pack을 설치 할것인지 묻습니다.

Install을 눌러 줍니다.

Keil 창에서 위와 같이 Packs을 다시 읽어 올것인지 물어보면 예를 클릭 해줍니다.

 

그러면 위 화면과 같이 Keil 프로그램이 표시 됩니다.

여기서 마우스로 Build를 클릭 하거나 키보드에서 F7 버튼을 클릭 합니다.

그러면 컴파일 과정이 Build Output 창에 표시 하다 화면 처럼 Error 및 Warning 이 0으로 출력 하고 Build Time Elapsed : 하고 시간이 나오면서 컴파일이 완료 됩니다.

 

여기까지 나오면 정상적으로 Keil, Pack, 등등 설치 하신겁니다.

728x90
반응형
728x90
반응형

HT32F52357와 HT32F52367은 기능은 같은데 Flash와 SRAM 용량 차이가 있음.

홀텍 홈페이지(https://www.holtek.com/productdetail/-/vg/HT32F52357_67)에 들어갑니다. Documents 글씨를 누르고 스크롤을 아래로 내리면 

Demo Code가 있는데 HT32_STD_5xxx_FWLib_V1.4.1_6948.zip 글씨를 클릭 하여 다운 받아 줍니다.

다운로드가 완료 되면 폴더 열기를 눌러서 폴더 확인 합니다.

폴더를 열어서 확인하면 압축 파일로 되어 있는데 복사 하거나 잘라내기 하여 자신의 원하는 폴더로 옮겨 놓는다.

 

나는 D Driver에 옮겨 놓았다.

 

마우스 왼쪽 버튼으로 클릭후 오른쪽 버튼을 눌러 압축 풀기를 해준다.

압축 풀기 버튼을 눌러서 압축을 풀어준다.

압축이 모두 풀리면 그림과 같이 폴더가 생겼음을 알수 있다.

홀텍사에서 받은 프로그램이 정상 동작을 하지 않아서 정상 동작하는 예제 파일을 원하시는 분은 메일 주소 남겨 주세요.

 

 

728x90
반응형

'프로그램 > Holtek 32Bit' 카테고리의 다른 글

Holtek EVM Board에 LED 켜기 1단계 준비 작업  (0) 2023.07.09
Holtek GPIO Output 예제 실행하기  (0) 2023.07.09
Keil 실행하기  (0) 2023.07.08
Keil에 Holtek MCU 등록하기  (0) 2023.07.08
Keil 설치하기  (0) 2023.07.08

+ Recent posts