MEGAWIN

MG82F6D Series UART0 TX RX INT

롬돌이 2022. 12. 2. 10:40
반응형

1. 프로그램 개요

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

UART0을 인터럽트 방식으로 송/수신하는 것을 테스트 한다.

 

 

2. 회로도

                         

 

 

 

 

3. Code

main routine

void main()

{

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

         Uart0RxIn=0;                            // 변수 초기화

         Uart0RxOut=0;

         Uart0TxIn=0;

         Uart0TxOut=0;

         bUart0TxFlag=0;

        

         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

 

         Uart0SendStr("Start!\n");              // 시리얼로 시작을 알리는 문자 전송

 

         while(1)

         {

                  if(LedTime==0)                         // LED Timer

                  {

                           LedTime=100;

                           LED_G_0 = !LED_G_0;         // LED_G_0토글

                  }

                  if(Uart0RxIn != Uart0RxOut)                            // UART0 수신 버퍼 길이와 UART0 수신버퍼 읽기 길이가 틀리면

                  {

                           Uart0SendByte(RcvBuf[Uart0RxOut]);                 // 한 바이트를 전송하고,

                           Uart0RxOut++;                                   // UART0 수신버퍼 읽기 변수 1ㅈㅇㄱ

                           if(Uart0RxOut>=UART0_RX_BUFF_SIZE)      // UART0  버퍼크기보다 변수 값이 크면 클리어 시킨다.

                           {

                                   Uart0RxOut=0;

                           }

                  }

 

         }

 

}

⑵ 시스템 초기화 루틴

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

*Function:   void InitSystem(void)

*Description:           Initialize MCU

*Input:  

*Output:    

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

void InitSystem(void)

{

           InitPort();

           InitTimer0();

           InitUart0_S0BRG();

           InitInterrupt();

}

- 포트 설정을 수행한다.

- 타이머 0 초기화

- USR0S0BRG 초기화

- 인터럽트 동작 설정

 

 

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로 설정한다.

}

 

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

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

 

⑷ 타이머 0 초기화

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

*Function:   void InitTimer0(void)

*Description:   Initialize Timer0

*Input:  

*Output:    

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

void InitTimer0(void)

{

           TM_SetT0Mode_1_16BIT_TIMER();                                                // TIMER0 Mode: 16-bit

           TM_SetT0Clock_SYSCLKDiv12();                                                 // TIMER0 Clock source: SYSCLK/12

           TM_SetT0Gate_Disable();                                                                      // TIMER0 disable gate

          

           TM_SetT0LowByte(TIMER_12T_1ms_TL);                                      // Set TL0 value

           TM_SetT0HighByte(TIMER_12T_1ms_TH);                                      // Set TH0 value

          

           TM_EnableT0();                                                                                              // Enable TIMER0

}

 

- 타이머 0의 모드 설정

#define TM_SetT0Mode_1_16BIT_TIMER()                           TMOD=(TMOD&(~(T0M0|T0M1)))|(T0M0)

T0M1=0, T0M0=1로하여 모드 116비트 타이머로 설정한다.

- 타이머 0의 클럭 설정

#define TM_SetT0Clock_SYSCLKDiv12()   AUXR3=(AUXR3&(~T0XL));AUXR2=(AUXR2&(~T0X12));TMOD=(TMOD&(~T0C_T))

T0XL = 0, T0X12 = 0, T0C/T = 0으로 저장하여 타이머 0의 클럭을 (SYSCLK/12)로 결정한다.

SYSCLK 12MHz이므로, 타이머 0의 클럭은 1MHz이다. 따라서 타이머 01us마다 1씩 증가한다.

 

- 게이트 사용하지 않음

#define TM_SetT0Gate_Disable()                                                TMOD=TMOD&(~T0GATE)

타이머 0Gate를 사용하지 않는 것으로 설정한다.

 

- 1ms 타이머로 설정

#define TM_SetT0HighByte(x)                               TH0=x

#define TM_SetT0LowByte(x)                               TL0=x

타이머 01ms 타이머가 되도록 TH0, TL0에 초기값을 저장한다.

 

- 타이머 0 시작

