MEGAWIN

MG82F6D Series INT nINTx Wake UP

롬돌이 2022. 11. 25. 11:37
반응형

1. 프로그램 개요

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

외부 인터럽트 입력에 의해 Power Down Mode에서 시스템이 깨어나는 것을 보여준다.

INT0, INT1, INT2가 사용되며, 시스템이 깨어 났을 때 어느 인터럽트가 입력되었는지를 LED에 연결해서 확인할 수 있도록 해 준다.

 

 

2. 회로도

                         

 

 

 

 

 

3. Code

main routine

void main()

{

         u8 BakCKCON2;                         // CKCON2의 값을 백업하기 위한 변수

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

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

         DelayXms(2000);                        // 2초 딜레이

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

         INTCnt=0;                                //

         WakeUpSorce=0;                       // wake up에 사용된 인터럽트 확인용 변수

         while(1)

         {

 

                  if(WakeUpSorce == 0)                 // wake up 인터럽트가 0이면

                  {

                           LED_G_0=!LED_G_0;           // LED_G_0을 토글 시킨다.

                  }

                  else if(WakeUpSorce == 1)           // wake up 인터럽트가 1이면

                  {

                           LED_R=!LED_R;                 // LED_R을 토글 시킨다.

                  }

                  else                               // 그 외의 인터럽트이면

                  {

                           LED_G_1=!LED_G_1;   // LED_G_1을 토글 시킨다.

                  }

                  DelayXms(100);                 // 100ms 딜레이

                  INTCnt++;                       // 시간 카운트 +1

                  if(INTCnt >=50)                // 5초가 지나면(원 소스에는 200으로 되어 있었다. 테스트하기에는 너무 긴 시간이라 약

// 5초 정도로 수정했다.

                  {

                           LED_G_0=1;LED_G_1=1;LED_R=1;

                           BakCKCON2=IAP_ReadPPage(CKCON2_P);   // Backup CKCON2 (if used PLL CKM)

                           IAP_WritePPage(CKCON2_P,BakCKCON2&(~(MCKS0_P|MCKS1_P)));                  // MCK=OSCin (if used PLL CKM)

                           POW_SetMode_PD();                            // MCU enter Power-Down mode

                           _nop_();

                           DelayXus(100);                                            // delay for stabilize CKM (if used PLL CKM)

                           IAP_WritePPage(CKCON2_P,BakCKCON2);    // restore CKCON2,use CKM (if used PLL CKM)

                           INT_DisAll();                                      // Disable global interrupt  

                           if(WakeUpSorce == 0)                          // wake up 소스가 INT0 일 때

                           {

                                   LED_G_0=0;                              // LED_G_0 ON

                           }

                           else if(WakeUpSorce == 1)                    // wake up 소스가 INT1일 때

                           {

                                   LED_R=0;                                 // LED_R ON

                           }

                           else                                                // 그 외 일 때

                           {

                                    LED_G_1=0;                              // LED_G_1 ON

                           }

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

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

                           INT_EnAll();                                        // Enable global interrupt   

                           INTCnt=0;                                         // 파워다운 모드 진입 딜레이 리셋

                  }

         }

}

 

⑵ 시스템 초기화 루틴

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

*Function:   void InitSystem(void)

*Description:           Initialize MCU

*Input:  

*Output:    

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

void InitSystem(void)

{

           InitPort();

           InitClock();

           InitINT0();

           InitINT1();

           InitINT2();

           InitInterrupt();

}

- 포트 설정을 수행한다.

- Clock 설정.

- 외부 인터럽트 0, 1, 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, P26LED 구동을 위하여 Push-Pull type로 설정한다.

           PORT_SetP1OpenDrainPu(BIT0|BIT1|BIT5|BIT6);                          // Set P10,P11,P15,P16 as open-drain with pull-high

è P10, P11, P15, P16을 풀업을 가지고 있는 Open-Drain 으로 설정한다.

}

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

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\MG82F6D16_nINTx_WakeUP\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();

}

 

 

 

nINTx 초기화

 

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

*Function:   void InitINT0(void)

*Description:           Initialize INT0

*Input:  

*Output:    

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

void InitINT0(void)

