아두이노 시리얼 통신( PC <-> 아두이노 )

Software/Arduino|2023. 1. 17. 10:44
반응형

아두이노와 외부 디바이스 또는 PC 와 RS232 통신을 하기위한 방법을 설명합니다.

제 블로그에서는 가급적 실사용 위주를 중심으로 코드를 올립니다. 큰 틀은 가져가시고 세부적인 부분만 수정하셔도 동작에 지장이 없으실 겁니다. 

하기의 코드는 실제 개발 제품에 사용했던 것으로 PC가 Master 이고 아두이노가 Slave 인 구성에서의 코드입니다. 

아두이노가 Master 가 되는 상황에서 다른 디바이스를 제어할 경우는 코드 구성이 좀 틀립니다. 

또한 하기 코드의 프로토콜에는 별도의 오류 체크를 포함하지 않았지만 통신 오류를 줄이기 위해 Check Sum 이나 CRC 등의 오류 체크를 포함할 수도 있습니다. 

#define     STX             0x02
#define     ETX             0x03
#define     BUFFER_MAX      20              // 수신버퍼 최대 용량 

const int COMM_CTRL        = 3 ;			// MAX485 RX/TX Control

volatile int Comm_Index = 0 ;					// Receive buffer Index Pointer 
volatile boolean stringComplete = false ;   	// 수신 데이타가 다 들어왔는지 확인한다.
volatile boolean serial_start = false ;

char Receive_Buffer[BUFFER_MAX] ;
char Send_Buffer[7] = {STX, 0x30, 0x31, 'I', 'O', 'K', ETX} ;	            // Serial 송신 버퍼

//--------------------------------------------------------------------------------
void setup() 
{
    Serial.begin(9600);         // set serial communication (9600 bps)

    pinMode(COMM_CTRL, OUTPUT) ;  // RS485 통신의 경우 송,수신 전환 단자제어 
    digitalWrite(COMM_CTRL, LOW);    
}
//--------------------------------------------------------------------------------
void loop() 
{
    if(stringComplete == true)      // 통신 패킷이 모두 들어왔다. 
    {
        if(Receive_Buffer[1] == 0x30 && Receive_Buffer[2] == 0x31)    // 자신의 데이타가 맞다. 
        {
            switch(Receive_Buffer[3])   // 수신된 명령어???
            {
                case 'I' : Initialize() ;       // initialize  
                           break ;                            
                case 'P' : function1() ;
                           break ;
                case 'R' : function2() ;
                           break ;
                case 'T' : function3() ;
                           break ;
                case 'S' : function4() ;
                           break ;                           
                default  : Error() ;
                           break ;
            }
            
            Send_Action_Result() ;   // 수신에 대한 응답 메시지 송신
        }
        memset(Receive_Buffer, 0x00, sizeof(Receive_Buffer)) ;  // 수신 버퍼 Clear 
        stringComplete = false ;   // 시리얼 입력에 대한 작업이 종료 되었다. 
    }
}
//--------------------------------------------------------------------------------
void Send_Action_Result(void)
{
  /****************************************
    function : 시리얼 포트로 수신결과에 대한 응답을 보낸다.
  ****************************************/
    int count ;

    digitalWrite(COMM_CTRL, HIGH)  ;    // RS485 통신칩의 송/수신 컨트롤 단자 제어용입니다. 
                                        // 경우에 따라 없을 수도 있습니다. 
    for (count = 0 ; count < 7 ; count++)
    {
        Serial.write(Send_Buffer[count]) ;    // 송신 버퍼의 내용을 시리얼로 전송합니다.
    }

    delay(10) ;		// RS485 통신의 경우 이걸 해 주어야만 컨트롤 단자가 LOW 로 떨어지지 않는다.

    digitalWrite(COMM_CTRL, LOW)  ;
}
//------------------------------------------------------------------------------------
void function1() {} 
void function2() {} 
void function3() {} 
void function4() {} 
//------------------------------------------------------------------------------------
void Error(void)
{
    Send_Buffer[3] = 'N' ;    // NAK 반송  
    Send_Buffer[4] = 'A' ;    
    Send_Buffer[5] = 'K' ;
}
//-------------------------------------------------------------------------------- 
void Initialize(void)
{
    /* 명령어 수행 루틴 작성 */

    Send_Buffer[3] = 'I' ;    // 반송 명령어 
    Send_Buffer[4] = 'O' ;    // OK : 명령을 정상적으로 수행했다. 
    Send_Buffer[5] = 'K' ;
}
//-------------------------------------------------------------------------------- 
void serialEvent()   // 시리얼 포트의 입력 인터럽트 
{
    if (stringComplete == false)
    {
        char inChar = (char)Serial.read() ;

        if (inChar == STX && serial_start == false)      // 시리얼 포트로 데이타가 들어오기 시작 
        {
            serial_start = true ;
            Comm_Index = 0 ;
        }

        Receive_Buffer[Comm_Index] = inChar ;

        if (Receive_Buffer[Comm_Index] == ETX)          // 시리얼 포트로 데이타가 모두 들어왔다.        
        {
            stringComplete = true ;
            serial_start = false ;
        }

        Comm_Index ++ ;

        if (Comm_Index >= BUFFER_MAX) Comm_Index = 0 ;
    }
}
//--------------------------------------------------------------------------------

 

반응형

댓글()