1. 프로그램 개요
P22는 Green 0 LED, P24는 Red LED, P26은 Green 1 LED가 연결되어 있다.
P10, P11을 아날로그 입력으로 설정한다. P10은 비교기의 Positive input, P11은 비교기의 Negative Input으로 설정한다.
인터럽트가 발생하면 LED를 Toggle 시킨다.
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.PDF의 “제 13절 Configurable I/O Ports”를 참조한다.
è (EN)MG82F6D17_Datasheet_V051.PDF의 “제 14절 Configurable I/O Ports”를 참조한다.
è (EN)MG82F6D64/32_Datasheet_V051.PDF의 “제 14절 Configurable I/O Ports”를 참조한다.
- P22, P24, P26은 Push-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를 이용해서 UART0의 Baud 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을 제어가능하게 된다. CPU는 S0CR1을 읽고 쓰기 위해SFR어드레스 0xB9을 제어한다.
- UART0를 MODE 1으로 설정한다.
#define UART0_SetMode8bitUARTVar() S0CFG=S0CFG&(~SM30);SM00_FE=0;SM10=1
SM30 비트 클리어, SM00비트 클리어, SM10 비트 셋 시킴으로서 MODE 1으로 설정한다. Mode 1은 8-bit UART이고, Baud Rate는 가변이 된다.
- UART0의 Receive Enable
#define UART0_EnReception() REN0=1
UART0이 시리얼 통신으로 데이터를 받아들일 수 있도록 설정한다. S0CON 레지스터의 REN0를 셋(=1) 시킨다.
- UART0의 Baud Rate를 S0BRG를 이용한다.
#define UART0_SetBRGFromS0BRG() S0CR1=S0CR1|(S0TCK|S0RCK)
앞서 S0CR1을 제어 가능하도록 설정해 두었으며, S0TCK, S0RCK를 셋 시킴으로써 S0BRG의 Overflow를 UART0의 송신/수신 클럭으로 사용하도록 설정한다.
- Baud Rate를 2배로 설정한다.
#define UART0_SetS0BRGBaudRateX2() PCON0=PCON0&(~SMOD1);S0CFG=S0CFG|(SMOD2)
SMOD1을 클리어 시켜 Double Baud Rate를 Disable 시키고, SMOD2를 셋 시켜 향상된 기능의 UART를 사용한다. Baud Rate는 Double 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
위의 수식으로 계산 시 S0BRT는 177.875가 나온다. 따라서 9600 Baud Rate를 위해서는 178(0xB2)을 S0BRT, S0BRC에 초기값으로 저장한다.
- S0BRG를 동작시킨다.
#define UART0_EnS0BRG() S0CR1=S0CR1|S0TR
è (EN)MG82F6D16_Datasheet_V051.PDF의 17. Serial Port 0(UART0)를 참조한다.
è (EN)MG82F6D17_Datasheet_V051.PDF의 18. Serial Port 0(UART0)를 참조한다.
è (EN)MG82F6D64/32_Datasheet_V051.PDF의 18. 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.0을 Postive 입력으로 설정한다.
- Negative Input Pin 설정
#define AC0_SetNegaReferenceVoltage_AC0NI() AC0MOD=AC0MOD&(~(NVRS0|NVRS1|NVRS2|NVRS3|NVRL))
AC0MOD레지스터의 5~7번 비트인 NVRS0 ~NVRS3, 그리고 3번 비트인 NVRL을 클리어 시킨다. Negative Input Pin은 P1.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)에는 1Hz의 Vpp 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 Board에 USB Connector를 연결하여 전원을 인가하고, 전원 스위치를 ON시키고, OCD ICE를 연결한 상태에서 위 이미지의 Start/Stop Debug Session(Ctrl+F5) 버튼을 눌러 컴파일된 프로젝트의 디버그 데이터를 다운로드 시킨다.(컴파일 시 에러가 발생하지 않아야함)
다운로드 후 Run(F5) 버튼을 클릭하면 프로그램이 동작한다.
5. 동작 영상
'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 |