ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Firmware 엔지니어를 위한 Communication 구현
    Electron 2015. 5. 19. 16:39
    Firmware 엔지니어를 위한 Communication 구현
    [전기기술정보] i8051/AVR
    [전기기술정보] Dual UART
    [전기기술정보] RS-485
    [전기기술정보] MODEM


    Firmware 엔지니어를 위한 Communication 구현

    최근 계속해서 발전해온 통신 관련 알고리즘은 장비와 장비, 비동기/동기 및 PC와의 통신을 필요로 한다. 특히 막연히 버퍼를 확인하는 Poling같은 원시적인 방법이 아니라 멀티 태스킹의 모습으로 프로그램 해야 하는 알고리즘이 필요하다. 이와 관련, 본 고에서는 하드웨어와 소스 코드에 관련된 통신 방법을 중점적으로 고찰해 보고자 한다. 그밖에 자세한 문의는 동호회 www.icbank.com/community/Conan을 이용하기 바란다.

    김형태,
    (주)마이크로비젼 수석팀장(conan@microvision.co.kr)

    i8051 및 AVR
    인텔 8051 통신 모드에서 구현된 시리얼 통신 코드와 링 버퍼 , 그리고 AVR UART 내부 구조와 ANSI C 언어로 구현된 초기화 및 통신 에러에 대해 알아본다.

    i8051
    보내기와 받기를 관장하는 리시버 버퍼와 전송 버퍼는 동일한 것으로 SFR의 99h 번지에 있는 같은 SBUF에서 이루어진다. 이것에 대한 시리얼 동작 제어는 SCON(98h) 레지스터를 통해서 일어나며 8051 코어를 이용할 경우 4가지 전송 모드가 있다. 시리얼 포트는 인터럽트에 의해 송신과 수신을 제어하는데, 1바이트가 수신되면 CPU의 수신 플래그가 설정되면서 인터럽트를 발생시킨다. 이 때가 수신 버퍼를 읽어야 하는 시점이다. 수신 인터럽트 플래그 비트는 SCON의 0번째에 위치한 RI 플래그가 담당하는데 1(High로 Set)이 될 때 한 단어가 수신되는 것(그러나 반드시 통신 관련 레지스터가 Enable 되어있어야 한다)이다.
    소프트웨어에 의해 선택할 수 있는 전송 방식에는 4가지 통신 모드가 있다. 표 1에서 알 수 있듯이 모드0은 CPU의 시리얼 포트가 I/O의 쉬프트 동기를 맞출 수 있는 클록을 제공하는 동기(Synchronous)방식이고 나머지는 비동기(Asynchronous)방식이다. 

    표 1. 시리얼 포트의 동작 모드
    모드
    동기/비동기
    속도(Baud)
    데이터
    Start/Stop
    9번째 데이터 비트
    1
    SYNC(동기)
    12 * (14.7456MHz)^-1
    8
    없음
    없음
    2
    ASYNC(비동기)
    Timer1 에 의해 결정
    Start 1 비트
    Stop 1 비트
    3
    32*(14.7456MHz)^-1 
    또는 64 * (14.7456MHz)^-1
    9
    비트 0.1
    또는 Parity 비트
    4
    Timer1 에 의해 결정


    동기는 비동기에 비해 비트 단위로 클록을 발생하기 때문에 빠른 통신이 가능한 반면, 비동기는 처음 비트에서 스스로 동기를 맞추게 되어있다. 각 모드에서의 기능에 대해서는 설명이 필요하다. 특히 모드1은 가장 많이 사용하는 방법이므로 프로그램과 함께 알아보겠다.
    통신모드0의 Bps를 도표를 이용하여 계산해보면 12*TCLK=12*(14.7456MHz)-1=0.814㎲=1,228,800Bps와 같으므로 시스템 클록 상에서 최대 통신속도가 가능하다는 결론이 나온다.
    통신모드1은 PC와 인터페이스하기 위해 사용하는 가장 일반적인 방법으로 10비트 비동기 모드이며 타이머1의 값을 조정하므로 전송 속도를 프로그램할 수 있다. 타깃 보드에서 사용한 통신 방법이며 전송 속도를 구하기 위한 공식은 다음과 같다.

    이를 TH1 위주로 다시 풀 수 있다.

    여기서 tCLK=(시스템 클록)-1=(14.7456MHz)-1=0.068㎲이고 SMOD 비트는 레지스터(PCON:87h:비트7)에 있다.
    8051 코어는 내부 구조가 정해진 시간만큼 BPS를 위해 클록을 발생시킬 필요가 있는데 여기에 타이머 하나를 사용하게 된다. TH1(8Dh)은 통신 속도 타이머 설정 값인데, 1씩 증가해서 FFh에서 0이 되면 인터럽트를 발생한다. 그런데 이런 전송 속도를 사용하기 위해서는 다음과 같이 TMOD(89h) 레지스터의 타이머1 GATE(MSB) 비트를 0으로 해놓아야 한다. D7~D4는 타이머1이고 D3∼D0은 타이머0을 나타낸다.

      D7     D6   D5   D4    D3     D2   D1   D0  = TMOD (89h)
    GATE  C/T  M1  M0  GATE  C/T  M1  M0  = 비트
       0       0     1     0      X      X     X    X   = 값      (X:상관없음)

    표 2는 14.7456MHz의 클록을 DS5002FP(8051 코어로 되어 있음)의 XTAL1(48), XTAL2(47)핀에 입력한 상태에서 SMOD(PCON:87h:비트7)와 TH1(8Dh)의 값을 통해 통신 속도를 계산한 것이다. 클록을 선택할 때는 이처럼 시스템 통신 속도 계산 값이 정수배가 되도록 설계해야 장기 전송 중에도 타이밍이 틀려 잃어버리는 정보가 적다. 그리고 통신 속도를 두 배로 키우기 위해서는 SMOD를 0에서 1로 바꾸면 간단히 배가(倍加)된다.

    표 2. 14.7456MHz 클록에서의 Baud Rate
    Bps
    SMOD
    Timer1의 GATE, C/T
    타이머 모드
    TH1 값
    38400
    0
    0
    TMOD의 타이머1 M1=1, M0=0이면 타이머 모드2로 설정,
    즉 8비트 자동 재장전(Auto-Reload)타이머로 설정
    FFh
    19200
    0
    0
    FFh
    9600
    0
    0
    FCh
    4800
    0
    0
    F8h


    시리얼 포트를 모드1의 통신 방식으로 할 경우 다음과 같은 순서로 초기화한다. TH1을 0xFC로 놓으면 9600Bps가 되고 SMOD 비트를 다시 1로 놓으면 통신 속도가 두 배로 된다.
    void serial_init(void) // Function 이름은 임의로 만들어도 된다.

    { ES = 1; // Enable Serial Interrupt
    SCON = 0x50; // 통신모드=1, REN=1
    PCON = 0x80; // or PCON |= 0x80, SMOD=1
    TMOD |= 0x20;
    // Timer mode=1, Auto_reload ‘|’는 논리 OR
    PS = 1; // Serial Port Priority=1, 우선순위 높게
    TH1 = 0xFC;
    // Bps 설정, 19200Bps, 표에서는 9600Bps
    TR1 = 1; // Run Timer1
    TI = 0; // Initial TI
    RI = 0; // Initial RI
    }

    통신모드2는 11비트 비동기 모드로서, 전송 속도는 시스템에서 사용한 클록 시간을 32배 혹은 64배 중 하나만 선택하여 운용(運用)할 수 있다. 선택은 SMOD(PCON:87h)비트에 의해서 하며 SMOD=0이면 1/64 값이고 SMOD=1이면 1/32가 된다. 제일 빠른(SMOD=1) 방법으로 Bps를 계산할 경우에 (2SMOD/64)*14.7456MHz=943,718,400Bps가 된다.
    통신모드3은 모드1, 2와 비슷하지만 8E1(8데이터 비트, 짝수(Even) 패리티, 정지 1비트)로도 설정이 가능하다. 패리티 비트(PSW:D0h:비트0)를 시리얼 통신의 9번째 비트TB8(SCON:98h:비트3)로 전송하면 되는 것이다.
    패리티 비트는 어큐뮬레이터(Accumulator:누산기) ACC의 8비트 중 1의 개수가 짝수가 되도록 0과 1을 조정하기 때문에 통신용 9번째 비트는 짝수 패리티(Even Parity)가 된다. 다중 통신을 하기 위한 엔지니어라면 다음 기사에서 다루게 될 RS-485 통신이나 달라스의 DS5002FP/8051 매 뉴얼을 참조하기 바란다.
    통신모드0~3은 SFR의 SCON 제어에 의해 이루어지며 인터럽트와 프로그램 조작으로 SBUF에 읽고 써서 전송 및 수신되는 구조이다. 데이터는 LSB(Least Significant Bit:부여된 위치에서 덜 중요)부터 시작해서 MSB(Most Significant Bit:부여된 위치에서 가장 중요)순서로 쉬프트 아웃된다.
    다음은 비동기 통신모드1과 3, 특히 모드1에 대해 예를 들고 PC와 인터페이스 하기 위한 방법을 그림과 실례를 들어 설명하고자 한다. 모드1, 2, 3은 비동기 통신 전이중(Full-Duplex)방식으로, 하나의 스타트 비트와 8개의 데이터 비트 및 하나의 스톱 비트가 있다(모드2, 3은 9번째 추가비트가 있다). 그래서 모드1은 한 단어(Word)의 길이가 8N1(하이퍼터미널 참고)일 경우 10비트가 되며 보레이트 발생은 Overflow 출력으로부터 유도된다. 좀더 기술적으로 설명하자면 CPU에서 통신을 위한 데이터 출력은 소프트웨어로 SBUF에 기록할 때마다 시작하는데(그림 1 참조), 그림 2 와 같이 WRSBUF(Write SBUF)가 발생하는 시점에서 보내기 동작이 일어난다.




    Dual UART
    RS-232의 확장용 칩을 이용한 설계에서 회로 구성과 관련된 소스코드를 통해 기본 기술을 습득한다.

    시리얼 통신용 포트는 마이크로프로세서에 보통 많아야 두 개 정도이다. SoC와 함께 구성된 MPU에는 다수의 UART를 설계하기가 쉽지만 주어진 Resource에서는 다수의 비동기 통신을 구현하기 난감할 때가 있다. 이때 사용할 수 있는 것이 Dual UART이다. 이는 UART 포트가 한 개의 칩 상에 한 개 이상 들어가 있는 것이다. Dual UART는 쉬프트 레지스터와 통신인터럽트 FIFO 등의 버퍼가 함께 들어 있어 시리얼 통신 포트를 추가할 때 유용한 유틸리티이다. 실험에 사용된 칩 벤더로는 미국 캘리포니아에 소재한 EXAR 회사의 Dual UART ST16C2550CJ를 이용했다.
    그림 1의 UART Tree는‘http://www.exar.com’의 웹사이트에서 제공받은 것이다. 전압/버스/FIFO/UART 개수 등으로 항목을 구분해 놓았다. 칩 내부 통신 엔진은 같으므로 한 개만 코딩할 수 있다면 나머지는 Firmware에서 적용하는데 무리가 없다.
    원래 이름은‘Dual UART with 16Byte Transmit and Receive FIFOs’이며 TI사의 TL16C752b와 핀 구성이 같다. 다음은 ST16C2550의 Datasheet에서 발췌한 특징이다.
    ·두 개의 UART 디바이스 내장
    ·Up to 4 Mbps with external clock of 64MHz Firmware 엔지니어를 위한 Communication 구현
    ·Up to 1.5Mbps data rate with a 24MHz crystal frequency
    ·16Byte transmit FIFO to reduce the bandwidth requirement of the external CPU
    ·16Byte receive FIFO with error flags to reduce the bandwidth requirement of the external CPU
    ·Independent transmit and receive UART control
    ·4개 선택 가능 Receive FIFO interrupt trigger levels
    ·Modem control signals(-CTS, -RTS, -DSR, -DTR, -RI, -CD)
    ·Programmable character lengths(5, 6, 7, 8) with Even, odd, or no parity
    ·Status report register
    ·Crystal or external clock input
    ·TTL compatible inputs, outputs
    ·3.3V or 5V supply operation
    Dual UART의 장점이자 단점은 칩 인터페이스를 버스에 의해 연결해야 하기 때문에 Memory Mapped I/O로는 설계가 불가능하다는 것이다. 실 험에 사용된 MPU는 8051 코어로 되어 있는 ADuC812BS를 사용해 PSD와 연결하고, 이를 DUAL UART와 인터페이스 했다.
    이 시스템은 반도체 생산라인 검사 장비 온도를 6Ch의 RS-485를 통해 받아들인 후, RS-232로 자동 송출할 때 이용한 것 중의 일부이다.
    그림 2에서 볼 수 있듯이 MPU 회로도에서는 UART를 연결하기 위해 8비트 ADUC812BS를 사용하여 시스템을 구성했다. 또한 통신으로 오는 데이터의 소실을 막기 위해 NV RAM으로 XDATA 영역을 디자인했다. NV RAM은 통신의 링 버퍼로 구현되었으며, 일반 RAM처럼 특별한 조작없이 데이터가 저장되지만 전원이 없어져도 플래시메모리처럼 데이터가 지워지지 않는다. 아쉬운 것은 가격이 좀 비싼 편이다.
    Source 1은 ADuC812에 관련된 사항의 초기화이며, Source 2는 함수에 대한 소스 코드와 설명이다.





    FIFO, LIFO, FILO
    FIFO(First In First Out Memory)는 먼저 저장된 데이터가 우선적으로 읽히기 때문에 자동차가 지나다니는 터널과 같다.
    먼저 터널 입구로 들어간, 자동차에 해당하는 정보(보통은 1Byte)가 먼저 반대편 출구로 나오는 구조인 것이다. 다른 용어로는 Tunnel Stack이라고 한다. LIFO(Last In First Out)는 막혀있는 터널이라고 생각하면 되는데 먼저 들어간 정보는 나중에 들어간 정보가 나오기 전에는 막혀서 나오지 못한다. 그래서 나중에 들어간 정보가 먼저 나오는 형태를 취한다. LIFO를 일본 용어사전에서는 FILO(First In Last Out Memory)라 한다.
    MPU에서 사용하는 대부분의 스택 구조는 나중에 저장된 데이터부터 꺼내야 하는 LIFO 구조로 되어 있다. 그래서 다른 용어로는 Stack Memory라고도 한다.








    Source 1. ADuC812에 관련된 사항의 초기화

    //================================================================
    void main(void){
    EA=0; // Disable All Interrupt
    init_timer0(); // Timer0의 초기화
    init_qbuffer(); // q-buffer setup, 초기화
    #ifdef DUAL// Dual UART Using, 전처리기
    UART_16c2550_4_set(); // UART, 통신 속도 115200BPS 설정
    #else, 아니면 MPU의 UART 동작
    init_serial(); // 19200Bps setting, at SMOD=0
    #endif
    EA=1; // 모든 인터럽트 가동
    putstring("₩n₩n₩n₩n"); // Program Version Print, 설정된 UART_16c2550_4_set로 발신
    putstring("₩nMessage : Program Ver "); // Program Version Print
    putstring("5.1"); // 프로그램 버전 출력
    putstring("₩n"); // New Line
    // Dual UART 초기화 현재 4개의 Dual UART 코딩되어 있으므로 선택적으로 사용
    // 즉 7개는 RS-485 입출력에 사용되며 1개의 시리얼 통신은 PC와 통신
    UART_16c2550_1_set();// 19200,9600
    UART_16c2550_2_set();// 19200,9600
    UART_16c2550_3_set();// 19200,9600
    Buff_1_clear(); //16x2550_1 A buff clear, // 버퍼 구현
    Buff_2_clear(); //16x2550_1 B buff clear
    Buff_3_clear(); //16x2550_2 A buff clear
    Buff_4_clear(); //16x2550_2 B buff clear
    Buff_5_clear(); //16x2550_3 A buff clear
    Buff_6_clear(); //16x2550_3 B buff clear
    Buff_7_clear(); //16x2550_4 A buff clear
    // Buff_8_clear(); //16x2550_4 B buff clear// PC 통신을 위한 시리얼, 실제 Ring Buffer 구현
    flag_state =0; //플래그 초기화, Application은 경우에 따라 추가
    // Initial Dual UART value
    cs1_count=cs2_count=cs3_count=cs4_count=cs5_count=cs6_count=1;// array count
    cs1_t_flag=cs2_t_flag=cs3_t_flag= cs4_t_flag=cs5_t_flag=cs6_t_flag=OFF;
    bit_flag_transfer=ON; // Display ON
    rxpc_data=get_char=0;
    while(1){// end less loop
    if(check_pop()) // for PC Check input
    rxpc_data=get_char;// PC에서 처리해야 되는 입력 키보드 값의 저장
    //Receiver channel A, A-1, 실제로는 RS-485로 입력받음
    if(COMMA_1_LSR & 0x01){ // check FIFO
    pass=COMMA_1_RHR; // 임시 버퍼
    cs1_t_flag=ON; // Timer flag ON
    if(pass==STX) { // Start Text Code 검출
    cs1_count=0; // 문자 받기 시작
    goto pass_comma; // 처리 루틴의 효율을 높이기 위해 Jumper
    }
    if(pass==ETX) { // End of Text 검출
    putbyte(STX); // send STX, 02 value, PC로 받은 데이터 송출
    for(uc_i=0;uc_i putbyte(cs1[uc_i]);// send data at PC
    flashwrite_512over_MMC_write(cs1[uc_i]); // 이 루틴은 빠져 있음
    // 실제로는 512바이트씩 끊어서 MMC(Multi Media Card)에 저장
    }// end for
    putbyte(ETX); // PC로 보낸 다음 마지막 처리
    cs1_count=0;// initial, 수신 카운트 초기화
    goto pass_comma; // 효율적인 처리
    }//cs1_count- -; // discount count
    if((pass!=STX) && (pass!=ETX)) // 수신 데이터가 STX, ETX가 아니면 사용 가능한 Data
    cs1[cs1_count++]=pass;// 입력된 데이터(실제로는 온도 데이터)를 버퍼에 저장
    // 데이터 중에서 숫자가 아닌 특별한 ASCII 코드일 경우 예외 처리
    if((pass='a') && (pass<='z')) 
    rxd_data=pass;// Other Command code
    }
    pass_comma :
    cs1_timer=0; // Timer 카운트 시작
    }// end COMM
    //2===============================================
    // 2Ch∼7Ch까지의 데이터 수신 프로그램은 이곳에 넣을 것
    //7===============================================
    // Timer checker A, A-1 Chnnel의 수신 Time Out을 꼭 넣어야 통신 장애가 생기지 않음
    if((cs1_t_flag==ON) && (cs1_timer > TIMEOUT)){ // 보통 TIMEOUT 1Sec
    COMMA_1_FCR |= ~BIT1; // 0000 0010 // RX FIFO Reset, 수신 데이터 모두 버림
    cs1_count=0;
    }// 1Ch 끝
    // 다음 채널은 이곳 이후부터 추가
    // for Dual UART, 채널로부터 들어온 1바이트 명령어 처리
    switch(rxd_data) {
    case 'C': case 'c': // 처리 코드, 대/소문자
    rxd_data=0; // 처리하기 전에 Clear
    cs1_count=cs2_count=cs3_count=cs4_count=cs5_count=cs6_count=1;// array count
    cs1_t_flag=cs2_t_flag=cs3_t_flag= cs4_t_flag=cs5_t_flag=cs6_t_flag=OFF;
    if(cs1[cs1_count]=='a') (void) UartASputchar ('a');// Ch1
    if(cs2[cs2_count]=='b') (void) UartBSputchar ('b');// Ch2
    if(cs3[cs3_count]=='c') (void) UartCSputchar ('c');// Ch3
    if(cs4[cs4_count]=='d') (void) UartDSputchar ('d');// Ch4
    if(cs5[cs5_count]=='e') (void) UartESputchar ('e');// Ch5
    if(cs6[cs6_count]=='f') (void) UartFSputchar ('f');// Ch6
    break;
    // 다른 처리는 이곳에, 아래는 예제
    case ESC:// PC transfer STOP
    rxd_data=0;
    if(cs1[cs1_count]=='a') (void) UartASputchar ('a');
    if(cs2[cs2_count]=='b') (void) UartBSputchar ('b');
    if(cs3[cs3_count]=='c') (void) UartCSputchar ('c');
    if(cs4[cs4_count]=='d') (void) UartDSputchar ('d');
    if(cs5[cs5_count]=='e') (void) UartESputchar ('e');
    if(cs6[cs6_count]=='f') (void) UartFSputchar ('f');
    break;
    default:
    rxd_data = 0;
    break;
    }// end switch rxd
    switch(rxpc_data) {// PC의 시리얼로 입력된 데이터 처리
    case 'C': case 'c':// 대소문자 구별 없음
    rxpc_data=0;
    // Application 프로그램은 이곳에
    cs1_count=cs2_count=cs3_count=cs4_count=cs5_count=cs6_count=1;// array count
    cs1_t_flag=cs2_t_flag=cs3_t_flag= cs4_t_flag=cs5_t_flag=cs6_t_flag=OFF;
    break;
    case ESC:// MMC, PC Trance Stop
    rxpc_data=0;
    break;
    }// end switch rx
    }// end while
    }// end main
    //================================================================



    Source Source 2. 함수에 대한 소스 코드와 설명
    //================================================================
    void init_qbuffer(void){
    q.rp=0;
    q.wp=0;
    }
    void UART_16c2550_1_set(void){
    STCommCfgPort (COMMA_1, 9600, 8, COMM_NO_PARITY, 1);
    STCommCfgPort (COMMB_1, 9600, 8, COMM_NO_PARITY, 1);
    }
    void UART_16c2550_2_set(void){
    STCommCfgPort (COMMA_2, 9600, 8, COMM_NO_PARITY, 1);
    STCommCfgPort (COMMB_2, 9600, 8, COMM_NO_PARITY, 1);
    }
    void UART_16c2550_3_set(void){
    STCommCfgPort (COMMA_3, 9600, 8, COMM_NO_PARITY, 1);
    STCommCfgPort (COMMB_3, 9600, 8, COMM_NO_PARITY, 1);
    }
    void UART_16c2550_4_set(void){
    STCommCfgPort (COMMA_4, 115200, 8, COMM_NO_PARITY, 1);
    STCommCfgPort (COMMB_4, 115200, 8, COMM_NO_PARITY, 1);
    }
    void STCommCfgPort (Byte ch, Uint32 baud, Byte bits, Byte parity, Byte stops){
    Uint16 div;
    Byte divlo,divhi,lcr;
    div = (Uint16)((Uint32)COMM_DIV16_CLK / (Uint32)baud);
    divlo = div & 0x00FF;
    divhi = (div >> 8) & 0x00FF;
    lcr = ((stops - 1) << 2) + (bits - 5);
    switch (parity) {
    case COMM_PARITY_ODD:
    lcr |= 0x08;
    break;
    case COMM_PARITY_EVEN:
    lcr |= 0x18;
    break;
    }
    switch (ch) {
    case COMMA_1:
    COMMA_1_LCR = BIT7;
    COMMA_1_DIV_LO = divlo;
    COMMA_1_DIV_HI = divhi;
    COMMA_1_LCR = lcr;
    COMMA_1_FCR = 0x01; //tx, rx reset
    COMMA_1_FCR = 0x07; //0000 0111, trigger 2550, TX, RX Enable
    COMMA_1_IER = 0x01; //enable RCV holding register
    break;
    case COMMB_1:
    COMMB_1_LCR = BIT7;
    COMMB_1_DIV_LO = divlo;
    COMMB_1_DIV_HI = divhi;
    COMMB_1_LCR = lcr;
    COMMB_1_FCR = 0x01; //tx, rx reset
    COMMB_1_FCR = 0x07; //0000 0111, trigger 2550, TX, RX Enable
    COMMB_1_IER = 0x01; //enable RCV holding register
    break;
    case COMMA_2:
    COMMA_2_LCR = BIT7;
    COMMA_2_DIV_LO = divlo;
    COMMA_2_DIV_HI = divhi;
    COMMA_2_LCR = lcr;
    COMMA_2_FCR = 0x01; //tx, rx reset
    COMMA_2_FCR = 0x07; //0000 0111, trigger 2550, TX, RX Enable
    COMMA_2_IER = 0x01; //enable RCV holding register
    break;
    case COMMB_2:
    //중략...
    break;
    case COMMA_3:
    //중략...
    break;
    case COMMB_3:
    //중략...
    break;
    case COMMA_4:
    //중략...
    break;
    case COMMB_4:
    //중략...
    break;
    }
    }
    void Buff_1_clear(void){ //for ch1
    for(Buff_1_no=0; Buff_1_no<=BUFF_MAX; Buff_1_no++)
    Buff_1[Buff_1_no] = 0;
    Buff_1_no = 0;
    RX_16c2550_1_A_f=OFF; //receive flag clear
    }
    //================================================================

    [출처] Dual UART|작성자 맥가이심





    RS-485
    노이즈에 강해 원격 자동화에 많이 사용되는 RS-485 통신의 기본 원리와 회로도, 프로토콜 제작에 대해 알아본다.

    RS-232는 그라운드와 데이터 신호의 전압 차이로 상대 기기에 전달된다. 그래서 통신 선로가 길수록 전압 저하로 노이즈에

    약하고 고속이나 장거리에는 부적합 한 것이 단점이다. 반면 RS-422(EIA-422)는 고속 및 장거리 노이즈에 상대적으로 강한

    통신 방법이다. 232가 불평형 통신 선에 의한 인터페이스라면 485는 평행형 통신 선이며, 쌍방 접속으로 최대 10Mbps로

    수 Km까지 전송이 가능하다. 485는 표 1에 나타낸 것처럼 422와 전기적으로 다른 것 이외에는 유사하다.

    항목RS-232RS-423RS-422RS-485
    모드 타입불평형불평형평형평형
    최대수Driver(송신)11132
    Receive(수신)1101032
    최대 케이블 길이(m)15120012001200
    최대 Bps20K100K10M10M
    Transmit LevelMax±15V±6V경우에 따라 다름-
    Min±5V±3.6V±2V±1.5V
    수신감도±3V±0.2V±0.2V±0.2V
    Load Impedance(Ω)3K∼7K450이하100이하60이하
    Output Current Limit500mA∼(Vcc 또는 GND)150mA∼GND150mA∼GND150mA∼GND
    Driver ZOUT 최소값(Power Off)300Ω60kΩ60kΩ60kΩ
    그림 1은 RS-485 IC의 내부 구조 및 연결 방법을 나타낸 것이다. LTC485와 MAX465는 Pin-to-Pin으로써 전기적 차이는 약간 있으나 기능 핀 구성이 같다. 언급된 제품 이외에 상당수 더 있지만 필자는 LTC485를 통해 실험했다. 그림1의 왼쪽은 IC 핀 구성과 내부 구조를 나타내며, 오른쪽은 IC를 이용해서 원거리를 케이블로 연결했을 경우를 매뉴얼에서 언급한 대로 나타냈다. 선로 상의 A, B 사이에 있는 RI는 종단 저항을 나타내며, 선로 임피던스마다 다르지만 보통 50~150Ω을 병렬로 연결해서 사용한다. 수신 쪽에서 정보를 보냈을 경우 반대편에 부딪혀서 메아리처럼 되돌아오는 신호를 소멸시키기 위해서이다. 빨래 줄처럼 한 개의 신호 선에 여러 대의 장비가 서로 통신할 경우에는, 장비마다 종단 저항을 전부 연결하는 것이 아니고 보내는 장비와 가장 멀리 위치한 받는 장비 한 대씩 두대만 종단 저항을 연결한다. 그래서 485 통신 보드에는 보통 100Ω의 종단 저항에 점프 핀으로 선택적인 연결을 할 수 있도록 해서, 선로 상의 마지막에 해당하는 보드에 종단 저항 설치가 가능하게끔 구성한다.
    통신 선로 상에 직렬로 되어 있는 R14~R17의 1Ω 저항값은 선로로 과 전압이 들어오면 내부 기기를 보호하기 위한 보호 저항이다(신뢰성 없음). 선로 상에 이상 전압이 예상되거나 전기적으로 서로 절연(Isolation)하기 위해서는 포토 커플러를 485 드라이브 IC와 TTL 로직 IC 사이에 놓고 설계하기도 한다(그림 2 참조).


    그림 2. RS-485와 RS-232 통신 설계

    SYNSYNSOHHeaderSTXTextETXBCC

    SYN : Synchronous Idle
    SOH : Start Of Heading
    STX : Start Of Text
    ETX : End Of Text
    BCC : Block Check Character
    그림 3. 동기식 메시지 형식

    2개 이상의 스테이션 사이에 정보를 전송하기 위한 순서 규약이 프로토콜이며, 이에 의해 통신이 제어된다. 통신 규약의 목적은 기기 사이의 연결을 시작하거나 끝내고 송수신부를 지정하며, 오류 확인, 데이터 전송에 관련된 모든 제어 기능을 관리하는 데 있다. 232에서도 약간 언급했지만 데이터 전송에는 동기식과 비동기식이 있다.
    동기식 방법에는 문자 지향적 프로토콜(Character-Oriented Protocol)과 비트 지향적 프로토콜(Bit-Oriented Protocol) 이 있다. 대부분의 통신 코드는 문자 지향적 방법의 변형을 이용하여 비동기식으로 통신하는 알고리즘이다. 데이터 전송을 담당하는 통신 제어 문자를 표 2에 나타냈는데, 이들 문자를 약속된 절차에 따라 서로 주고받으면서 통신하는것이다. 문자 지향적 형식은 헤더(Header) 영역과 텍스트(Text) 영역, 그리고 오류 검사(Error Check) 영역으로 나뉘며 이를 메시지(Message)라 한다.
    그림 3은 동기식 문자 지향적 프로토콜의 전형적인 메시지 형식을 나타낸다. SYN은 상호 약속에 의해 송신부와 수신부의 동기를 돕는 것으로 0110100의 특수 문자를 사용하는데, HDLC(High-level Data Link Control)같은 비트 지향적 프로토콜에는 플래그 0111 1110을 사용한다. 필자가 구현한 통신 프로토콜은 시리얼 통신모드1을 사용한 비동기식이고, 메시지 형식은 문자 지향적인 방법을 이용했다. 특히 동기 맞추는 부분은 제외한 자작 프로토콜을 이용했다.
    표 2는 서로 떨어져 있는 보드 사이를 통신하기 위해 미리 정의한(현재 통용되고 있음) 문자 기호를 나타내며 16진 Hex값이 이에 해당한다. 여기서부터는 이런 기호를 이용해서 장비와 장비간에 서로 통신하는 방법과 프로토콜을 정의하고자 한다. 궁극적인 목적은 넓은 범위에서 사각지대 없이 여러 대의 기기가 원활하게 서로 통신하며 정보를 주고받는 것이다. 데이터 수수를 위해 가장 먼저 해야 할 일은 신뢰성에 기반을 둔 통신이다. Mast, Slave의 개념을 쉽게 이해하기 위해서 이제부터는 대장/부하 개념으로 설명하겠다.
    대장보드와 부하보드 상호간에는 비동기 통신, Polling, Selecting, Response 프로토콜을 사용한다. 통신 속도는 변경할 수 있지만, 기본적으로 19,200Bps에 고정되어 있다. 데이터 길이는 8비트, Stop 비트는 1, 패리티 비트는 없으며(8N1) 16진(Hex)과 ASCII 코드 또는 BCD 코드를 사용한다.
    각 기기에는 고유의 UAD(Unit Address)가 Dip S/W에 의해 설정돼 있다. 그래서 사람 이름을 부르는 것과 같이 상대방의 UAD를 이용하여 통신하게 된다. 통신은 정해진 전문 형식에 의해 이루어진다. 통신할 데이터가 없더라도 일정한 시간이 되면 대장보드가 부하보드의 어드레스를 불러 주는데 이를 정기적 Polling라 한다(이하 POL). POL은 회선이 끊어졌는지 확인하며 기기가 정상적으로 동작하는지 체크하는 데도 이용된다. Selecting은(이하 SEL) 대장보드가 부하보드를 UAD로 불러 데이터를 송신할 때 이용되며, Response(이하 RSP)는 POL에서 해당 UAD가 응답할 내용을 대장보드에게 보낼 때 사용된다.
    기호Hex의미기능
    STX02Start Of Text블록의 시작
    ETX03End Of Text블록의 끝
    EOT04End Of Transmission전송의 끝
    INQ05Inquiry명령 실행응답 문의
    ACK06Acknowledge인식했음을 알림
    DLE10Data Link Escape전송 제어용 확장 코드
    NACK15Negative Acknowledge잘못 인식했음을 알림
    ETB17End Of Transmission Black전송 블록의 끝
    POL70Polling대장보드가 보냄
    SEL73Selecting부하보드 지정 정보 전달
    UAD0~FUnit Address기기 번호
    BCC0~FFExclusive OR Sum블록 검사


    HDLC
    HDLC(High-level Data Link Control)는 정보 전송을 위해 국제 표준위원회 ISO에서 개발한 비트 중심의 데이터 통신 프로 토콜이다. HDLC는 OSI 모형을 사용하는 컴퓨터와 컴퓨터 사이 의 데이터 통신에서 데이터 링크 계층에 대한 비트 단위의 동기 전송 방식을 정의하고 있다. 즉 데이터 프레이밍, 흐름 제어, 에 러 검출 정정 용도로 쓰이는 비트 기반 데이터 링크 계층의 동기 식 프로토콜인 것이다. HDLC에서의 순서와 정보는 Flag(8bit),Address(8bit), 제어(8bit), 데이터 정보(임의), 프레임 오류 점 검용(16bit), Flag(8bit)과 같은 프레임 형식으로 데이터가 저장 된다. HDLC는 IBM의 SDLC를 기반으로 개발됐고 ISO에 의해 표준화되었다. 표준 프로토콜 서브셋으로 구현된 HDLC의 예를 보면, 이더넷에 사용되는 802.2와 X.25에 사용되는 LAP 등이 대표적이다.
     
     
    출처 : 네이버

    통신 전문 형식의 예를 도식화하면 그림 4와 같다. 주기적으로 POL이 행해져서 부하보드가 송출할 정보가 없고 그냥 대답만 할 경우에는 CK(Acknowledge)만 보낸다. 보낼 전문이 있으면 RSP로 구성된 데이터 블록을 대장보드에게 보내면 된다.
    한편 대장보드가 부하보드에게 정보를 보내고자 할 경우에는 부하보드의 UAD를 SEL 전문에 넣고 정보를 보낸다. 사실 POL과 SEL은 1:n의 일대 다 통신일 경우 대장보드를 포함해 RS-485 선로에 있는 부하보드 전부가 정보를 받고 해석한다. 그 후 자신의 UAD를 받았다면 해당 기기는 내부적으로 명령을 처리하고 응답한다. 응답 정보를 보낼 경우에는 RSP를 보내거나, 아니면 ACK 또는 NAK(Negative Acknowledge)를 보내면 된다. 홈 가드 보드의 통신에서 잘 받았거나 긍정 응답일 경우는 ACK, 정상적으로 통신이 수행되지 않았거나 부정 응답은 NAK를 보내어 확실한 통신이 이루어지도록 한다.
    쉽게 말하자면 여러 사람들이 모여 서로 대화하는 것과 유사하다. 세 사람이 대화할 경우를 생각해보자. 서로 동시에 말하지 않기 위해 한 사람이 누군가와 대화하고 있다면 나머지 한 사람은 잠시 기다려 준다. 즉 자신의 이름이 아니면 응답하지 않고 불려진 상대의 대화가 끝날 때까지 기다리는 것이다. 하지만 기다리는 사람이 심심하지 않도록 가끔 이름을 불러 주는 에티켓을 발휘할 수 있다. 이러한 쌍방 간의 약속이 바로 프로토콜인 셈이다. 이는 기존 통신 시스템에서 사용하는 방법을 모방하여 만든 것이다.
    좀더 높은 신뢰성과 암호화 기법이 필요한 독자는 스스로 개발하던지 또는 국제적으로 공인된 방법을 사용하기 바란다.
    그림 4를 통해 다시 한 번 프로토콜을 설명해보겠다. 통신할 때는 3가지 모드가 있는데 POL, SEL, RSP가 그것이다. POL은 다시 정기적인 POL과 필요에 의해 사용하는 비정기적인 POL로 나눈다. 대장보드에서 부하보드에게 통신이 정상적으로 되는지, 선로에는 이상이 없는지, 그리고 부하보드가 응답할 것이 있는지 등을 POL한다. POL을 받은 부하보드는 보낼 정보가 있으면 RSP로 응답하고, 정보가 없다면 ACK를 보내 통신이 정상적으로 행해지고 있음을 대장보드에게 통보한다.


    RS-485 통신의 Echo, Non Echo 모드
    멀티 포인트 버스를 사용하는 시스템은 하나의 버스에 여러 개의 마스터가 연결되어 있다. 이 때문에 하나의 마스터가 다른 마스터와 통신할 경우 반드시 출력 개폐를 해야 한다. 이것은 RS-422의 멀티 드롭 모드와 동일한 개념이다. 하지만 동시에 여러 개의 마스터가 출력하여 데이터가 충돌하는 현상이 발생하 므로 이러한 문제는 S/W에 의해 해결되어야 한다. 그러한 방법 중 하나가 자기가 보낸 정보를 자기가 받아보면 서 충돌 여부를 확인하는 것인데 이를 RS-485 Echo 모드라 부 른다. 예를 들자면 어떤 마스터가 멀티 포인트 버스에‘ABC’라 는 데이터를 보내면 이 데이터가 자동적으로 되돌아온다 (Echo). 이를 읽어와서‘ABC’여부를 확인한 후 동일한 정보가 아니거나 들어온 데이터 수가 틀리면 충돌한 것으로 보고 적절 한 시간 지연을 거친다. 그리고 다시 출력시켜 정확한 값이 되돌 아 올 때까지 되풀이하면 된다. 이 때 마스터의 RxD 신호선은 항상 멀티 포인트 버스에 접속돼 있어 자신의 데이터뿐만 아니라 다른 마스터가 보내는 데이터도 받을 수 있다. 이러한 데이터 가 자신에게 필요한 정보인지 판단하는 것은 S/W에 의해 결정 된다. 즉 RS-485 Echo 모드에서 마스터의 RxD 신호선은 항상 멀티 포인트 버스에 접속돼 있어야 하는 반면, TxD 신호선은 데 이터를 출력할 때만 접속시켜야 하고 나머지는 반드시 단락시켜 야 한다. 만약 단락시키지 않으면 RS-422의 멀티 드롭 모드와 같이, 다른 마스터가 데이터를 보내도 충돌이 발생하여 올바른 송수신이 되지 않는다. RS-485 Non Echo 모드는 RS-485 Echo 모드에서 자기가 보낸 데이터가 자기 자신에게 되돌아오는 기능을 없앤 것이다. 이는 TxD 신호선을 멀티 포인트 버스에 접속시키면 그 즉시 RxD 신호선이 멀티 포인트 버스에서 단락된다. 또 TxD 신호선 을 멀티 포인트 버스에서 단락시키면 바로 RxD 신호선이 멀티 포인트 버스에 접속하게 된다.
     
     
    출처 : 시스템베이스

    한편 대장보드가 특정 부하보드에게 직접 정보를 전달하는 SEL이 있다. SEL을 받고 부하보드가 정상적으로 명령을 처리하면 ACK를 보내고 송수신 에러가 발생하면 NACK를 보낸다. ACK는 보통 정보를 잘 받았을 경우에 사용하고 NACK는 SUM 체크나 수신 오류를 범했을 경우 사용한다.
    도식화된 그림 5를 보면 3개 모드 중에서 맨 왼쪽은 정기적인 POL이다. PC에 연결되어 있는 대장보드가 부하보드에게 정기적으로 주소와 함께 정보를 보낸다. 이 때 RS-485 통신선에 연결된 기기들은 일단 분석한 후 자신의 어드레스와 받는 UAD가 동일한지 판단한다. 동일하다면 보낼 데이터 없이 대답만 할 경우 ACK를 보내고, 그림 5의 두 번째 상황처럼 응답 데이터가 있을 때는 RSP를 보내 통신한다. 전문 형식을 정상적으로 받으면 ACK를 보낸다. 반면 한번 더 송신을 요청하거나 취소할 때 또는 잘못 받았을 경우에는 NACK를 보내어 재 송신이 이루어질 수 있도록 한다. 그리고 도식화되어 있지는 않지만 정기적인 POL이나 정보를 보냈는데 일정 시간 동안 ACK 또는 NACK 응답이 없으면, 몇 번 더 재 송신한 후에 회선이 단선된 것으로 판단한다.
    통신 프로토콜을 제작하는 것은 생각보다 상당히 복잡하고 여러 가지 실험을 통해 검증되어야 한다. 그러므로 LoopBack Test 프로그램에 대해 알아보면서 프로토콜을 이해하도록 하자. Loop Back Test는 통신 동작을 확인하기 위해 간단하게 이용하는 방법으로, 송신한 것을 자신이 수신하여 정확히 동작하고 있는지 파악할 때 사용한다. Loop Back Test Tool은 그림 6과 같이 제작한다. 그림 6에서 M은 Male(수컷), F는 Female(암컷)이고 10Ω은 의미 없는 보호 저항이다. 여기서 RX_H와 TX_H를 극성에 맞지 않게 잘못 연결하면 485 드라이버 칩이 내부적으로 파괴된다는 점을 기억하자.
    Loop Back Test Tool의 R1과 R2에 오실로스코프 프로브와 GND 단자를 놓고 파형을 측정하면 그림 7의 하드카피 RS-485 파형을 얻을 수 있다.
    이 때 DB 9핀 소켓의 1번에 스코프의 측정 단자 프로브를, 6번에는 스코프의 그라운드를 연결해야 한다. 처음 통신이 없을 때는 Stop을 유지하고 있다가 통신이 시작되면 Start(Low), 그리고 대문자‘Z’의 ASCII Code인 0x5A(0101 1010) LSB부터 전송되어 MSB를 마친 후 Stop(High) 비트, 그리고 다시 한 번 Stop(문헌에서는 State라 한다) 비트를 유지한다. 프로그램에서 통신모드1, 데이터 8비트, 패리티 없고 Stop 비트 1(8N1)로 설정해 놓았기 때문이다.
    통신속도는 한 비트의 시간이 52㎲이기 때문에 역수를 취하면 19230.76≒19200Bps로 데이터가 송신된다는 것을 알 수 있다. 그리고 보면 기계는 정말 거짓말을 하지 않는다. 이 때문에 필자는 엔지니어로서, 인간의 명령에 따라 충실히 동작하는 기계를 올바르게 사용해야겠다는 의무감을 느끼기도 한다.
    Source는 RS-485 통신의 기본 구조와 Loop Back Test 프로그램으로, 숫자‘2’를 누르면 영어 대문자‘Z’를 TXH 및 TXL로 485 통신 선로에 보내고 RXH 및 RXL로 다시 받는 내용이다. 통신 결과는 RS-232를 통해 하이퍼터미널에 프린트했다. 그러나 보통의 MPU는 UART 포트가 하나밖에 없어 232 통신과 485 통신을 프로그램에 의해서 이쪽 저쪽으로 스위칭 해야 한다. 그러므로 데이터를 잃어버리면 안 되는 통신 시스템을 요구하는 구조의 포트 전환은 굉장한 기술을 요하거나 아니면 적합하지 않다고 본다.




    Source. 타깃 보드 커뮤니케이션 테스트 프로그램
    /*
    목적 : Target Board Communication Test
    File name: com_test.c
    Copyright Conan Kim All Rights Reserved.
    */
    #include 
    #include // 중간생략
    #include "C:₩hardware₩work₩gu_5002.h" // DS5002FP SFR 정의
    #include "C:₩hardware₩work₩gu_type.h" // #include 정의
    #include "C:₩hardware₩work₩gu_hard.h" // Memory Map
    #define uchar unsigned char
    #define uint unsigned int
    /*******************/
    /* function prototype */
    /*******************/
    // Interrupt initial
    void init_serial(void); // 19200Bps setting
    // Communication
    void init_qbuffer(void); // Ring Buffer 초기화
    bit check_pop(void); // RS-232로부터 입력 검사
    // Utility
    void title_print(void);
    uchar xtoa_h(uchar _byteh); // Hex to ASCII Converter 상위 Nibble
    uchar xtoa_l(uchar _bytel); // Hex to ASCII Converter 하위 Nibble
    void putstring(char* star); // 문자열 RS-232 프린터
    void putbyte(char c); // 문자(文字) 하나 출력
    /*******************/
    /* Variables Declarations */
    /*******************/
    uchar xdata get_char; // Q 버퍼에서 읽어온 입력 값
    struct ring xdata q; // For Communication q-buffer
    /******************/
    /* Main Function */
    /******************/
    void main(void){
    uchar xdata i;
    EA=0; // Disable Interrupt
    init_serial(); // 19200Bps Setting
    init_qbuffer(); // Ring Buffer Setup q.rp=q.wp=0
    EA=1; // Enable Interrupt
    wdt(); // Watchdog Timer
    switch(485){ // 참이므로 무한 루프 형성
    case(485): // Endless Loop
    title_print(); // 화면 프린터
    putstring("₩nCMD>"); // 다음 명령 대기상태 Prompt
    while(7){ // True 무한 Loop, for(;;)와 동일
    wdt(); // Watchdog Timer
    if(check_pop() && get_char==0x0D) // CR(Enter) Check
    putstring("₩nCMD>"); // 엔터키이면 Prompt
    switch(get_char){
    case('h'):case('H'):case('?'): // Help Display
    putstring("485_Communication(1), 485_Loop_back_Test(2)₩nCMD>");
    break; // 절대 빠트리지 말자........ 필자 무지 고생했음
    case('1'):case('!'): // 1일 경우, 실제 통신 프로그램 위치
    putstring("Now! 485_Communication ₩nCMD>");
    break;
    case('2'):case('@'): // 2일 경우
    putstring("Now! 485_Loop_Back_Test₩nCMD>");
    putstring("Send ASCII Code 'Z' to RS-485₩nCMD>");
    putstring("Receive(5) Char 'Z' to RS-485₩nCMD>");
    ON_485(); // 485 Port On
    // GU_TYPE.H에 다음과 같이 정의되어 있음
    // #define ON_485() CON1=0;CON2=1
    // #define OFF_485() CON1=1;CON2=1
    // #define ON_MODEM() CON1=1;CON2=0
    // #define OFF_MODEM() CON1=1;CON2=1
    for(i=1;i<=5;i++){ // 5회 실행
    wdt();
    putbyte('Z'); // send 485 Port Z=0x5A=0101 1010
    if(check_pop()){ // 485를 통해 수신 데이터 확인
    OFF_485(); // 485 Port off, 수신 데이터 있음
    putbyte(get_char); // 하이퍼터미널에 입력값 프린터
    putstring("("); // 괄호
    putbyte(xtoa_l(i)); // i 값을 ASCII로 변환
    putstring(")₩nCMD>");
    ON_485(); // 485 Port On
    } // end if
    }// end for(i∼
    OFF_485(); // 485 Port Off, RS-232로 변환
    putstring("("); // 괄호
    putbyte(xtoa_l(i)); // ASCII로 변환
    putstring(")₩nCMD>");
    putstring("END RS-485 Communication ASCII Code 'Z' Send Test₩nCMD>");
    putstring("If You Read Just Number '(6)' is Fail₩nCMD>");
    break;
    case('5'):case('%'): // this mode Output ASCII Code 'A'
    putstring("Now! Modem Test₩nCMD>");
    break;
    default:break;
    } // end switch(get_char)
    } // end while(7)
    break;
    default: wdt(); break; // 필요하지 않음
    } // end switch(485)
    } // end main
    // ========================================================
    // ======================== Utility Routine ===============
    // ========================================================
    bit check_pop(void){
    if(q.wp!=q.rp){
    get_char=(q.buffer[q.rp]); // pop get char by check flag
    q.rp++; // Increment Read Point
    if(q.rp>QSIZE) q.rp=0; // 링 구조를 가지고 있음
    return (1);
    }
    get_char=NULL; // 입력이 없으면 공(空), 여기서는 Zero
    return (0);
    }
    void putbyte(uchar c){ // TI=1이 될 때까지 실행
    SBUF = c; // 전송 인터럽트가 발생할 때 까지 대기
    while(!TI); // 괄호가 참이면 계속 실행, 즉 TI=0이면 대기
    TI=0; // (!TI)=0이 거짓이 되려면 TI=1
    }
    void putstring(char *str){ // Point 문자열 출력
    unsigned int xdata i;
    for(i=0;str[i]!='₩0';i++) {
    if(str[i]=='₩n') {
    putbyte(0x0a); // 0x0a = Line Feed(줄 바꿈)
    putbyte(0x0d); // 0x0d = Carriage Return(커서를 좌측 끝)
    }
    else putbyte(str[i]);
    }
    }
    uchar xtoa_h(uchar _byteh){ // 16진수를 ASCII로 변환 상위 Nibble
    uchar nibble = _byteh >> 4;
    return ((nibble > 9)? nibble + 'A' - 10 : nibble + '0');
    }
    uchar xtoa_l(uchar _bytel){ // 16진수를 ASCII로 변환 하위 Nibble
    uchar nibble = _bytel & 0x0F;
    return ((nibble > 9)? nibble + 'A' - 10 : nibble + '0');
    }
    void title_print(void){ // 사용자 타이틀 프린터
    putstring("₩n******************************");
    putstring("₩n* Target Board of Home Guard Communication Test *");
    putstring("₩n******************************");
    putstring("₩n₩n");
    putstring("CMD>Push '?'or 'H' key then Commands display₩nCMD>");
    }
    // ========================================================
    // ======================== Initial Routine ===============
    // ========================================================
    void init_qbuffer(void){ // 링 버퍼 초기화 루틴
    q.rp=0; // Read Point value = 0
    q.wp=0; // write Point value = 0
    }
    void init_serial(void){ // 19200
    ES =1; // Enable Serial Interrupt
    PS=1; // Serial Port Priority High
    SCON = 0x50; // Mode=1, REN=1
    PCON |= 0x80; // SMOD=1
    TMOD |= 0x20; // Timer Mode=2, 8bit Auto_reload Timer
    TH1 = 0xFC; // Time Value
    TR1 = 1; // Run Timer 1
    TI = 0; // Initial TI & RI
    RI = 0; // SCON에서 이미 정의되어 있음
    }
    // ========================================================
    // ======================== Interrupt ==================
    // ========================================================
    void timer0_isr(void) interrupt 1 using 1{ // auto reload 방식
    timer.tick++;
    if(timer.tick==0xFFFF) timer.tick=0;
    }
    void push_q(void) interrupt 4 using 1{ // UART 인터럽트
    if(RI){ // RI=1일 때 실행
    RI=0; // Empty RI(다음 인터럽트 받을 준비)
    q.buffer[q.wp]=SBUF; // Write Point로 옮김
    q.wp++; // Increment Write Point
    if(q.wp>QSIZE) q.wp=0; // Write Point가 넘치지 않게(Ring Buffer)
    } // End if(RI)
    }
    /*********************************/
    Source를 컴파일 한 후 프로그램을 로딩, 윈도우의 하이퍼 터미널과 실험용 보드인 홈 가드 보드를 연결한다. 정상적으로 Loop Back Test가 되었다면 그림 8과 같은 결과를 얻을 수 있다.
    만약 P2나 P3의 DB 9핀 소켓에 아무 것도 연결하지 않고 프로그램을 실행시키면 Z(1)~Z(5)가 출력되지 않고‘(6)’만 화면에 나타난다.
    바탕화면에 하드 카피된 TTY 프로그램은 PC 회사에서 COM 포트를 테스트하기 위해 이용하는 실행 파일로 Microsoft Corp.에서 만든 것이다. 윈도우에서 제공되는 하이퍼터미널을 사용해도 된다.
    자체적으로 RS-485의 TX를 통해 보낸 정보를 RX로 받는 것까지 됐다면 다시 프로토콜로 돌아오자. 앞에서 프로토콜을 필자가 직접 만들었다고 했다. 그런데‘프로토콜’의 사전적 의미를 찾아보니 외교상으로는 의전(儀典)이나 의례(儀禮)를 나타내며, 전산에서는 컴퓨터 상호간 또는 컴퓨터와 단말기 사이의 데이터를 송수신하는데 필요한 통신 규약으로 쓰여 있다. 결국 프로토콜은 일상 생활에서도 사용되고 있는 것이다.
    특히 많이 사용되는 전화망 통신의 예를 들어보자. 첫째, 음의 변조방식과 전화번호가 있다. 둘째, 통화하고자 하는 상대가 응답이 가능한지 이름이나 교환 및 내선 번호를 통해 확인한다. 셋째, 상대방과 접속이 되어서도 언어와 Yes or No의 대답 등 일정한 도덕 규약이 있다. 이렇게 프로토콜은 통신 문화이며 정해진 예절이다.
    자작한 통신 프로토콜은 다음과 같은 사항을 생각하지 않고 만든 점에 유의하도록 하자. 우선 데이터 투명도를 DLE(Data Link Escape)로 생각하지 않았다. 또한 선로 상에서의 통신 속도를 자동으로 맞추지 못하며, 통신 상에서 각종 대기 시간 및 정기적 POL 시간 등을 실험을 통해 정확히 고려하지 않았다.
    나머지는 차지하고라도 데이터 투명도는 꼭 짚어보고 넘어가야 하겠다. 초기 데이터 통신에는 ASCII 문자만으로 통신을 하다가 점점 정보 의미가 확대됨에 따라 2진 정보를 전송할 필요가 있게 됐다. 그러나 2진 정보는 문자 지향적 프로토콜에서 수신부에 의해 잘못 해석될 우려가 있다. 이를 막기 위한 작업을 투명(Transparent) 데이터라고 부른다.
    데이터 투명도는 문자 지향적 프로토콜에서 각 통신 제어 문자 이전에 DLE(Data Link Escape)라는 문자를 삽입하므로 이루어진다. 그래서 텍스트를 보낼 때 DLE로 시작해서 DLE로 끝나는 것이다. 만약 DLE(0x10h=0001 0000)와 똑같은 2진 정보가 텍스트 안에 존재하고 있다면, DLE의 혼선을 막기 위해 다시 한번 DLE를 보내는데 수신 시에도 두 개를 받았다면 하나를 버린다. 그러나 이런 방법의 데이터 투명도는 프로그램 하기도 까다롭고 특히 효율이 떨어진다는 단점이 있다.
    다른 방법으로는 텍스트 수를 세어 보내는 쪽에서 주고, 받는 쪽에서는 바이트 수를 세어 받는 방법도 있다. 보통 비트 지향적 프로토콜에서 많이 사용한다. 표 3은 홈 가드에서 사용하는 프로토콜의 정해진 명령어를 보여준다.
    구현된 타깃 보드는 PC와 연결되어 있는 하나의 대장보드와 이곳에 연결되어 있는 여러 대의 부하보드로 구성돼 있어 서로 정해진 프로토콜에 의해 통신하면서 정보를 주고받는다. 장비가 여러 대의 기기와 접속했을 경우 어떤 모양새를 도플러지(Topology)라고 하는데, 기본적인 방법에는 Point to Point와 멀티 드롭 방식이 있다.
    표 3. 프로토콜 제작 예

    코드명칭설명비고
    31초기 설정홈 가드 초기화대장보드가 부하보드에 보낼 때 사용
    UAD가 00일 경우에는 부하보드 전부 해당
    32날짜 설정RTC 년, 월, 일 설정
    33시간 설정RTC 시, 분, 초 설정
    34알람 설정RTC 알람 설정
    35모뎀 설정모뎀 초기화 설정
    36ResetReset
    39주소 보고 명령기기의 DIP S/W값 요청
    3A기기 상태 보고가드 현재 상태 보고 요청
    3B기기 제어 명령부하보드의 기타 제어 요청
    ----
    51가드 상태 통보--
    59기기 주소 통보기기의 DIP S/W 값-
    5A기기 상태 통보가드 현재 상태초음파, 온도, 방범 스위치
    5B기기 제어 통보기기 제어-
    5F기기 고장 통보부하보드 고장보드 고장 상태



    Fan Out
    디지털 집적회로(IC)의 외부에 접속되는 부하에 대하여 회로 의 출력 드라이브 능력을 나타낸다. 팬 아웃이 크면 드라이브 능 력이 크다고 할 수 있다. TTL IC에서는 보통 10∼20개 정도의팬 아웃을 가져, 동일 선상에 접속되는 부하를 능력 이상으로 연 결하면 드라이브 능력이 떨어진다. 팬 아웃 수치로 칩 세기를 평 가할 수도 있다.

    P_to_P 방식은 초등학생들이 자연시간에 실험해보았듯이 컵에 실을 꿰어 일대 일로 통신하는 것이다. 멀티 드롭은 P_to_P를 계속 확장한 것으로, 흡사 빨랫줄에 여러 개의 세탁물이 집게로 고정된 모양을 하고 있는 방법이다.
    보드의 연결도 멀티 드롭으로 구성되어 있어 통신하고자 하는 정보를 UAD(Unit Address)와 함께 선로에 놓으면 일단 전부 통신 선로에 연결되어 있는 대장 및 부하보드가 정보를 취득한 후 자신의 UAD가 아니면 버리는 구조로 되어 있다. 특히 대장보드가 UAD에 0X00을 넣어 선로에 놓으면 선로에 있는 모든 부하보드는 전부 자신의 UAD로 간주하고 제어 명령을 해석하고 실행한다. 이런 프로토콜을 이용하여 빠른 시간에 부하보드를 초기 설정이나 시간 설정할 수 있다.
    다음은 프로토콜에서 미처 설명하지 못한 통상적인 부분을 요약한 것이다. 프로토콜을 작성할 때 염두해 두어야 할 부분이기도 하다.
    .전송에 이상이 있을 경우 4회 정도 등, 정해진 회수만큼 재 시도해본다.
    .부하보드가 대장보드로부터 두 번 이상 똑같은 명령을 받고 다시 한 번 정상적으로 처리했다면 ACK를 보낸다.
    .NACK 수신 시에는 바로 전 상태의 전문을 다시 보낸다.
    .EX-OR 또는 SUM 에러가 발생하면 NACK를 보내고 NACK를 받은 보드는 에러가 발생했던 전문을 다시 보낸다.
    .대장보드는 정기적으로(시간은 상태에 따라 변할 수 있음) POL을 행한다.
    .POL에서 재 시도 횟수를 넘을 때까지 부하보드가 응답하지 않는다면, 대장보드는 선로의 이상 혹은 고장으로 판단한다.
    .부하보드는 대장보드의 POL에 응답하는 것 외에 자체적으로 RSP 전문을 보낼 수 없다.
    .부하보드끼리는 POL, SEL, RSP를 서로 행할 수 없다.



    그림 9는 대장보드와 부하보드를 연결하는 방법을 나타낸다. ‘MAST’는 대장보드를, ‘SLAVE’Keeper 1~Keeper n은 부하보드를 가리킨다. 부하보드는 통신모드3으로 할 경우 8비트의 UAD 때문에 0x0∼0xFF로 한계가 있다. 하지만 통신모드1로 했을 경우에는 이야기가 달라진다. 즉 프로토콜을 잘 만들고 Fan Out 한계가 없다면 무한대의 부하보드와 통신할 수 있는 것이다.
    RX, TX는 대장보드를 기준으로 송수신이 결정(사실 장비의 보통 기준은 PC이다)되기 때문에 대장보드가 송신이면 부하보드는 수신으로 맞춰야 한 다 . 즉 대장보드의 TX_H(TX_L)와 부하보드의 RX_H(RX_L)가 서로 연결되어야 하는 것이다. 이를 지키지 않으면 485 드라이버가 제 기능을 할 수 없다. 대장보드의 TxD 및 RxD 신호는 드라이브 RS-232를 통해 PC와 인터페이스 된다. 그러나 대장이든 부하든 같은 모듈을 사용하고 두 개의 프로그램이 같이 적재되어 있는데, 딥 스위치의 설정에 따라 대장보드와 부하보드가 결정된다.




    MODEM
    모뎀의 원리와 관련 회로도를 통해 초기화와 스펙, 그리고 운영에 관한 노하우를 알아 볼 수 있다.

    통신매체 중에서 거의 가정마다 보급되어 있는 정보 단말 기로 전화를 들 수 있다. 최근에는 점점 더 발달하여 광파이 버 및 고속 디지털화되고 있으나 아직도 아날로그 회로를 탑 재한 전화가 많으므로 필자는 전화 회선을 이용하여 정보를 보내고 받는 것을 시도한 적이 있다. 모뎀(Modem)은 변조기 (Modulator)와 복조기(Demodulator)의 영문 단어 머리글 자의 합성으로서, 디지털 데이터를 아날로그 신호 전송매체 (전화기)를 이용해 먼 거리에 있는 단말기에 전송해주는 데이 터 전송장비이다. 전화 회선을 이용한 제품이 상품으로 등록 되기 위해서는 검정을 거쳐야 하는데, 본고에서는 모뎀 칩 제 어 및 하드웨어 구성 원리에 대해 설명하고자 한다. 용어가 상당히 생소하기 때문에 영문으로 나온 단어를 눈여겨보기 바란다.
    8051 코어 DS5002FP는 Zilog 회사의 Z02201 ‘V.22bis Modem Data Pump With Integrated AFE’칩에 의해 초 기화하고 전화를 받거나 거는 제어를 했다. Z02201은 CPU 의 명령 코드나 데이터와 같은 디지털 신호를 아날로그 신호 로 변조한 후, 전송하고 받을 때는 변조된 신호를 복조하여 아날로그 신호를 다시 디지털 신호로 바꾸어 주는 AFE(Analog Front End) 칩이다.
    디지털 신호의 사용 주파수가 0에서 무한대인 반면, 전화 전송회선의 주파수 범위는 300~3,400Hz 대역으로 국한되 어 있으므로 규격에 맞게 전송해야 한다. 그림 1은 공업계 고 등학교‘데이터 통신(9211-26470)’교과서에 나온 내용을 인용했다. 블록도의 데이터 부호기는 단말기로부터 입력되는 디지털 신호를 어떤 방법으로 변조할 것인가 결정하고 부호 화한다. 그 후 변조기에서 반송 주파수로 변조되어 아날로그 신호가 된다.









    여파기(濾波器)는 필터(Filter)로서 모뎀 성능에 큰 영향을 미치는데 선로 특성에 맞는 주파수만을 통과시키는 역할을 담당한다.
    DAA(Direct Access Arrangement)는 교과서에서 아날로 그 신호 정합장치라는 용어로 되어있다. 모뎀과 전화선 사이 에 연결되어 있으면서 모뎀에서 나오는 신호를 선로 특성과 적절히 맞추어 선로 상에서 손실이 가장 적은 상태로 송신하 기 위해 사용한다. 또 선로 상에서 유기되는 과전류와 과전압 으로부터 모뎀을 보호하기도 한다.
    등화기 및 AGC(Automatic Gain Control)는 신호가 선로 상에 존재하는 R, L, C 성분에 의해 이득이 감쇠하고 지연되 는 현상이 생기므로 이를 보상해 주기 위한 회로이다. 복조기 회로에 의해 복조된 신호는 해독기(Decode)를 통해 원래의 디지털 신호로 변환되어 단말기로 보내진다.
    모뎀은 변조 방식에 따라 크게 3가지 종류로 나눈다. 첫째 진폭 변조 방식(ASK : Amplitude Shift Keying)은 디지털 신호를 반송파의 진폭에 따라 0, 1의 신호로 나타낸다. 주로 300Bps 정도의 저속 모뎀에서 사용되며 고속에서 사용할 경 우 다른 방법과 혼합하여 사용한다.
    두 번째로 주파수 변조 방식(FSK : Frequency Shift Keying)은 반송파(Carrier Wave)의 주파수를 이용해 0, 1 을 나타내는 방법이다. 예를 들어 디지털 신호 1을 1270Hz, 0을 1070Hz나 2225Hz 및 2025Hz로 보내면 상대가 주파 수를 해석하여 1과 0으로 복조한다. 주로 1,200~2,400Bps 정도의 중간 속도 모뎀에서 사용한다. 그림 2의 파형을 보면 서 이해를 돕자.
    마지막으로 위상 변조 방식(PSK : Phase Shift Keying) 은 0, 1을 반송파에서 위상의 변화로 변조하는 방식이다. 예 를 들어 00:90°, 01:180°, 10:270°, 11:0°만큼 반송파의 위 상을 변조하여 송신하면 수신은 이를 디지털 신호로 복조한 다. 한 개의 위상으로 1비트에서 4비트까지 나타낼 수 있기 때문에 주로 4,800Bps 이상의 고속 모뎀에서 사용한다.


    표 1. Modem Standard ITU V.XX

    Modem Standards ITU V.XX
    V.22
    V.22 bis
    Synchronous/asynchronous data transmission, full-duplex operation over 2-wire leased or dialup lines; 1200-bps data rate (V22 bis, 2400 and 1200 bps). Small businesses can beat the expense of leased lines by using V.22 modems with dialup lines. If they later add a 2-wire leased line, they can still use this modem. V.22 accommodates the equipment found in today's typical "hybrid" network; synchronous mainframes and terminals, and asynchronous PCs. V.22 bis doubles data throughput (to 2400 bps) for quick service of large file transfers.
    V.32Synchronous/asynchronous data transmission, full-duplex operation over 2-wire dialup or 2-wire leased lines; 9600 bps data rate (fallback to 4800 bps). The V.32 recommendation is the first universal standard for 9600 bps modems on dialup (private lines) or leased phone lines. V.32 compliant modems are the industry standard for medium-speed networks. Trellis-encoding modulation allows high data speeds and reduces errors. Data can be sent over standard dial-up lines, which are a lot less expensive to use than leased (private) lines. And V.32 compliant modems will work anywhere in the world. Any business, large or small, that handles large quantities of data transfer or huge data files can benefit from the fast, accurate data transfer of V.32 technology.


    표 2. Protocols for Error Correction and Compression

    Protocols for Error Correction and Compression
    MNP
    Levels 1-4
    Micro_com Networking Protocol (MNP) developed by Micro_com Systems, Inc., enables error-free async data transmission. Although MNP is proprietary, it became an industry standard in the 80s because users demanded it from manufacturers. Both modems in a connection must use the same MNP protocols.
    V.42
    V.42 bis
    These "V.XX" protocols are internationally recognized standards for error control and data compression. V.42 is the recommendation of the ITU for error control; it contains two algorithms (LAPM, or Link Access Protocol, and MNP 1-4). When two, V.42 compliant modems establish a connection, they use LAPM to control data errors and retransmit "bad" data blocks. If one modem supports V.42 and the other supports only MNP, then the two negotiate to use MNP protocol. In both cases, the error-control process is automatic and requires no special user action or software programs. V.42 bis roughly corresponds to MNP Level 5. The difference is the amount of data compressed: V.42 can usually generate a 4:1 ratio of data compression, depending on the type of file transmited.


    Mark, Space

    통신에서 나타내는 Mark는 2진수의‘1’을 나타낸다. 통신 회선은 정상이지만 통신이 행해지지 않을 때를 가리키고 Space는 그와 반대를 의미한다. 나중에 키보드에서도 동일한 용어가 나오지만 의미는 다르다.


    잠깐 덧붙이자면, 모뎀은 PC에서 정보를 다른 기기에 보내 고 받기 위해 개발된 것이므로 지금 하는 설명도 PC와 모뎀 의 상관 관계를 벗어날 수 없다. 외장 및 내장형 모뎀을 PC와 연결하기 위해서는 RS-232에 연결, 표준 방식으로 상호 접 속해야 한다. 모뎀의 프로토콜에 해당하는 표준 방식으로는 CCITT 및 BELL에서 제정한 표준안이 있는데, 이를 충실히 따르면 모뎀 상호 간에 호환성을 가질 수 있다. 그림 3은 모 뎀 통신의 전형적인 연결을 보여준다. 원거리에 있는 PC와 PC간에 전화선(Telephone Line)을 이용하여 통신하기 위해 모뎀이 어디에 위치해 있는지를 나타냈다. 모뎀과 PC 사이에 RxD와 TxD만 연결한 것처럼 표시되어 있는데, 뒤에서 다루 겠지만 여러 신호선이 연결되어 있다.
    표 1은 Modem Standards ITU V.XX의 권고안과 압축 에러 교정에 관한 내용을 나타낸 것이다. 모뎀 칩 회사에서 제공하는 설명서에‘V’로 시작하는 여러 기호들이 나타나거 나 호환성이 있다는 것을 나타낼 때 도움이 되는 규약들이다. 본고에서는 지면 상 내용이 생략되었지만 인터넷 웹 사이트 (http://www.ustr.net/modem/modem.shtml)에 가면 보 다 자세한 정보를 알 수 있다. 데이터 뒤에 있는 표 2는 압축 에 관련된 사항이다.
    전화 라인에 연결된 회로를 보자. 그림 4 왼쪽 하단에는 Modular Jack J1이 있는데 전화선에 연결되는 커넥터이다. PCB에는 4개 핀이 전부 납땜되지만 사용할 때는 두 개의 선 으로 전화 통화가 가능하다. 모뎀을 전화선과 연결할 때에도 동일한 커넥터를 사용하여 조립하면 된다. 보통 전화 라인에 서 들어오는 신호의 노이즈를 차단하기 위해 가장 먼저 라인 필터를 사용하기도 하지만 덩치가 커지므로 여기서는 생략했 고 대신에 비드(Bead)를 이용하여 일부 노이즈를 제거하고 자 했다. 또 퓨즈를 사용하여 과전압에 대해 기기가 보호될 수 있도록 했다. 실험을 해보지는 않았지만 회로도에서 점선 으로 표시된 1000pF/1kV의 바이패스(Bypass) 콘덴서 (Condenser=Capacitor) 두 개를 신호 라인에 대해 병렬로 사용해도 된다.
    과도한 전압이 전화선로로 들어오면 1,000V 이상의 피크 전압이 Bypass C를 통해 그라운드로 빠지게 된다. RV2는 바리스터(Varistor)라는 부품으로 천둥이나 번개와 같은 Surge Voltage를 제거하기 위한 것이다. 배리스터는 에너지 에 따라 저항 값이 변하는 소자로 Surge 전압이 들어오면 저 항이 거의 0에 가까워 전화 라인이 서로 합선(Shot)되어 전 류가 급격히 흐르고, 결국 자신이 파괴된다(육안으로 보기에 는 땅콩이 두 쪽으로 갈라지는 모양). 그러므로 낙뢰 등 순간 적인 과전압이 발생하여 기기에 한 번 유입되고 나면 RV2471(47*101V)은 파괴되어 다음으로 들어오는 Serge를 막 을 수 없다. 퓨즈처럼 한 번 사용하면 교체해야 하는 소모품 소자이지만 교체하지 않아도 되는 Poly Switch가 있다.
    전화 라인으로 전화가 오면 어떻게 될까? Ring_DET(Ring Detect) 신호에 전화가 걸려오면 선로에는 150V(실효값 : 75Vrms)의 전압이 흐르는데 이를 5V로 변환해서 보내준다. 여기서 전화 라인에 직접 오실로스코프(TEKTRONIX, TDS680B)로 측정한 파형을 제시한다. 평상 시 전화가 결려 오지 않은 상태에서는, 약간 출렁이긴 하지만 DC로 46V 정 도 나오다가 전화벨 신호가 파형에 잡힌다. 전화벨이 울리는 시간은 1.02초, 쉬는 시간은 2.01초로 전화벨이 울릴 때마다 Ring_DET는 33.6%{=1.02/(2.01+1.02)*100}Duty의 ‘A’부분 파형에서 양(+)의 값을 검출하여 5V 신호가 발생 한다. ‘A’부분 파형을 확대하면 주파수 20Hz(1/50ms)의 구형파임을 알 수 있다. 그림 5에 전화벨이 울렸을 때의 파형 을 나타냈고, 벨이 울리는 부분의 파형 확대는 그림 6에서 볼 수 있다.
    회로도의 U13(도시바 : 4N35)과 U12(HP:6N136) IC는 서로 동일한 동작을 하는 부품이기 때문에 둘 중 하나만 PCB 에 납땜하면 된다. U12는‘Single Channel High Speed Optocoupler’이다. 2번, 3번 핀의 Anode, Cathode 핀에서 링이 검출되어 LED(Light Emitting Diode)가 ON(발광)되 면 5번과 6번 핀에 있는 TR이 도통(On)되어 연결돼 있는 6 번 핀의 전압이 GND로 흘러 들어가면서 신호(Ring_DET) 는 Low가 된다. 이 때 10KΩ 저항이 TTL(Transistor Transistor Logic)의 전압 레벨로 만들어 준다.
    Off_Hook(Modem) 신호는 CPU에 의해 모뎀을 사용하고 자 할 경우 릴레이(Relay)를 구동, 전화 회선과 모뎀 회선을 서로 연결시켜주는 스위치 역할을 한다. 평상시에는 Q1이 오 프돼 있어 릴레이가 구동되지 않으므로 모뎀이 전화기와 단 절되어 있다. T1의 Transformer는 1차측 300~3400Hz에 서 임피던스(Impedance) 600Ω±20%, 권선비 1:1±3%의 절연용 트랜스이다. 특히 1차측에서 DC 전류는 최소한 80mA까지 흘러야 하고 삽입 손실(Insertion Loss)은 2.3dB 이하로 한다.

    그림 7. 전화 라인과 링 검출 파형

    그림 5. 전화 라인 측정 파형

    그림 6. 링 신호‘A’확대


    이 제품은 선로 측과 모뎀 회로 사이를 분리하고 서로 간에 신호 손실의 보상이 되도록 하는데 목적이 있다. 또한 회선이 연결(통화) 되었을 때 최대 120mA 정도의 직류 전류가 교환기로부터 흘러 들어오기 때문에 직류가 중첩되어도 신호의 전달 특성이 변화하지 않아야 한다.
    그림 7은 전화 라인을 홈 가드 보드에 연결한 후 프로그램 을 실행시키고 하이퍼터미널 윈도우에서 숫자‘2’를 누르고 나서 다른 전화로 보드에 전화를 건 다음의 파형을 측정한 것 이다. Ch1은 전화 라인 양단의 전압을 나타낸 것이고 Ch2는 U12의 6번 핀 또는 U13의 5번 핀의 링 검출 신호 결과를 나 타냈다. Ch1의 전압 레인지(Range=Vertical Scale)는 100V이므로 세로 한 칸 반의 전압이 150V를 나타내고 가로 사각형 한 칸이 5ms이므로 0V를 유지하는 시간은 25.1ms임 을 파형에서 보여준다. 전체적으로 신호를 길게 합치면 앞에 서 다루었던 2초간 쉬고 1초간 링을 발생하는 전화벨 신호에 서 주파수 20Hz(1/50ms)의 구형파를 확대한 것과 같다. Ch2는 Ch1의 링 신호 하강 부분을 검출한 파형인데 마이컴 의 I/O 포트에서 보면 1.8ms동안 Low를 유지한다. 다시 말 해 벨이 울리는 1초 동안(쉬는 시간 2초) 20번의 Low 신호 가 검출되는 것이다. 그래서 벨 신호 횟수를 Source 1과 같 이 검출하면 정확한 벨 횟수에 문제가 발생하기 때문에, 인터 럽트로 처리하는 방법과 하드웨어적으로 콘덴서 혹은 플립플 롭을 사용해 파형을 평탄하게 하는 방법을 권하고 싶다.
    Source 1. 전화벨 검출 테스트 프로그램

    /*
    목적 : 전화벨 검출 Test 프로그램
    File Name : GUARD2.C의 일부분
    --------------------------------------------------------
    */
    switch(dip_sw){ // 딥 스위치 값이 0x3X이면 실행
    case(Modem_Test): // This is Z02201 Modem Controller Test
    putstring("₩n**********************");
    putstring("₩n* Target Board of Home Guard, MODEM TEST*");
    putstring("₩n**********************");
    putstring("₩n₩n");
    putstring("CMD>Push '?'or 'H' key then Commands display₩nCMD>");
    while(Modem_Test){ // 딥스위치 설정 상태가 맞으면 무한 루프
    wdt();
    if(check_pop() && get_char==0x0D) // CR(Enter) check
    putstring("₩nCMD>"); // check q-buffer and run
    switch(get_char){
    case('h'):case('H'):case('?'):
    putstring("Status R/W/R(1), Ring Detect(2), Stop(Enter)₩nCMD>");
    break;
    case('1'):case('!'): // 특별한 목적 없는 모뎀 테스트 루틴
    putstring("₩nCMD>");
    putstring("Read MODEM Status Register:");
    putbyte(xtoa_h(MDMST));// 부록의 gu_hard.h 참조
    putbyte(xtoa_l(MDMST));
    putstring("₩nCMD>Read MODEM Status After Writer:");
    MDMST=0xA0;
    putbyte(xtoa_h(MDMST));
    putbyte(xtoa_l(MDMST));
    putstring("₩nCMD>");
    break;
    case('2'):case('@'):// Ring Detect
    Ring_DET=1; // 벨 검출 초기값
    Off_Hook=HOOK; // 통화 수화기를 전화기에 내려놓은 상태
    ring_count=0; // 벌 검출 초기값
    while(100){ // 무한 루프
    wdt(); // Feeding dog
    if(Ring_DET==0){ // I/O로부터 Low 입력이면 링 검출
    ring_time=0;// 벨이 한번 울리고 전화가 끊어질 수 있으므로
    ring_count++; // 링 카운트 증가
    putstring("Now! Ring Detect: ");
    putbyte(xtoa_l(ring_count)); // 검출 횟수 프린터
    putstring("₩nCMD>");
    } // end if(Ring_DET==0){
    if(ring_count==RING_4TH){ // 4번 검출되면 실행
    putstring("Now! Connect Tel Line ");
    putstring("₩nCMD>");
    ring_count=0; // 카운트 다시 초기화
    Off_Hook=HOOK_NO; // 수화기를 든 상태, 릴레이 동작
    break; // Out of while Routine
    } // end if(ring_count==RING_4TH){
    if(ring_time>TIME_30SEC){ // TIME_30SEC은 3초
    ring_time=0;// Ring 검출 시간 초과
    ring_count=0; // 벨이 울리고 3초 경과, 카운트 무효
    }
    if(check_pop() && get_char==0x0D) // CR(Enter) check
    putstring("Stop Tel Ring Detect ₩nCMD>");// 엔터키
    } // end while(100)
    default: break;
    }// end switch(get_char){
    } // end while(Modem_Test){
    break;
    //=============================================================




    그림 8은 모뎀 칩 주변을 나타내는 3/8 회로도의 일부분이 다. U15는 모뎀을 선택하기 위한 디코드이고 U10이 모뎀 칩 이다. 5핀 AP3은 나중에 칩 상태를 검사할 때 사용할 것 같 아서 붙여놓았다. ‘To Line’은 실제로 전화 라인과 연결되는 부분이며 나머지 주변에 있는 회로는 Z02201의 데이터 시트에서 추천해준 그대로 구성했다. 74HA138의 디코드에 의해 Chip Select 신호가 발생하고 A0~A2의 어드레스에 의해 레지스터 를 선택하게 되어있는데 병렬 방법으로 인터페이 스 했기 때문이다.
    U10의 Z02201은‘V.22BIS Modem Data Pump with Integrated AFE’라는 이름을 가진 Zilog 회사의 모뎀 칩으로 전화 라인과 마이컴을 연결하는데 다리 역할을 한다. 용어에 있는 Data Pump는 캐리어 주파수를 가진 실질적 DSP를 지칭하고 전송된 디지털 데이터의 변조 및 복조 를 담당한다. Data Pump 모뎀 칩으로는 이밖에 동급의 TSC73K324L, RC2324 등이 있다. 자일 로그 회사의 모뎀에 관련된 기타 사항은 웹사이 트(http://www.zilog.com/products/)의 ‘Embedded Modem Solutions’항목에 있으며 하드웨어와 프로그램 설정과 관련된 보다 자세한 사항을 참조할 수 있다.
    44핀 PLCC IC Z02201의 데이터 시트는 설 정 값이 많아 상대적으로 다른 제어 IC에 비해 이 해하기 난해하며 모뎀 관련 용어가 많은 것이 특 징적이다. 사실 모뎀 부분은 생각보다 많은 통신 기술을 요구한다.
    필자도 이 부분의 프로그램은 완벽하게 될 때 까지 공개를 하지 않을 생각이다. 다만 본고에서는 독자들이 스스로 해결하는데 도움이 되도록 모뎀 설정과 원리, C 프로 그램 함수에 대해 다루도록 하겠다.
    Z02201은 TTL과 호환성이 있으며 인터페이스 할 때 병렬 모드와 직렬모드로 선택해서 할 수 있다. 홈 가드는 병렬(패 럴렐) 8비트로 해서 8051 코어 DS5002FP가 칩 제어를 하 도록 했다. 이 때 8비트 I/O 모뎀 레지스터는 직접 제어할 수 있고 모뎀의 RAM 데이터를 읽고/쓰고는 간접 제어가 가능 하다. CPU와 병렬로 인터페이스 할 때는 V.24(RS-232) 신 호를 연결하지 않고 15개의 신호선과 통신선만 있으면 된다.


    AFE, CODEC

    AFE(Analog Front End)에는 아날로그를 디지털로 변환하는 D/A같은 장치 혹은 CODEC(Coder/Decoder)이 들어있다. CODEC은 음성 신호 등을 디지털로 보내기 위해 전화기에 부가하는 장치로 부호화와 복호화를 지칭하는 합성단어다. 여기에서의 용도 는 디지털 신호 대역폭을 최대로 하거나 압축과 풀기를 하기도 한다. 또한 AFE에는 적절한 주파수로 주기적 샘플 인터럽트를 발생할 수 있는 타이머가 포함된다.


    Z02201의 주요 특징

    - Data Modem Through to 2400Bps
    ·ITU V.22bis, V.23, V.21
    ·Bell 212A and Bell 103
    - FSK(V.23, 1200/75Bps, V.21/Bell 103 300Bps),
    DPSK(V.22/Bell 212A 1200Bps) 또는 QAM
    Encoding(V.22bis 2400Bps)
    - Scrambler/Descrambler 기능
    - 톤 발생, 톤 검출
    - 시리얼 또는 패럴렐로 인터페이스 가능
    - 두 형식의 Handshake Timing
    - HDLC Framing 지원
    - 외부 메모리가 필요 없음
    - 저전력
    ·50mA Active Mode
    ·25μA Sleep Mode
    - PLCC 44핀
    - 5V 단일 전원 사용
    - 보통 0~70℃ 사용


    표 3. Z02201 모뎀 칩 핀 설명

    신 호I/O설명
    1/RESETIReset, 부논리(Active Low)
    2, 26GND-그라운드, 0∼70℃ 동작, 납땜 온도 230℃에서 10초
    3TEST1ITest Pin 1, 디지털 그라운드와 연결
    4EYECLKOEye Pattern Clock, 상승 트리거일 때 유효, Eye Pattern Display의 D/A 변환기 쉬프트 레지스터의 클록으로 사용
    5EYEOUTOEye Pattern Data, 시리얼 16비트 Eye Pattern 데이터
    6EYESTBOSerial Eye Pattern Strobe, D/A 변환기 로딩 신호로 사용
    7, 17AVDD-Analog Power 5V
    8TXO+AOTransmit Differential Analog Output Positive, 전화 라인과 600Ω으로 연결
    9TXO-AOTransmit Differential Analog Output Negative
    10, 12AGND-Analog Ground 0V
    11VrefAOReference Voltage, 전압 발생 장치에서 사용
    13, 14CF1, CF2AIIntegration Capacitor Pin, 두핀 사이 82㎊ 연결, 내부 필터
    15RXI-AIReceive Differential Analog Input Negative
    16RXI+AIReceive Differential Analog Input Positive
    18/HCSIHost Chip Select, 부논리(Active Low), 0(Low)->Z02201 선택
    19~21HA0∼HA2IHA2가 MSB(Most Signification Bit)
    22/HIRQOHost Interrupt Request, Open Drain, Pull-Up 저항연결, RXIE와 TXIE 비트 설정에 의해 출력
    23/HWRIHost Write Enable Strobe, Data Pump에 쓰기, 부논리
    24, 44Vcc-5V±0.5, 동작 시 50mA 소비전류 @25℃
    25/HRDIHost Read Enable Strobe, Data Pump에서 읽기, 부논리
    27∼34HD0∼HD7I/O양방향, 정논리(Active High), Host Data Bus
    35/RLSDOReceive Line Signal Detect, 0->입력신호 검출
    36RxDOReceive Data, Data Pump의 Serial Data
    37TCLKOTransmit Serial Data Clock, CPU와 시리얼 통신 동기 데이터
    38TxDITransmit Data, Data Pump의 Serial Data
    39/OHOOff Hook Relay Control, 전화와 연결하는 릴레이를 제어
    40/RTSIRequest To Send, RTSP 비트에 의해 결정, Standby 모드일 경우 Don't Care
    41TEST2/RCLKI/OTest Pin 2/Receive Data Clock, 디지털 그라운드 연결
    42XTALOCrystal Oscillator Output
    43EXTALICrystal Oscillator Input, 24.576MHz 크리스탈 연결


    표 4. 모뎀 통신 방법 선택

    구성ModulationBpsBaud비트 당 표현 수
    V.22 bis 2400QAM24006004
    V.22 bis 1200DPSK12002
    V.22 12002
    V.23 1200/75FSK1200/751200/751
    V.213003001
    Bell 212ADPSK12006002
    Bell 103FSK3003001


    CRC(Cycle Redundancy Check)
    CRC(Cycle Redundancy Check)는 HDLC(High Level Link Control) 같은 동기식 전송의 경우 많이 사용하는 오류 검출 방식이 다. 이는 보내는 데이터를 고차의 메시지 다항식으로 간주하고 정해진 생성 다항식(Checking Polynomial)으로 나눈 후, 계산한 값의 나머지 BCC(Block Check Code)를 데이터 다음에 추가하여 송신하는 원리다. 수신측은 보낼 때 계산한 생성 다항식과 동일한 다항식 을 이용해 계산한 후 나머지가 없으면 전송된 데이터가 정확하다고 판단한다. Checksum에 비해 복잡하고 한 비트의 오류는 수정이 가 능하나 두 비트 이상의 오류는 불가능하다.


    표 9. Modem RAM Map

    기호Address(Hex)설명
    CONFIG01FFData Pump Configuration
    TRNCTRL01FETraining Control
    BUFCTRL01FDBuffer Control
    TONESTATUS01FCDTMF, Tone Control 상태
    DPCTRL01FAData Pump 기타 제어
    MSTATUS01F7Modem 제어, 상태
    EQMMaxThresh01F6MSE 최대 경계 값
    RLSDoffThresh01F5RLSD Off 경계 값
    RLSDonThresh01F4RLSD On 경계 값
    CONN_Mode01F0Connection Speed After Handshake is Complete
    DTMFfh_lev01A1DTMF High Band Transmit Level
    DTMFfl_lev01A0DTMF Low Band Transmit Level
    TONEGENA191Tone Generator A
    TONEGENB196Tone Generator B
    TxLevel185Modem Transmit Level
    Seq3Count018EDial Timer Inter-Pulse Count
    Seq1Count018DDial Timer Off Count
    Seq1Count018CDial Timer On Count
    Biquad A Coeff0155∼015EBiquad A 계수
    Biquad B Coeff015F∼0168Biquad B 계수
    Tone Coefficients0145∼0154Tone 검출 계수
    EQMlev92Eye Quality Monitor Level
    ThreshOFF52Biquad Detectors Off Point
    ThreshON51Biquad Detectors On Point
    ToneLevels026∼035Tone 검출 Level
    ToneThresh3Tone 검출 경계 값
    DTDStstus0Discrete Tone Detector Status


    그림 9의 오른쪽 아래에 EYE로 시작하는 3선 Eye Pattern은 16비트 시리얼 커뮤니케이션에서 사용하는 핀이 다. 이는 동기(EYECLK)에 의해서 X-Axis의 8비트, Y-Axis 의 8비트를 보내게 되어 있으나 홈 가드는 사용하지 않는다.
    표 3은 Z02201 모뎀 칩의 핀 설명이다. I(Input)와 O(Output)는 디지털 입/출력, AI(Analog Input)와 AO(Analog Output)는 아날로그 신호와 관련된 입/출력을 나타낸다. 용어에 나오는 Host는 마이컴 즉 DS5002FP를, Data Pump는 모뎀 칩 Z02201의 메모리를 가리킨다. TxD(38), RxD(36), /RTS(40), /RLSD(35), TCLK(37), RCLK(41)는 병렬 인터페이스 모드에서는 사용하지 않는다.
    Z02201은 표 4와 같은 통신 방법을 프로그램에 의해 선택 할 수 있다. 홈 가드에서는 구성 항목의 두 번째‘V.22 bis 1200’을 사용하여 프로그램 하고자 했다. QAM(Quadrature Amplitude Modulation), FSK(Frequency Shift Key), DPSK(Dual Phase Shift Keying)는 모뎀에서 사용하는 용어이다.
    ‘Modem Data Pump’라는 이름의 IC Z02201은 소프트 웨어에 의해 인터페이스 하기 위해서 크게 두 가지 어드레스 가 있다. 하나는 외부 하드웨어에 의해 HA0~HA2(핀 19~21)까지 선택하는 인터페이스 레지스터 어드레스이며, 다른 하나는 칩 내부에 있는 모뎀 DSP RAM 어드레스이다. 전자는 마이컴의 어드레스에 의해 제어되는 8비트 레지스터 로서, 이곳에 설정하고자 하는 모뎀 DSP RAM 어드레스와 데이터 값을 넣으면 16비트 DSP RAM 영역을 제어할 수 있 다. DS5002FP의 A2~A0 어드레스 버스와 연결된 Z02201 핀의 HA2~HA0은, 각 조합에 의해 7개의 8비트 내부 레지 스터에 값을 읽고 쓸 수 있다. 내부 레지스터는 RAMDL (RAM Data Low Byte)과 RAMDH(RAM Data High Byte)가 조합을 이루어 RAM 데이터 16비트를 만든다. 그리 고 RAMAL(RAM Address Low Byte)과 RAMAH(RAM Address High Byte)에 의해 0x1FF~0까지의 어드레스 공 간을 읽고 쓰기할 수 있도록 한다. 여기에는 DATAP(Data Parallel)에 의해 병렬(Parallel)모드에서 데이터 전송 시 사 용하는 레지스터, RAM Control & States, 모뎀 상태를 알 려주는 Modem(=Data Pump) Status 레지스터, HDLC가 포함된다.
    0~111까지 7개의 레지스터가 표 5에 정리되어 있다. 표 에서 음영으로 되어 있는 6개의 레지스터 비트는 상하가 한 쌍으로 AND가 취해지고 다시 3개의 AND 출력이 NOR 게 이트와 연결, 최종 출력에 Z02201의 22번 핀 /HIRQ에 연결 되어 있다.


    표 5. Z02201 Interface Register Map

    FunctionHA2,1,0B7B6B5B4B3B2B1B0Access
    RAM Access Low000=0RAMDL(RAM Data Register Low Byte), RAM을 읽고/쓰고 할 때 데이터로 사용R/W
    RAM Access High001=1RAMDH(RAM Data Register High Byte), RAM을 읽고/쓰고 할 때 데이터로 사용
    RAM Access Address010=2RAMAL(RAM Data Address Low Byte), RAMAH는 High Bit를 나타냄W
    Parallel Data011=3DATAP(Parallel Data), TPDM 레지스터 비트와 관계R/W
    RAM Control & Status100=4TXIERXIERAMIETPDMRTSPRAMRWRAMRQRAMAH
    Modem Status101=5TXIRXIRAMIDPFLCTSPRTRNDCDETRESR
    HDLC111=700000TENDRXERREOFR/W


    표 6. RAM Control & Status Register

    기 호설명(HA2, HA1, HA0 : 100=4 : REG4)
    RAMAHRAM Address High. 1→ 0xFF번지 이상을 지정, 0→ 이하의 번지
    B0
    RAMRQDSP RAM Access Request. 1→ 모뎀 내부 RAM의 읽기/쓰기 요구, 0→ Request 완료
    B1
    RAMRWDSP RAM Read/Write. 1→ RAM의 쓰기 요구, 0→ RAM의 읽기 요구
    B2
    RTSPRegister Request to Send. /RTS 40번 핀과 OR로 연결되어 있다. 1→ DSP 데이터 전송중, 0→ DSP 제어중
    B3
    TPDMSelect Parallel Data Mode. 1→ 병렬(Parallel) 데이터 모드, 0→ 직렬(Serial) 데이터 모드
    B4
    RAMIERAM Interrupt Enable. 1→ RAM 읽고 쓰기를 완료 후 Data Pump에 인터럽트를 발생한다.
    B5
    RXIE병렬 데이터 모드에서 Receive Data Interrupt Enable. 1→ RXI(REG5에 있음) 비트가 1일 경우 Data Pump에 인터럽트를 발생한다.
    B6
    TXIE병렬 데이터 모드에서 Transmit Data Interrupt Enable. 1→ TXI(REG5에 있음) 비트가 1일 경우 Data Pump에 인터럽트를 발생한다.
    B7


    표 7. Modem Status Register

    기호설명(HA2, HA1, HA0 : 101=5 : REG5)
    RESReset Mode. 1→ DSP(Z02201)가 하드웨어적으로 Reset 또는 Power On시에 Reset 상태, 0→ Data Pump는 Reset을 완료한 상태
    B0
    CDETCarrier Detect. 1→ 데이터 전송 준비가 되어있는 상태,
    0→RTRND가 설정된 상태 또는 Remote MODEM으로부터 검출된 신호가 없을 때
    B1
    RTRNDRetrain Detect, 2400Bps(V.22bis일 경우만 해당), 1→ Retrain Sequence Detect
    B2
    DPBUSYData Pump Busy, HDLC에서는 의미 없음. 1→ 데이터 전송 시작,
    0→ Standby 모드, 수화기를 올려놓았을 때, 전화 라인이 접속이 없을 때
    B3
    RAMIData Pump Interrupt Status. 1→ Data Pump RAM에 읽기/쓰기 요구 진행 중
    B4
    RXIReceive Interrupt Status. 1→ 병렬 데이터 전송모드(TPDM=1)이며 DATAP 레지스터에 8비트 데이터를 쓰기,
    0→DATAP로부터 읽음
    B6
    TXITransmit Interrupt Status. 1→ 병렬 데이터 전송모드(TPDM=1)이며 DATAP 레지스터에서 8비트 데이터 읽음, 0→ DATAP에 쓰기
    B7


    표 8. HDLC Register

    기호설명(HA2, HA1, HA0 : 111=7 : REG7)
    EOFReceive End of Frame. 1→ HDLC 프레임 수신 완료
    비트 0
    RXERRReceive Error. 1→ HDLC CRC 수신 에러
    비트 1
    TENDTransmit End of Frame. 1→ HDLC 프레임 전송 완료, 0→ CRC 바이트 전송
    비트 2


    예를 들어 TXIE, TXI가 동시에 로직1이 되면 나머지 신호 가 로직0이여도 /HIRQ 핀이 활성화되어 Interrupt Request 를 할 수 있다. 표 5 및 표 6~8과 이어지는 내용은 자일로그 칩 매뉴얼(http://www.zilog.com)을 참고했다. 그 외 필자 가 미처 설명하지 못한 부분은 직접 인터넷 매뉴얼을 참고하 길 바란다.
    Z02201도 레지스터가 여러 개 있는 Control Chip이므로 상당히 복잡하게 느껴질 수도 있다. 그러나 많은 레지스터가 모뎀 제어에서 한번 설정해 놓으면 거의 바뀌지 않으므로 일 정 절차와 목록을 빠짐없이 해야 손대는 일이 없을 것이다.
    Source 2. DSP RAM 기록 시의 절차 및 예제 프로그램
    DSP RAM에 기록할 때의 절차 및 예제 프로그램
    1) RAMDL, RAMDH에 데이터 쓰기
    2) RAMAL, RAMAH에 레지스터 주소 쓰기
    3) RAMRW=1, RAMRQ=1
    4) DSP에 의해 RAMRQ=0이 될 때까지 대기(약 105μs)
    // Sub Routine Program
    void write_DSP_RAM(unsigned int address, unsigned int value){
    unsigned char conan;
    PE_EN();
    RAMDL=value;
    RAMDH=(uchar)(value >> 8); // 오른쪽 쉬프트 8번
    RAMAL=(uchar)address;
    if(address&0x0100) // Address is high int value, 어드레스를 High와 Low로 나눔
    RAMCS|=0x01; // set=1, high byte
    else RAMCS&=0xFE; // Low Byte 어드레스
    RAMCS|=0x04; // OR 0000 0100, RAMRW=1, RAM Control State
    RAMCS|=0x02; // OR 0000 0010, RAMRQ=1, RAM Control State
    XDATA_EN();
    time.modem=0; // modem wait check time out, 모뎀 응답 검사
    PE_EN(); // 아래 RAMRQ=0이 될 때까지 기다림
    //#define RAMRQ 0x02 // 0000 0010
    //#defineRAMRW 0x04 // 0000 0100
    conan=RAMCS & 0x02;// RAMRQ 변수를 직접 사용하면 컴파일 정상으로 안됨
    XDATA_EN();
    while (conan){ // RAMCS & 0000 0010
    XDATA_EN();
    wdt();
    if(time.modem>=TIME_03SEC){ // 3초 이상 모뎀 칩을 기다릴 수 없음
    flag&=∼MDM_FLAG; // MDM_FLAG의 값을 반전
    putstring("₩nCMD>Break/Remove MODEM Chip at write mode₩nCMD>");
    break;// while 루프를 빠져나감
    } // end if(time.modem∼
    PE_EN();
    conan=RAMCS;
    XDATA_EN();
    conan&=RAMRQ; // 다시 검출
    } // end while(RAM∼
    XDATA_EN();
    }
    /************************************/


    Source 3. DSP RAM 판독 시의 절차 및 예제 프로그램
    DSP RAM으로부터 읽을 때의 절차 및 예제 프로그램
    1) RAMAL, RAMAH에 레지스터 주소 쓰기
    2) RAMRW=0, RAMRQ=1
    3) DSP에 의해 RAMRQ=0이 될 때까지 대기(약 105μs)
    4) RAMDL, RAMDH로부터 데이터 읽음
    // Sub routine Program
    unsigned int read_DSP_RAM(unsigned int address){
    unsigned int intpass;
    unsigned char charpass;
    PE_EN();
    RAMAL=(uchar)address; // low address setting
    XDATA_EN();
    if(address & 0x0100){ // Address is high int value, RAMAH
    PE_EN();
    RAMCS|=0x01; // RAM address High is 1
    XDATA_EN();
    }
    else {
    PE_EN();
    RAMCS &= 0xFE; // RAM address High is 0
    XDATA_EN();
    }
    PE_EN();
    RAMCS|=0x02; // OR 0000 0010, RAMRQ=1, RAM Control State
    RAMCS&=0xFB;// AND 1111 1011, RAMRW=0
    XDATA_EN();
    time.modem=0; // modem wait check time is initial
    PE_EN();
    charpass=RAMCS & 0x02; // RAMRQ=0000 0010=0x02
    XDATA_EN();
    while(charpass){ // RAMCS & 0000 0010
    wdt(); // (After Read RAM Control Status) AND (RAMRQ(0000 0010))
    XDATA_EN();
    if(time.modem>=TIME_03SEC){// 3초 이상이면 무언가 잘못됨
    flag&=∼MDM_FLAG; // disable modem 플래그
    putstring("₩nCMD>Break/Remove MODEM Chip At Read Data ₩nCMD>");
    break;
    } // end if(time.modem∼
    PE_EN();
    charpass=RAMCS; // RAMRQ=0000 0010=0x02
    XDATA_EN();
    charpass&=0x02;
    } // end while(RAM∼
    PE_EN();
    intpass=(unsigned int)(RAMDH<<8) | (unsigned int)(RAMDL);
    XDATA_EN();
    return (intpass);// 데이터 값 16비트 리턴
    }
    /************************************/


    표 9. Modem RAM Map

    기호Address(Hex)설명
    CONFIG01FFData Pump Configuration
    TRNCTRL01FETraining Control
    BUFCTRL01FDBuffer Control
    TONESTATUS01FCDTMF, Tone Control 상태
    DPCTRL01FAData Pump 기타 제어
    MSTATUS01F7Modem 제어, 상태
    EQMMaxThresh01F6MSE 최대 경계 값
    RLSDoffThresh01F5RLSD Off 경계 값
    RLSDonThresh01F4RLSD On 경계 값
    CONN_Mode01F0Connection Speed After Handshake is Complete
    DTMFfh_lev01A1DTMF High Band Transmit Level
    DTMFfl_lev01A0DTMF Low Band Transmit Level
    TONEGENA191Tone Generator A
    TONEGENB196Tone Generator B
    TxLevel185Modem Transmit Level
    Seq3Count018EDial Timer Inter-Pulse Count
    Seq1Count018DDial Timer Off Count
    Seq1Count018CDial Timer On Count
    Biquad A Coeff0155∼015EBiquad A 계수
    Biquad B Coeff015F∼0168Biquad B 계수
    Tone Coefficients0145∼0154Tone 검출 계수
    EQMlev92Eye Quality Monitor Level
    ThreshOFF52Biquad Detectors Off Point
    ThreshON51Biquad Detectors On Point
    ToneLevels026∼035Tone 검출 Level
    ToneThresh3Tone 검출 경계 값
    DTDStstus0Discrete Tone Detector Status

    [출처] MODEM |작성자 맥가이심





    출처: http://www.icbanq.com/elecinfo_net_new/Elec_TechInfo_Main.aspx

Designed by Tistory.