해보기는 했어?

오늘 안됐다고 포기하지 말고 용기내서 내일 다시 해 보자.

MEGAWIN

MG82F6D Series TIM_T2_Mode0_AutoRL_AndEXI

롬돌이 2022. 12. 27. 11:42
반응형

1. 프로그램 개요

P22Green 0 LED, P24 Red LED, P26Green 1 LED가 연결되어 있다.

타이머 2의 모드 0 16-bit 자동 재적재 모드(Auto-Reload)이다. 타이머 2 오버플로 플래그인 TF2 TF2IG플래그로 제어될 수 있는 타이머 2의 인터럽스 소스 중 하나이다.

EXEN2T2EXI의 상태가 1(high)에서 0(low)로 바뀔 때 EXF2 플래그를 셋 시킬 수 있도록 해 준다. 이 외부 인터럽트 입력은 TF2 플래그와 함께 타이머 2 인터럽트를 공유한다.

 

T2EXI 핀인 P11에 버튼을 연결하고, 버튼이 눌릴 때 마다 연결된 LED가 토글 되도록 한다.

2. 회로도

3. Code

main routine

 

void main()

{

InitSystem();                                      // 시스템 초기화루틴

LED_G_0=0;LED_G_1=0;LED_R=0;              // LED ALL ON

           DelayXms(1000);                                  // 1초 딜레이

          LED_G_0=1;LED_G_1=1;LED_R=1;              // LED ALL OFF

           INT_EnAll();                                       // Enable global interrupt

                                                    

    while(1)

    {

          LED_R=!LED_R;                                   // LED_R toggle

          DelayXms(100);                                   // 100ms delay

    }

}

⑵ 시스템 초기화 루틴

/***********************************************************************************

*Function:   void InitSystem(void)

*Description:           Initialize MCU

*Input:  

*Output:    

*************************************************************************************/

void InitSystem(void)

{

           InitPort();

           InitClock();

          

           InitTimer2();                         

 

           InitInterrupt();                                                                            // Initialize Interrupt}

- 포트 설정을 수행한다.

- 클럭을 설정한다.

- 타이머 2를 초기화 시킨다.

- 인터럽트를 초기화한다.

 

 

 

Port 초기화

/***********************************************************************************

*Function:   void InitPort(void)

*Description:  Initialize IO Port

*Input:  

*Output:    

*************************************************************************************/

void InitPort(void)

{

           PORT_SetP2PushPull(BIT2|BIT4|BIT6);                                        // Set P22,P24,P26 as Push-Pull,For LED.

è P22, P24, P26 LED용으로 사용한다.

 

           PORT_SetP1OpenDrainPu(BIT1);                                                 // set P11 as open-drain with pull-high for T2EX

è P11Pull-Up을 가지고 있는 OpenDrain타입으로 설정하여 T2EX 신호 입력으로 사용할 수 있도록 한다.

}

*** 사용된 매크로함수는 “API_Macro_MG82FG6D16.H”에서 찾아볼 수 있다.

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\MG82F6D16_GPIO_TIM_T2_Mode0_AutoRL_AndEXI\code\include

⑷ 클럭 초기화 루틴 è 시스템 클럭 및 내부 클럭을 설정한다.

프로그램의 루틴 자체는 복잡하게 많이 설정해 두었으나 그 구조는 아래와 같다.

MCU_SYSCLK의 값은 11059200, 12000000, 22118400, 24000000, 29491200, 32000000, 44236800, 48000000로 설정이 가능하며, 각각 프로그램 상단에

#define        MCU_SYSCLK          12000000

와 같이 선언해주었다. 그리고, 바로

#define        MCU_CPUCLK          (MCU_SYSCLK)

로 선언하여 System 클럭과 CPU 클럭을 동일하게 사용하기로 선언하였다. 물론 사용자의 선택에 따라 틀려질 수 있으므로 어플리케이션에 따라 선언하면 된다.

#if (MCU_SYSCLK==12000000)                        // System Clock12MHz로 선언되어 있으면

#if (MCU_CPUCLK==MCU_SYSCLK)                    // CPU ClockSystem Clock와 동일하면

         // SysClk=12MHz CpuClk=12MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1);         // 이와 같이 설정하고

        

#else

         // SysClk=12MHz CpuClk=6MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1);         // CPU clockSystem Clock와 같거나 1/2로 설정할

// 수 있다.

#endif

#endif

- CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1);

CKCON0 레지스터의 각 비트를 설정한다.

CKCON0.7 : AFS, Alternated Frequency Selection, 내부 클럭 IHRCO12MHz(AFS = 0), 또는 11.059MHz(AFS = 1)로 설정함

CKCON0.3 : CCKS, CPU Clock Select, 0:CPU CLOCK = System Clock, 1:CPU CLOCK = System Clock/2

