해보기는 했어?

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

MEGAWIN

MG82F6D Series CMP

롬돌이 2022. 11. 24. 14:13
반응형

1. 프로그램 개요

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

P10, P11을 아날로그 입력으로 설정한다. P10은 비교기의 Positive input, P11은 비교기의 Negative Input으로 설정한다.

인터럽트가 발생하면 LEDToggle 시킨다.

 

 

2. 회로도

/* LED 부분 회로도 추가 */

 

3. Code

main routine

void main()

{

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

           printf("\nHello");                                 // 프로그램의 시작을 알리는 메시지

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

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

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

 

           INT_EnAll();                                       // Enable global interrupt

    while(1)

    {

                     DelayXms(200);                         // 200ms Delay

                     LED_G_0=!LED_G_0;                   // LED_G_0 Toggle

    }

}

 

⑵ 시스템 초기화 루틴

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

*Function:   void InitSystem(void)

*Description:           Initialize MCU

*Input:  

*Output:    

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

void InitSystem(void)

{

 

           InitPort();                             // 포트 초기화 루틴

           InitUart0_S0BRG();                // S0BRG를 이용한 UART0

           InitCMP();                            // CMP(비교기설정)

           InitInterrupt();                       // 인터럽트 초기화

}

 

 

 

각각의 루틴들을 확인해 보도록 한다.

⑶ 포트 초기화 루틴 è 회로도를 보면서 각 입출력 핀의 속성을 지정한다.

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

*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.

           PORT_SetP1AInputOnly(BIT0|BIT1);                                 // Set P10,P11 as Analog-Input-Only,For CMP input.

}

è (EN)MG82F6D16_Datasheet_V051.PDF13Configurable I/O Ports”를 참조한다.

è (EN)MG82F6D17_Datasheet_V051.PDF14Configurable I/O Ports”를 참조한다.

è (EN)MG82F6D64/32_Datasheet_V051.PDF14Configurable I/O Ports”를 참조한다.

 

- P22, P24, P26Push-Pull type으로 설정한다.(LED연결)

#define PORT_SetP2PushPull(x)                           P2M0=P2M0|(x); SFRPI=1;P2M1=P2M1&(~(x));SFRPI=0

Port 2의 핀들을 Push-Pull 속성으로 설정하려면 P2M0의 해당 비트는 1(set), P2M1의 해당비트는 0(clear)로 각각 설정하면 된다.

P2M1 레지스터는 SFR Page 1에서만 설정이 가능하므로 위 매크로에서 보면 SFRPI=1, SFRPI=0의 코드가 추가되었다.

정상적인 동작을 위하여 SFRPI default 0으로 항상 유지시킨다.

 

- P10, P11 핀을 아날로그 입력 전용 핀으로 설정한다.

#define PORT_SetP1AInputOnly(x)                                 P1M0=P1M0&(~(x));P1M1=P1M1|(x)

Port 1은 디지털 입/출력으로도 사용이 가능하나 아날로그 입력 핀의 기능도 할 수 있다. P1M0의 해당 비트는 0(clear), P1M1의 해당 비트는 1(set)로 설정하면 아날로그 입력핀으로 설정이 된다.(default)

*** 위 매크로함수는 “API_Macro_MG82FG6D16.H”에서 찾아볼 수 있다.(각각의 IC별로 선언된 API_Macro_MG82FG6Dxx.H를 찾아본다.)

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

 

 

UART0초기화 èS0를 이용해서 UART0Baud Rate를 설정한다.

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

*Function:              void InitUart0_S0BRG(void)

*Description:          Initialize Uart0, The source of baud rate was S0BRG

*Input:  

*Output:    

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

void InitUart0_S0BRG(void)

{       

         UART0_SetAccess_S0CR1();                    // Enable access S0CR1

         UART0_SetMode8bitUARTVar();              // UART0 Mode: 8-bit, Variable B.R.

         UART0_EnReception();                                   // Enable reception

         UART0_SetBRGFromS0BRG();                  // B.R. source:S0BRG

         UART0_SetS0BRGBaudRateX2();                       // B.R. x2

         UART0_SetS0BRGSelSYSCLK();                         // S0BRG clock source: SYSCLK

 

    // Sets B.R. value

         UART0_SetS0BRGValue(S0BRG_BRGRL_9600_2X_12000000_1T);

        

         UART0_EnS0BRG();                                       // Enable S0BRG

}

- UART0 MODE 설정

#define UART0_SetAccess_S0CR1()                            S0CFG=S0CFG|(SMOD3)

S0CFG 레지스터의 0번 비트인 SMOD3을 셋 시킴으로써 S0CR1을 제어가능하게 된다. CPUS0CR1을 읽고 쓰기 위해SFR어드레스 0xB9을 제어한다.

- UART0MODE 1으로 설정한다.

#define UART0_SetMode8bitUARTVar()                       S0CFG=S0CFG&(~SM30);SM00_FE=0;SM10=1

SM30 비트 클리어, SM00비트 클리어, SM10 비트 셋 시킴으로서 MODE 1으로 설정한다. Mode 18-bit UART이고, Baud Rate는 가변이 된다.

 

- UART0 Receive Enable

#define UART0_EnReception()                                           REN0=1

UART0이 시리얼 통신으로 데이터를 받아들일 수 있도록 설정한다. S0CON 레지스터의 REN0를 셋(=1) 시킨다.

 

- UART0Baud RateS0BRG를 이용한다.

#define UART0_SetBRGFromS0BRG()                                            S0CR1=S0CR1|(S0TCK|S0RCK)                

