Programming/8051

8051( 중급 12부 - serial 통신 2 )

청솔1 2009. 11. 29. 16:11

8051( 중급 12부 - serial 통신 2 )


 11부 강좌에서 수신 인터럽트 처리와 polling에 의한 송신 함수를 소개 했다.
 이번 강좌에서도 송신이 polling이긴 하지만 보다 효율적으로 Queue를 이용해서 송신 하
는 방법을 소개 함다.
 지난 강좌에서의 송신은 한바이트 송신 한 다음 다시 Tx_ready가 세트 되기를 기다렸다가
다음 바이트를 송신 하는식으로 되어 있어서 문자열을 송신 하려면 상당한 시간을 스탠바이
상태로 기다려야 함다.
 이러한 방식은 여러가지 task를 수행해야 하는 마이컴 입장에서는 시간 낭비적인 요소가 강
함다. 물론 간단한 프로그램에서는 무시 할수 있는 시간이긴 하지만 말임다.
 그래서 이번에 소개 하는 함수는 송신 할 문자열이 있으면 일단 송신 Queue에 넣어 줌다.
 main 함수에서는 먼저 Tx_ready를 조회하여 송신 가능한지 여부를 살펴 보고 송신이 가능하
다면 송신 Queue의 인덱스인 COM_tx_head와 COM_tx_tail값을 조회 합니다.
 만일 두 값이 같다면 더이상 송신할 데이터가 없다는 애기이고 틀리다면 송신할 데이터가 있
다는 애기 임다. 송신할 데이터가 있을경우 Queue에서 한바이트를 끄집어 내어 송신 해줌다.
 다음 송신 데이터를 송신할때까지 마이컴은 다른 일을 수행할수 있슴다. 다시 Tx_ready가
세트 되기 전까지 말임다. 이러한 함수를 사용하면 보다 효율적으로 시간 낭비 없는 프로그램
을 작성 할수 있슴다.
#define BUF_SIZE        128
#define COM_ready()     ( Tail  == Head ) ? 0 : -1
#pragma memory = default
/*-------------------------------bit 영역---------------------*/
bit Tx_ready;
/*-------------------------------외부램영역---------------------*/
#pragma memory = default
xdata unsigned char Queue[ BUF_SIZE ];
xdata unsigned char COM_tx_queue[ BUF_SIZE ];    /* COM2_buffered_puts */
xdata int COM_tx_head, COM_tx_tail;
/*-------------------------------code 영역 ---------------------*/
#pragma memory = code
unsigned char Ver_str[] = "  [ transmitt Queue test ]  ";
#pragma function = interrupt
void SCON_int( void ) {
    if( RI == 1 ) {           /* 수신 인터럽트 발생시 */
        RI = 0;
        Queue[ Head ] = SBUF;
        Head ++;              /* 인덱스 증가  */
        Head %= BUF_SIZE;     /* modular 연산 */
        }
    else if( TI == 1 ) {      /* 송신 인터럽트 발생시 */
        TI = 0;
        Tx_ready = 1;         /* bit 변수 */
        }
    }
#pragma function = default
void Init_COM( void ) {
    /* 2400 baud rate */
    Head   = 0;
    Tail   = 0;
    SCON    = 0x52;
    TH1     = 244;
    TR1     = 1;
    TI      = 1;
    RI      = 0;
    }
void Timer_init( void ) {
    TMOD = 0x21;    /* timer 1 8bit auto reload timer */
                    /* timer 0 16 bit timer */
    TH0  = 0xee;
    TL0  = 0x00;
    TR0  = 1;
    ET0  = 1;
    }
unsigned char COM_read( void ) {
    unsigned char in_data;
    in_data = Queue[ Tail ];
    Tail ++;					/* 인덱스 Tail 증가 */
    Tail %= BUF_SIZE;           /* modular 연산     */
    return in_data;
    }
/* 한 문자를 송신 하는 함수 */
void COM_putc( xdata unsigned char ch ) {
    while( Tx_ready == 0 );        /* 송신 가능한지를 검사 */
    Tx_ready = 0;                  /* 송신 완료를 확인 하기 위해 0으로 클리어 */
    SBUF = ch;                     /* 송신이 되면 인터럽트 루틴에서 1로 세트 */
    }
/* 문자열을 송신 하는 함수 */
void COM_puts( xdata unsigned char *str ) {
    int i;
    for(i=0;str[ i ] != 0;i++) {   /* 문자열 끝인  null을 확인 할때 까지 반복 */
        while( Tx_ready == 0 );
        Tx_ready = 0;
        SBUF = str[ i ];
        }
    }
/* 1 바이트를 송신 Queue에 넣는 함수 */
void COM_buffered_putc( xdata unsigned char c ) {
    COM_tx_queue[ COM_tx_head ++ ] = c;    /* 송신 Queue에 저장한다. */
    COM_tx_head %= BUF_SIZE;             /* modular 연산           */
    }
/* 문자열을 송신 Queue에 넣는 함수 */
void COM_buffered_puts( xdata unsigned char *str ) {
    int i;
    for(i=0;str[ i ] != 0; i++ ) {
        COM_tx_queue[ COM_tx_head ++ ] = str[ i ];
        COM_tx_head %= BUF_SIZE;
        }
    }
void main( void ) {
 	unsigned char temp;
     /*---- 각종 변수 초기화 ----*/
    Head = Tail = 0;
    Tx_ready = 1;
    COM_tx_head = COM_tx_tail = 0;
    /*---- 인터럽트 초기화 ----*/
    Timer_init();
    Init_COM();
    ES      = 1;
    PS      = 1;
    EA      = 1;
    COM_buffered_puts( Ver_str );
    /*---- 메인 처리 루틴 ----*/
    for(;;)  {
        if( COM_ready() ) {
            temp = COM_read();
            COM_putc( temp );
            }
        if( Tx_ready ) {  /* 송신 가능 상태 인가? */
            /* 송신 큐에 데이터가 남아 있는가?    */
            if( COM_tx_head != COM_tx_tail ) {
                COM_putc( COM_tx_queue[ COM_tx_tail ++ ] );
                COM_tx_tail %= BUF_SIZE;   /* modular 연산 */
                }
            }
        /* 그외 나머지 루틴을 처리 */
        ...........................
        ...........................    
        }
    }
이와 같은 함수를 이용하면 사용자는 임의의 시점에 송신 하고자 하는 문자열을 COM_buffered_puts() 함수를 사용하여 Queue에 넣어 주기만 하면 됨다. 이때 중요한것은 Queue의 용량이 문제가 될수 있슴다. 그점만 주의 한다면 훌륭한 시리얼 프로그램을 작성하실수 있을검다. 그리고 시리얼 데이터를 하나의 패킷화 하여 처리 하는 방법은 이미 8부에서 소개한바 있슴다. 차근 차근 순서대로 강좌가 진행 되지 못해 매끄럽지 못한점 양해를 구함다.

'Programming > 8051' 카테고리의 다른 글

8051의 타이머 0  (0) 2009.11.30
8051타이머 모드설정  (0) 2009.11.30
8051( 중급 11부 - serial 통신 )  (0) 2009.11.29
8051( 중급 10부 - A/D )   (0) 2009.11.29
8051( 중급 9부 - Graphic LCD )  (0) 2009.11.29