해보기는 했어?

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

MEGAWIN

MG82F6D Series INT KBI Wake UP

롬돌이 2022. 12. 19. 11:08
반응형

1. 프로그램 개요

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

KBI0, KBI1 P10, P11에 연결되어 있다. KBI 인터럽트가 발생하면 LED_RON 시키고, 인터럽트 플래그를 클리어 시킨다. 그 뒤 LED_ROFF 시킨다.

메인 루틴에서는 MCKOSCin으로 설정하고, 파워다운 모드로 들어간다. KBI를 통해 wake up 되면 클럭 부분에 대해 다시 설정을 하고, LED_G_1을 두 번 깜빡인다.

 

2. 회로도

3. Code

main routine

void main()

{

         u8 KBICnt=0;

         u8 BakCKCON2;

         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

 

        while(1)

        {

                  KBICnt=100;                             // 시스템 딜레이

                  while(KBICnt!=0)

                  {

                           DelayXus(100);

                           KBICnt--;

                  }

                 

                  // MCK=OSCin

                  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)

 

                  LED_G_1=0;                                       // wake up LED 깜빡임

                  DelayXms(500);                                  // Key를 계속 누르고 있으면 인터럽트가 계속 발생하게 되어

                  LED_G_1=1;                                       // LED_G_1은 계속 켜져 있게 된다.

                  DelayXms(500);

                  LED_G_1=0;

                  DelayXms(500);

                  LED_G_1=1;

    }

}

⑵ 시스템 초기화 루틴

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

*Function:   void InitSystem(void)

*Description:           Initialize MCU

*Input:  

*Output:    

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

void InitSystem(void)

{

 

           InitPort();

           InitClock();

           InitKBI();

           InitInterrupt();

 

           INT_EnAll();  // Enable global interrupt

}

- 포트 설정을 수행한다.

- Clock 설정.

- KBI 초기화

- 인터럽트 설정

- 인터럽트 동작 설정

 

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);                                                    // Set P10 as open-drain with pull-high, For KBI.

è P10, P11 Pull-Up이 추가된 Open Drain으로 설정하고 Key 입력으로 사용한다.

}

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

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

}

 

 

 

KBI 초기화

 

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

*Function:   void InitKBI(void)

*Description:           Initialize KBI

*Input:  

*Output:    

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

void InitKBI(void)

{

           KBI_SetKBMask(KBI0|KBI1);                                  // Enable channel KBI0,KBI1

           KBI_SetKBI01P10P11();                                          // KBI0,KBI1 set to P10,P11

           KBI_SetKBPattern(KBI0_1|KBI1_1);                          // KBI Pattern is 1

           KBI_SetPatternNotEqual();                                     // Pattern Matching polarity selection : not equal

           KBI_SetFilter_Sysclk_x3();                                      // KBI Filter: SYSCLK x3

}

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

#define KBI_SetKBMask(x)                                              KBMASK=x

- KBMASK 레지스터는 키패드 인터럽트 마스크 레지스터이다. reset 값은 0x00이다. 사용하고자 하는 채널을 셋 시켜 활성화 시킨다.

- 포트 설정

#define KBI_SetKBI01P10P11()                                          SFRPI=3;AUXR6=AUXR6&(~(KBI0PS0));SFRPI=0

사용할 포트 설정은 SFR Page 3에 위치한 AUXR6 레지스터를 이용한다.

KBI0PS0 KBI0~1의 핀을 설정한다. 클리어시켰으므로 P1.0, P1.1을 사용한다.

- 패턴 설정

#define KBI_SetKBPattern(x)                                           KBPATN=x

KBPATN 레지스터는 키패드 패턴 레지스터로, 대응되는 키 입력을 사용하기 위하여 설정해 두어야한다.

- 인터럽트 발생 설정

#define KBI_SetPatternNotEqual()                         KBCON=KBCON&(~PATN_SEL)

KBCON 레지스터(키패드 제어 레지스터)PATN_SEL 비트를 클리어 시켜 KBPATN에 사용자가 정의한 키패드 패턴과 키패드 입력이 서로 틀리면 인터럽트를 발생시킨다.

- 필터 설정

#define KBI_SetFilter_Sysclk_x3()                           KBCON=(KBCON&(~(KBCS0|KBCS1)))|(KBCS0)

KBCON KBCS0만 셋 시켜 KBI 입력 필터 모드를 SYSCLKx3으로 설정한다. 필터에 대한 설명은 자세하지 않다.

 

è (EN)MG82F6D16_Datasheet_V051.PDF22. Keypad Interrupt(KBI)를 참조한다.

è (EN)MG82F6D17_Datasheet_V051.PDF23. Keypad Interrupt(KBI)를 참조한다.

è (EN)MG82F6D64/32_Datasheet_V051.PDF23. Keypad Interrupt(KBI)를 참조한다.

 

⑹ 인터럽트 초기화

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

*Function:   void InitInterrupt(void)

*Description:           Initialize Interrupt

*Input:  

*Output:    

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

void InitInterrupt(void)

{

           INT_EnKBI();                                   // Enable KBI interrupt

}

- Key board Input interrupt를 활성화시킨다.

 

Enable Global Interrupt

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

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

 

KBI 인터럽트 루틴

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

*Function:   void INT_KBI(void)     

*Description:   KBI Interrupt handler

*Input:  

*Output:    

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

void INT_KBI(void)                 interrupt INT_VECTOR_KB

{

           if(KBCON&KBIF==KBIF)                    // KBI 인터럽트 플래그가 셋 되어 있으면

           {

                     LED_R=0;                             // LED_R ON 시키고

                     KBCON&=(~KBIF);               // clear KBI interrupt flag

                     LED_R=1;                             // LED_ROFF 시킨다.

           }

}

- 발생한 인터럽트 플래그를 클리어 시켜주어 다음 입력을 대비한다.

 

4. 프로그램 실행

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

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

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

해당 폴더의 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/sp6Kl1rgjkM?feature=share

 

 

반응형

'MEGAWIN' 카테고리의 다른 글

MG82F6D Series PCA COPM Buf  (0) 2022.12.21
MG82F6D Series PCA Capture Buf  (0) 2022.12.20
MG82F6D Series IAP Sample  (0) 2022.12.16
MG82F6D Series IAP LOOP  (0) 2022.12.15
MG82F6D Series TIM_T2_Mode4_PWM  (0) 2022.12.13