앞서 S0CR1을 제어 가능하도록 설정해 두었으며, S0TCK, S0RCK를 셋 시킴으로써 S0BRGOverflowUART0의 송신/수신 클럭으로 사용하도록 설정한다.

 

- Baud Rate2배로 설정한다.

#define UART0_SetS0BRGBaudRateX2()                       PCON0=PCON0&(~SMOD1);S0CFG=S0CFG|(SMOD2)

SMOD1을 클리어 시켜 Double Baud RateDisable 시키고, SMOD2를 셋 시켜 향상된 기능의 UART를 사용한다. Baud RateDouble Baud Rate x 2가 된다.

 

- S0BRG의 클럭 설정

#define UART0_SetS0BRGSelSYSCLK()                         S0CR1=S0CR1|(S0TX12)

S0BRG의 클럭을 SYSCLK를 사용하도록 한다.

 

 

- Baud Rate : 9600 설정

#define S0BRG_BRGRL_9600_2X_12000000_1T             0xB2        // 0.16%

#define UART0_SetS0BRGValue(x)                              S0BRT=x;S0BRC=x

위의 수식으로 계산 시 S0BRT177.875가 나온다. 따라서 9600 Baud Rate를 위해서는 178(0xB2)S0BRT, S0BRC에 초기값으로 저장한다.

 

- S0BRG를 동작시킨다.

#define UART0_EnS0BRG()                                               S0CR1=S0CR1|S0TR

 

è (EN)MG82F6D16_Datasheet_V051.PDF17. Serial Port 0(UART0)를 참조한다.

è (EN)MG82F6D17_Datasheet_V051.PDF18. Serial Port 0(UART0)를 참조한다.

è (EN)MG82F6D64/32_Datasheet_V051.PDF18. Serial Port 0(UART0)를 참조한다.

 

 

CMP 초기화

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

*Function:   void InitCMP(void)

*Description:          Initialize CMP

*Input:  

*Output:    

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

void InitCMP(void)

{

         AC0_Enable();                                             // Enable CMP0

         AC0_SetInterruptMode_Rising();                       // Set interrupt mode:Rising edge

         AC0_SetPosInputP10();                                  // Positive: P10

         AC0_SetNegaReferenceVoltage_AC0NI();            // Negative: P11

}

- CMP0 초기화

#define AC0_Enable()                                                              AC0CON=AC0CON|AC0EN

아나로그 비교기0(AC0)이 동작할 수 있도록 설정한다.

- 상승 에지에서 인터럽트가 발생하도록 함

#define AC0_SetInterruptMode_Rising()                               AC0CON=AC0CON&(~(AC0M0|AC0M1))|(AC0M1)

AC0CON 레지스터의 0~1번 비트를 이용해서 AC0인터럽트 모드를 설정한다.

 

- Positive Input Pin 설정

#define AC0_SetPosInputP10()                                                   AC0MOD=AC0MOD&(~(AC0PIS0|AC0PIS1))

AC0MOD 레지스터의 0~1번 비트인 AC0PIS0, AC0PIS1 비트를 클리어 시켜 P1.0Postive 입력으로 설정한다.

 

- Negative Input Pin 설정

#define AC0_SetNegaReferenceVoltage_AC0NI()                     AC0MOD=AC0MOD&(~(NVRS0|NVRS1|NVRS2|NVRS3|NVRL))

AC0MOD레지스터의 5~7번 비트인 NVRS0 ~NVRS3, 그리고 3번 비트인 NVRL을 클리어 시킨다. Negative Input PinP1.1로 설정된다.

 

 

 

CMP0 인터럽트 설정

 

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

*Function:   void InitInterrupt(void)

*Description:           Initialize Interrupt

*Input:  

*Output:    

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

void InitInterrupt(void)

{

           INT_EnAC0();                                                                                                  // Enable CMP0 interrupt

}        

#define INT_EnAC0()                       EIE1=EIE1|EAC0

EIE1 레지스터의 7번 비트인 CMP0 인터럽트 Enable 비트를 셋 시킨다.

 

CMP0 인터럽트 루틴

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

*Function:   void INT_AC0(void)

*Description:   AC0  Interrupt handler

*Input:  

*Output:    

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

void INT_AC0(void) interrupt INT_VECTOR_AC0

{

           if((AC0CON&AC0F)==AC0F)

           {

                     LED_R=!LED_R;

                     AC0CON=AC0CON&(~AC0F);                     // clear AC0 interrupt flag

           }

}

- AC0CON 레지스터의 4번 비트인 AC0F 플래그가 셋 되어 있으면

- LED_R을 토글 시키고

- 인터럽트 플래그를 클리어 시킨다.

4. 프로그램 실행

Positive Input(P10)에는 약 3.2Vdc 전압을 입력함

Negative Input(P11)에는 1HzVpp 5V 펄스를 입력함

AC0 인터럽트 루틴에서 LED를 토글 시켜 두었음

프로그램 동작 시 해당 LED가 토글 되는 것을 확인함

 

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

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

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\MG82F6D16_CMP\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/Za6fwLIoreE

 

반응형

'MEGAWIN' 카테고리의 다른 글

MG82F6D Series BOD  (0) 2022.11.28
MG82F6D Series INT nINTx Wake UP  (0) 2022.11.25
MG82F6D Series TIM_T0T1_Mode 0  (0) 2022.11.23
MG82F6D Series TIM_T2_Mode2_Capture  (0) 2022.11.22
MG82F6D Series WDT Reset  (0) 2022.11.17