{

           INT_SetINT0P30();                                                           // nINT0 : P30

           INT_SetINT0_DetectEdge();                                    // nINT0 Detect type: edge, On Power-Down mode,only Level.

           INT_SetINT0_DetectLowFalling();                            // nINT0 Detect: low level/falling edge

           INT_SetINT0Filter_SysclkDiv6_x3();                // nINT0 filter:(sysclk/6)*3

}

- 사용하고자 하는 KBI 채널을 활서화시킨다.

#define INT_SetINT0P30()      XICFG=(XICFG&(~INT0IS1))|INT0IS0;SFRPI =1;XICFG1=XICFG1&(~INT0IS2);SFRPI=0

XICFGXICFG1(외부인터럽트 설정 레지스터)INT0IS2~0 플래그를 001로 설정하여 nINT0의 입력 핀을 P3.0으로 설정한다.

 

- Edge 설정

#define          INT_SetINT0_DetectEdge()                IT0=1

#define INT_SetINT0_DetectLowFalling()      AUXR0=AUXR0&(~INT0H)

IT0를 셋 시키면 falling edge에서 인터럽트가 발생하도록 해 준다. 만약 INT0H(AUXR0레지스터의 0번 비트)가 셋 되어 있으면 rising edge에서 인터럽트가 발생하도록 바뀐다.

IT01이면 Edge, 0이면 Level을 확인하여 인터럽트를 발생시키는 것을 선언하는 것이다.

 

- 필터 설정

#define INT_SetINT0Filter_SysclkDiv6_x3()               XICFG=XICFG&(~X0FLT);SFRPI=1;XICFG1=XICFG1|X0FLT1;SFRPI=0

INT0의 입력 필터 모드를 선택한다.

 

- INT1P15에 연결되며, INT0의 설정과 동일하다.

- INT2P16에 연결되며, INT0의 설정과 동일하다.

 

⑹ 인터럽트 초기화

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

*Function:   void InitInterrupt(void)

*Description:           Initialize Interrupt

*Input:  

*Output:    

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

void InitInterrupt(void)

{

           INT_EnINT0();                                                       // Enable INT0 interrupt

           INT_EnINT1();                                                       // Enable INT1 interrupt

           INT_EnINT2();                                                       // Enable INT2 interrupt

           INT_EnAll();                                                          // Enable global interrupt     

}

#define INT_EnINT0()            EX0=1

#define INT_EnINT1()            EX1=1

#define INT_EnINT2()            EX2=1

외부 인터럽트 인에이블 비트 EX0, EX1IE(인터럽트 인에이블 레지스터)에 있다.

외부 인터럽트 인에이블 비트 EX2XICON(외우 인터럽트 제어 레지스터)에 있다.

각각 0이면 인터럽트 Disable, 1이면 해당 인터럽트 Enable이다.

 

 

Enable Global Interrupt

#define INT_EnAll()                         EA=1              // Global enable

사용자가 설정한 시스템 인터럽트를 Enable 시킨다.

 

 

⑻ 인터럽트 루틴

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

*Function:   void INT_EXINT(void) 

*Description:   INT0 Interrupt handler

*Input:  

*Output:    

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

void INT_INT0(void)               interrupt INT_VECTOR_INT0

{

           WakeUpSorce=0;

           INTCnt=0;

           LED_G_0=1;LED_G_1=1;LED_R=1;

}

 

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

*Function:   void INT_EXINT(void) 

*Description:   INT1 Interrupt handler

*Input:  

*Output:    

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

void INT_INT1(void)               interrupt INT_VECTOR_INT1

{

           WakeUpSorce=1;

           INTCnt=0;

           LED_G_0=1;LED_G_1=1;LED_R=1;

}

 

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

*Function:   void INT_EXINT(void) 

*Description:   INT2 Interrupt handler

*Input:  

*Output:    

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

void INT_INT2(void)               interrupt INT_VECTOR_INT2

{

           WakeUpSorce=2;

           INTCnt=0;

           LED_G_0=1;LED_G_1=1;LED_R=1;

}

- 각각의 인터럽트에 따라 WakeUpSorce 변수의 값이 틀리다. INT00, INT11, INT22로 저장한다.

- INTCnt를 초기화 시키고, 모든 LEDOFF 시킨다,

 

 

 

 

4. 프로그램 실행

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

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

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\ MG82F6D16_INT_nINTx_WakeUP\KeilPrj

 

 

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

 

 

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

 

 

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

 

 

 

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

5. 동작 영상

 

https://youtu.be/jNyVtws2TKg

 

반응형