CKCON0.0 ~ 2 : Programable System Clock Select. SYSCLK_MCKDO_DIV_1(System Clock = Master Clock Divider Output)

 

/***********************************************************************************

*Function:   void InitClock(void)

*Description: 

*                                  Initialize clock

*Input:  

*Output:    

*************************************************************************************/

void InitClock(void)

{

#if (MCU_SYSCLK==11059200)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // SysClk=11.0592MHz CpuClk=11.0592MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1);

        

#else

         // SysClk=11.0592MHz CpuClk=5.5296MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1);

#endif

#endif

 

#if (MCU_SYSCLK==12000000)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // SysClk=12MHz CpuClk=12MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1);

        

#else

         // SysClk=12MHz CpuClk=6MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1);

#endif

#endif

 

#if (MCU_SYSCLK==22118400)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // SysClk=22.1184MHz CpuClk=22.1184MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx4, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X4|OSCIn_IHRCO);

#else

         // SysClk=22.1184MHz CpuClk=11.0592MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx4, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X4|OSCIn_IHRCO);

#endif

#endif

 

#if (MCU_SYSCLK==24000000)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // SysClk=24MHz CpuClk=24MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx4, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X4|OSCIn_IHRCO);

#else

         // SysClk=24MHz CpuClk=12MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx4, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X4|OSCIn_IHRCO);

#endif

#endif

 

#if (MCU_SYSCLK==29491200)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // Cpuclk high speed

         CLK_SetCpuCLK_HighSpeed();

         // SysClk=29.491200MHz CpuClk=29.491200MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx5.33, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X533|OSCIn_IHRCO);

#else

         // SysClk=29.491200MHz CpuClk=14.7456MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx5.33, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X533|OSCIn_IHRCO);

#endif

#endif

 

#if (MCU_SYSCLK==32000000)

#if (MCU_CPUCLK==MCU_SYSCLK)

         // Cpuclk high speed

         CLK_SetCpuCLK_HighSpeed();

         // SysClk=32MHz CpuClk=32MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx5.33, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X533|OSCIn_IHRCO);

#else

         // SysClk=32MHz CpuClk=16MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx5.33, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X533|OSCIn_IHRCO);

#endif

#endif

 

#if (MCU_SYSCLK==44236800)

         // SysClk=44.2368MHz CpuClk=22.1184MHz

         CLK_SetCKCON0(IHRCO_110592MHz|CPUCLK_SYSCLK_DIV_1|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx8, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X8|OSCIn_IHRCO);

#endif

 

#if (MCU_SYSCLK==48000000)

         // SysClk=48MHz CpuClk=24MHz

         CLK_SetCKCON0(IHRCO_12MHz|CPUCLK_SYSCLK_DIV_2|SYSCLK_MCKDO_DIV_1|ENABLE_CKM|CKM_OSCIN_DIV_2);

         DelayXus(100);

         // IHRCO, MCK=CKMIx8, OSCin=IHRCO

         CLK_SetCKCON2(ENABLE_IHRCO|MCK_CKMI_X8|OSCIn_IHRCO);

#endif

 

         // P60 Output MCK/4

         //CLK_P60OC_MCKDiv4();

}

 

Timer 2 설정

/***********************************************************************************

*Function:   void InitTimer2(void)

*Description:   Initialize Timer2

*Input:  

*Output:    

*************************************************************************************/

void InitTimer2(void)

{

           TM_SetT2Mode_AutoRLandExI();                                                // T2 mode: Auto-Reload and External Interrupt

           TM_SetT2Clock_SYSCLKDiv12();                                                 // T2 clock source: SYSCLK/12

           TM_SetT2LowByte(TIMER_12T_1ms_TL);                                      // T2 low byte

           TM_SetT2HighByte(TIMER_12T_1ms_TH);                                      // T2 high byte

           TM_SetT2RLHighByte(TIMER_12T_1ms_TH);                        // T2 reload high byte

           TM_SetT2RLLowByte(TIMER_12T_1ms_TL);                        // T2 reload low byte

           TM_EnableT2();                                                                                              // Enable T2

 

           TM_SetT2Capture_T2EXPin();                                                      // T2 EXI: T2EX pin

           TM_SetT2CKOT2EX_P10P11();                                                               // T2EX pin: P11

           TM_EnableT2EX_DetectFalling();                                                 // T2EX detect: Falling

}

 

- Timer 2 Auto Reload 와 외부 인터럽트 입력 모드로 설정

#define TM_SetT2Mode_AutoRLandExI()                          CP_RL2=0;T2MOD=T2MOD&(~T2MS0)

타이머 2를 모드 0 : 자동재적재 와 외부 인터럽트 모드로 설정한다.

 

- Timer 2용 클럭 설정

#define TM_SetT2Clock_SYSCLKDiv12()                 C_T2=0;T2MOD=T2MOD&(~T2X12);SFRPI=1;T2MOD1=T2MOD1&(~T2CKS);SFRPI=0