#define TM_EnableT0()                              TR0=1

TR0를 셋 시켜 타이머 0을 동작 시킨다.

 

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을 제어가능하게 된다. CPU S0CR1을 읽고 쓰기 위해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) 시킨다.

 

- UART0 Baud Rate S0BRG를 이용한다.

#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

위의 수식으로 계산 시 S0BRT 177.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)를 참조한다.

 

 

 

 

 

 

⑹ 인터럽트 초기화

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

*Function:   void InitInterrupt(void)

*Description:           Initialize Interrupt

*Input:  

*Output:    

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

void InitInterrupt(void)

{

           INT_EnTIMER0();                                                                                             //           Enable TIMER0 interrupt

           INT_EnUART0();                                                                                              //           Enable UART0 interrupt

           INT_EnAll();                                                                                          //  Enable global interrupt

}        

- 타이머 0UART0 인터럽트를 초기화한다. 그리고 Global interrupt bit를 셋 시켜 인터럽트 수신이 시작되도록 한다.

#define INT_EnTIMER0()                  ET0=1

#define INT_EnUART0()                   ES0=1

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

 

 

⑺ 타이머 0 인터럽트 루틴

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

*Function:   void INT_T0(void)

*Description:   T0 Interrupt handler

*Input:  

*Output:    

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

void INT_T0(void) interrupt INT_VECTOR_T0

{

           TH0=TIMER_12T_1ms_TH;

           TL0=TIMER_12T_1ms_TL;

 

           if(LedTime!=0) LedTime--;

}

- 타이머 01ms 마다 인터럽트가 발생할 수 있도록 TH0, TL0에 값을 저장한다.

- LedTime0이 아니면 1 감소시킨다. LED에 관련된 딜레이 시간을 만들 수 있다.

 

UART 0 인터럽트 루틴

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

*Function:   void INT_UART0(void)

*Description:   UART0 Interrupt handler

*Input:  

*Output:    

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

void INT_UART0(void) interrupt INT_VECTOR_UART0

{

           if(TI0)                                                        // 송신 완료 플래그가 셋 되면

           {

              TI0 = 0;                                               // 플래그를 클리어 시키고

                     if(Uart0TxIn==Uart0TxOut)                // Tx 버퍼에 마지막 저장된 위치와 마지막 송신된 위치가 동일하면

                     {

                                bUart0TxFlag=FALSE; // Tx 플래그를 False로 설정하고

                     }

                     else

                     {

                                S0BUF=TxBuf[Uart0TxOut];  // 서로 다르면 송신해야할 위치의 데이터를 송신한다.

                                bUart0TxFlag=TRUE;             // Tx 플래그를 True로 설정하고

                                Uart0TxOut++;           // Tx 송신위치를 +1 시킨다.

                                if(Uart0TxOut>=UART0_TX_BUFF_SIZE)        // 만약 Tx 송신위치가 버퍼상이즈와 같거나 크면

                                {

                                          Uart0TxOut=0;                      // 그 값을 0으로 만들어 송신위치를 버퍼의 첫 번째로 수정한다.

                                }

                     }

           }

           if(RI0)                                                                  // 수신 인터럽트 플래그가 셋 되면

           {

                     RI0 = 0;                                           // 클리어 시켜 주고

                     RcvBuf[Uart0RxIn] = S0BUF;            // 시리얼로 받은 데이터를 버퍼에 저장시키고

                     Uart0RxIn++;                                              // 저장 위치를 +1 시킨다.

                     if(Uart0RxIn >=UART0_RX_BUFF_SIZE)          // 저장 위치가 RX 버퍼의 크기보다 크거나 같으면

                     {

                                Uart0RxIn =0;                                  // 저장 위치를 알려주는 변수를 0 으로 만든다.

                     }

                    

           }

}

 

- /수신 모드 각각의 링버퍼를 갖고 있도록 설계되었다.

 

 

 

 

 

 

4. 프로그램 실행

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

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

\Megawin 8051\(EN)MG82F6D16_SampleCode_v1.20\ MG82F6D16_UART0_RX_TX_INT\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/W5FgMpS2tnQ?feature=share

 

 

반응형