T2CKS, T2X12, C/T2 비트를 이용해서 Timer 2의 클럭을 설정한다. 본 예제에서는 SYSCLK/12Timer 2의 클럭으로 설정한다.

SYSCLK12MHz이므로 Timer2의 클럭은 1MHz이다. 그러므로 Timer 21us마다 카운트 된다.

 

- 1ms 타이머를 만들기 위하여 TL2TH2에 적절한 데이터 값을 저장한다. 그리고, 자동 재적재를 위한 레지스터에도 동일한 값을 저장한다.

 

- Timer 2 동작

#define TM_EnableT2()                              TR2=1

TR2를 셋(1)시켜 타이머 2를 동작 시킨다.

 

- T2EX Pin을 설정한다.

#define TM_SetT2Capture_T2EXPin()                     SFRPI=1;T2MOD1=T2MOD1&(0xF8);SFRPI=0

SFR Page 1에 있는 T2MODE1 레지스터의 CP2S2 ~0을 모두 0(clear)으로 저장하여 타이머 2의 캡쳐 소스를 T2EX 핀으로 선택한다.

 

- T2EX 핀 할당

#define TM_SetT2CKOT2EX_P10P11()                    SFRPI=1;AUXR4=AUXR4&(~(T2PS1|T2PS0));SFRPI=0

SFR Page 1에만 존재하는 AUXR4 레지스터의 T2PS1, T2PS0 비트를 00으로 만들어 T2/T2CKO P1.0, T2EX P11에 할당한다.

 

- T2EX의 하강에지(Falling edge)에서 동작할 수 있도록 선언 함

#define TM_EnableT2EX_DetectFalling()                                                 EXEN2=1

 

 

 

 

 

 

⑹ 인터럽트 초기화

/***********************************************************************************

*Function:   void InitInterrupt(void)

*Description:   Initialize Interrupt

*Input:  

*Output:    

*************************************************************************************/

void InitInterrupt(void)

{

           INT_EnTIMER2();

}

- 타이머 2 인터럽트 설정

#define INT_EnTIMER2()                  ET2=1

IE(인터럽트 활성화 레지스터)의 비트 3ET2를 셋(1) 시켜서 타이머 2 인터럽트를 활성화시킨다.

 

⑻ 타이머 2 인터럽트 루틴

/***********************************************************************************

*Function:   void INT_T2(void)

*Description:   T2  Interrupt handler

*Input:  

*Output:    

*************************************************************************************/

void INT_T2(void) interrupt INT_VECTOR_T2

{

           if(TF2)                                            // 타이머 2 인터럽트일 경우에는

           {

                     LED_G_0=!LED_G_0;              // LED_G_0을 토글

                     TF2=0;                                 // 타이머 2 인터럽트 플래그 클리어

           }

           else if(EXF2)                                  // T2EX Pin 인터럽트일 경우

           {

                     LED_G_1=!LED_G_1;              // LED_G_1을 토글

                     EXF2=0;                               // EXF2 플래그 클리어

           }

}

è (EN)MG82F6D16_Datasheet_V051.PDF15. Timers/Counters를 참조한다.

è (EN)MG82F6D17_Datasheet_V051.PDF16. Timers/Counters를 참조한다.

è (EN)MG82F6D64/32_Datasheet_V051.PDF16. Timers/Counters를 참조한다.

4. 프로그램 실행

*** Keil compiler가 인스톨되어 있어야함 ***

해당 Example 폴더를 찾아가 KeilPrj폴더를 Open 한다.

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\ MG82F6D16_TIM_T2_Mode0_AutoRL_AndEXI

해당 폴더의 Keil project 파일을 더블 클릭하여 실행시킨다.(MG82F6D16_DEMO.uvproj)

Rebuild 아이콘을 클릭하여 프로젝트를 컴파일 한다.

Demo BoardUSB Connector를 연결하여 전원을 인가하고, 전원 스위치를 ON시키고, OCD ICE를 연결한 상태에서 위 이미지의 Start/Stop Debug Session(Ctrl+F5) 버튼을 눌러 컴파일된 프로젝트의 디버그 데이터를 다운로드 시킨다.(컴파일 시 에러가 발생하지 않아야함)

다운로드 후 Run(F5) 버튼을 클릭하면 프로그램이 동작한다.

 

5. 동작 영상

https://youtube.com/shorts/0hekiuRTveY?feature=share

 

 

반응형

'MEGAWIN' 카테고리의 다른 글

USB to Serial  (0) 2023.01.05
MG82F6D Series TIM_T2_Mode4_PWM  (0) 2022.12.28
MG82F6D SPI Master  (1) 2022.12.26
MG82F6D SPI Flash-2  (0) 2022.12.22
MG82F6D SPI Flash-1  (0) 2022.12.22