390 likes | 1.02k Views
8051 Serial 통신. Mode 0 : 동기 통신 Mode 1,2,3 : 비동기 통신. dolicom@naver.com http://blog.naver.com/dolicom. 통신 시 동시에 보내는 데이터 비트수. 패럴럴 통신 (Parallel) 두 지점 간 데이터 시 데이터 연결 수가 많다 . 8 비트를 많이 사용 LPT(Printer), SCSI(HDD), ATAPI(HDD) 데이터의 비트수가 많아 여러 선이 필요하므로 원거리 통신에 불리 시리얼이 고속 통신이 가능하여 사용이 주는 추세
E N D
8051 Serial 통신 Mode 0 : 동기통신 Mode 1,2,3 : 비동기 통신 dolicom@naver.com http://blog.naver.com/dolicom
통신 시 동시에 보내는 데이터 비트수 • 패럴럴 통신 (Parallel) • 두 지점 간 데이터 시 데이터 연결 수가 많다. • 8비트를 많이 사용 • LPT(Printer), SCSI(HDD), ATAPI(HDD) • 데이터의 비트수가 많아 여러 선이 필요하므로 원거리 통신에 불리 • 시리얼이 고속 통신이 가능하여 사용이 주는 추세 • 시리얼 통신 (Serial) • 동시에 보내는 데이터 수는 하나 • 패럴럴에 비해 원거리 전송에 유리 • 현재는 고속으로 전송으로 거리 제한(SATA, USB) • 패럴럴에 비해 저속이었으나 현재 고속이 가능 • UART, SPI, I2C, USB, SATA(HDD), Serial-SCSI
시리얼통신 데이터 사이 분리 방식 • 동기식 통신 • 전송 후 데이터 사이 구별을 데이터 클럭 사용 • 별도의 데이터 클럭 신호 필요 • 비교적 고속 전송, 가까운 거리 - 칩간 통신 • SPI, I2C • 비동기식 통신 • 전송 후 데이터 사이를 수신 쪽에서 구별 • 별도의 데이터 클럭이 필요 없음 • 비교적 저속 전송 속도, 원거리 • 장치간 통신 ( PC – PC, PC - 전자장치)
UART (RS-232C) • 두지점 간 비동기 시리얼 통신 • CPU의 초기부터 사용 • 데이터 수 5,6,7,8로설정 가능 • 에러 탐색을 위한 EVEN/ODD parity 사용 • 비교적 간단한 통신 방식, 속도 낮음, 원거리 • BAUD RATE (BPS와 비슷함) • 전송 라인은 디지털 전압보다 높음 – 원거리 전송 • Mark (1) : -3 ~ -12 V • SPACE (0) : +3 ~ +12V • 높은 전압 필요
I2C 수신 측에서 데이터 수신여부 확인하기 위해 송신 측에서는 1로 하고 수신 측에서 ACK 신호를출력 한다. SCL이 1일 때 SDA가 1에서 0으로 변하면 송신 시작
RS-232C 타이밍 차트 EVEN,ODD 5,6,7,8 비트 1, 1.5 비트 0x58 전송 예
RS-232C의 전압 특성 MARK : -3 ~-12 V SPACE : +3 ~ +12V TX UART 모듈 RX 커넥터 DS9 • MAX232 : 5V <-> -10~+10V • MAX3232: 3.3V <-> -10~+10V • 자체 전원 변환 회로 추가 되어 • 별도의 파워 전환 필요 없음 CPU
모뎀은 우선 전화등을 이용 통신 채널을 열어야 하기 때문에 바로 옆에 있는 컴퓨터 처럼 사용할 수 없다. 따라서 모뎀이 통신채널을 열었는지 확인할 필요가 있다. 모뎀 제어 신호
clock Serial 관련 레지스터
TMOD 레지스터 7 6 5 4 3 2 1 0 GATE C/T M1 M0 GATE C/T M1 M0 Timer 0 Timer 1 • GATE : 외부 인터럽트 핀(INT1, INT0)을 이용해서, 타이머를 정지/동작을 제어 한다. • 1. GATE=1, TR0=1 : INT0=1 –타이머0 동작, INT0 –정지 • GATE=1, TR1=1 : INT1=1 –타이머1 동작, INT1 –정지 • 2. GATE=0 : INT0,INT1 핀을 사용하지 않으며, TCON내의 TR0, TR1에 • 따라 동작/정지 된다. • C/T (Counter/Timer selector) : 카운터/타이머 모드를 결정 • 1. C/T=1 : 카운터 모드 –입력 핀 T0, T1에서 들어오는 펄스를 센다. • C/T=0 : 타이머 모드 –시스템 클럭/12을 센다. • M1:M0 : 동작 모드 설정 • 4가지 모드
TCON 레지스터 7 6 5 4 3 2 1 0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 Timer 1 Timer0 Interrupt • TR1/TR0 : 타이머/카운터 동작/정지 제어 한다. • TR0=1 : 타이머/카운터 0 동작 • TR0=0 : 타이머/카운터 0 정지 • TF1/TF0 : 타이머/카운터 오버플로 플래그 • TF0 : 타이머/카운터 0의 카운터 레지스터(TH1, TH0)가 오버플로가 되면 • 셋된다. • *이 때 다음과 같이 인터럽트 처리 된다.. • - 인터럽트 인에이블되어 있고 • - 인터럽트 요청하게 되면 • - 인터럽트 처리가 끝나면 자동으로 클리어 된다
T2CON 레지스터 0xC8 7 6 5 4 3 2 1 0 TF2 EXF2 RCLK TCLK EXEN2 TR2 CP/T2 CP/RL2 • TF2 : Overflow가 되면 1로 되고 SW로 지움. RCLK/TCLK=1이면 동작 안함. • EXF2 : Capture/Reload일 때, T2EX가 오면 1로 됨. EXEN2=1일때 동작. • - 인터럽트 요청 EXF2=1이면 Timer2 Vector로 처리-인터럽트 루틴 실행. • - DCEN=1로 Up/Down Counter Mode에서 동작 안함. • RCLK : Serial Mode1/3에서 Receive clock으로 사용. • TCLK : Serial Mode1/3에서 Transmit clock으로 사용. • EXEN2 : Timer2 External 동작. • TR2 : Timer2의 동작 시작/멈춤 설정. • CP/T2 : Timer/ Counter(외부입력 사용) 설정. • CP/RL2 : Capture/Reload 선택.
SCON 레지스터 - 1 7 6 5 4 3 2 1 0 SM0 SM1 SM2 REN TB8 RB8 TI RI • RI : 수신완료 및 인터럽트 요청플래그 • 0-수신없음, 1-수신완료 • TI : 송신완료 및 인터럽트 요청플래그 • 0-송신없음또는 송신중, 1-수신완료 • RB8 : Mode 2,3시 수신 9번째 데이터 비트 • TB8 : Mode 2,3시 송신 할,9번째 데이터 비트 • REN: 수신가능 제어비트 • 0-수신 불가, 1-수신가능
SCON 레지스터 - 2 7 6 5 4 3 2 1 0 SM0 SM1 SM2 REN TB8 RB8 TI RI • SM : 시리얼의 동작 상태 정의 • Mode : SM0 SM1 동작 Baud Rate (속도) • 0 00 Shift Register fosc/12 • 1 01 8비트 UART 변화 • 2 10 9비트 UART fosc/12 또는 fosc/32 • 3 11 9비트 UART 변화 • SM2 : 모드2,3에서 멀티통신 관련 비트 • 0 - 싱글 통신 기능으로 동작함. • 1 - 수신데이터 비트(RB8)가 1인 경우만 RI 비트를 세트시켜 • 8051 코어로 하여금 수신을 가능하도록 함. • 즉, 데이터 수신이 가능함.
SMOD– PCON 레지스터 7 6 5 4 3 2 1 0 SMOD - - - GP1 GP0 *PD *ILD • SMOD : 시리얼 클럭 타이머 0 사용할 때 • 시리얼포트의 기준클록 입력소스인 타이머0의 출력 펄스와 2분주된 시스템 클록을 다시 2분주할 것인지 선택하는 비트 • 0 – 타이머1 클럭 / 2 : 2분주 함 • 1 – 타이머1의 그대로 사용 • GP1 : 보통목적(General Purpose) 플래그 비트 • GP0 : 보통목적(General Purpose) 플래그 비트
clock Serial 클럭발생 타이머
비동기 수신 인식 – HW로 처리 MARK SPACE • 데이터 신호가 MARK에서 SPACE로 가면 수신 시작 • 전송하는 한 비트에 16/64개의 사이클을 사용하여 수신 시작 • MARK에서 0으로 바뀌는 순간 부터 16 사이클 마다 비트를 분리 • 데이터 비트 사이를 이 클럭을 사용하여 시간을 구별 • 16개의 주기가 끝나면 무조건 다음 데이터로 인식
타이머를사용한 UART 클럭발생 XTAL oscillator ÷ 2 ÷ 12 RX/TX CLOCK Timer 1/2
타이머을사용한 클럭 발생 구조 C/T = 0 TM1 Overflow TL1 8bits 1 ÷ 12 T1 pin OSC ÷ 2 TR1 ÷ 2 “0” “1” TH1 SMOD C/T = 0 “0” “1” TL2 8bits TH2 8bits RCLK T2 pin RX CLOCK ÷ 16 1 C/T = 1 C/T = 1 “1” “0” TR2 RELOAD TCLK TX CLOCK ÷ 16 RCAP2L RCAP2H
SCON:SM1=1 Serial Mode1,3-Timer1 Mode2 PMOD[1:0]:M1M0=10 PMOD[2]:C/T=0 PCON C/T = 0 TM1 Overflow TL1 8bits 1 T1 pin ÷ 12 OSC ÷ 2 RELOAD PCON:SMOD TCON:TR1 ÷ 2 “0” “1” TH1 SMOD T2CON:RCLK=0 C/T = 0 “0” “1” TL2 8bits TH2 8bits RCLK T2 pin RX CLOCK ÷ 16 C/T = 1 C/T = 1 “1” “0” TR2 RELOAD TCLK TX CLOCK ÷ 16 RCAP2L RCAP2H T2CON:TCLK=0
Serial Mode1,3-Timer2 BaudRate C/T = 0 TM1 Overflow TL1 8bits ÷ 12 OSC ÷ 2 T1 pin TR1 ÷ 2 “0” “1” TH1 SMOD PMOD[6]:C/T=0 T2CON:RCLK/TCLK=1 T2CON:RCLK=1 C/T = 0 “0” “1” TL2 8bits TH2 8bits T2 pin RCLK RX CLOCK 1 ÷ 16 C/T = 1 C/T = 1 “1” TCON:TR2 “0” RELOAD TCLK TX CLOCK ÷ 16 RCAP2L RCAP2H T2CON:TCLK=1
Serial 전송모드 • 모드 0 • 데이터의 시간 위치를 알리는 동기식. • RxD : Data In/Out으로 사용 • TxD : 데이터 클럭으로 사용 • 모드1 • 비동기 방식 – 데이터 만 사용(8bit) - UART • 에러체크를 위한 Parity가 없다. • 모드2/3 • 비동기 방식 – 데이터(8bit)+특수 1비트 – UART • SCON레지스터의 TB8/RB8비트를 CPU에서 설정 • 에러체크를 위한 parity는 8051의 P을 TB8에 전송
통신모드0–동기전송 (SPI와 유사) SBUF에 송신 데이터 쓰기 Transmit SCOC에 쓰기(RI 지워짐) Receive
통신모드 1 – 비동기 전송 Parity 불가능 SBUF에 송신 데이터 쓰기 Transmit SCOC에 쓰기(RI 지워짐) Receive
통신모드 2, 3(가변속도만 다름) Transmit Receive
Program Serial 프로그램
UART // file : uart.h #ifndef _UART_H #define _UART_H void Init_SerialTm(void) ; // Serial & Timer 초기화 void putchar(char ch); #endif #include <reg8051.h> void putchar(char ch) { while (!TI); //시리얼 버퍼 SBUF가 비어질 때까지 대기 SBUF = ch; TI =0; } //////////////////////////////////////////////////////// // Serial & Timer 초기화 void Init_SerialTm(void) { TMOD = 0x20; // 타이머1 : 모드2, 내부클럭사용 PCON = 0x00; // 만약에 19200보레이트인경우 SMOD =1 TH1 = 0xfd; // 9600 보레이트로 사용 SCON = 0x50; // 시리얼통신모드1 사용 SBUF = 0; // 초기값을 0설정(쓰레기값 방지) TR1 = 1; // Timer1 run } #include <stdio.h> #include “uart.h” void main(void) { BYTE i,c; Init_SerialTm(); putchar(‘*’); // 초기화 while(1) { putchar(‘.’); //데이터송신 delay(2); P1= c; // Port1 출력 } } void delay(int p) { int i,j; for(j=0;j<p;j++) for(i=0;i<1000;i++); }
UART #ifndef _UART_H #define _UART_H void Init_SerialTm(void) ; // Serial & Timer 초기화 void putchar(char ch); BYTE getchar(); #endif #include <reg8051.h> typedef unsigned char BYTE; void Init_SerialTm(void) // Serial & Timer 초기화 { TMOD = 0x20; // 타이머1 : 모드2, 내부클럭사용 PCON = 0x00; // 만약에 19200보레이트인경우 SMOD =1 TH1 = 0xfd; // 9600 보레이트로 사용 SCON = 0x50; // 시리얼통신모드1 사용 SBUF = 0; // 초기값을 0설정(쓰레기값 방지) TR1 = 1; // Timer1 run } void putchar(char c) { while (!TI); //시리얼 버퍼 SBUF가 비어질 때까지 대기 SBUF = c; TI =0; } BYTE getchar() { BYTE ch; while(!RI); // 수신 버퍼 ch = SBUF; RI=0; return ch; } #include <stdio.h> #include “uart.h” void main(void) { BYTE ch, cnt; Init_SerialTm(); putchar(‘*’); // 초기화 while(1) { ch= getchar(); // 데이터 수신 cnt++; // 수신 데이터 1증가 P1 = cnt; // LED에 데이터 표시 putchar(ch); // 데이터 송신 } } void delay(int p) { int i,j; for(j=0;j<p;j++) for(i=0;i<1000;i++); }
UART #include <reg8051.h> #include “uart.h” BYTE g_uCh; // UART 수신 문자 BYTE g_RxFlag; // 수신이되었는지를 나타냄 unsigned int g_tmCount; // Timer0 인터럽트에 의해 1 증가 void main(void) { BYTE cnt; Init_SerialTm(); g_tmCount = 0; cnt = 0; putchar(‘*’); // 초기화 TR0 = 1; // 타이머0 실행 ET0 = 1; // 타이머0인터럽트 인에이블( enable) EA = 1; while(1) { if (g_RxFlag) { putchar(g_uCh); //데이터송신 g_RxFlag = 0; } if (g_tmCount & 0xFF00) { P1= cnt++; // Port1 출력 } } } // 타이머 0 오버풀로워( Overflow) void intrTm0(void) interrupt 1 { TR0 = 0; // 타이머0 정지 TH0 = 0xf7; // 인터럽트 기간을 2ms ? 2170 TL0 = 0x86; //11.0592M/12=0.9216us-RELOAD g_tmCount ++; TR0 = 1; // 타이머0을 다시 시작 } #ifndef _UART_H #define _UART_H void Init_SerialTm(void) ; // Serial & Timer 초기화 void putchar(char ch); #endif #include <reg8051.h> void Init_SerialTm(void) // Serial & Timer 초기화 { TMOD = 0x21; // 타이머1 : 모드2, 내부클럭사용 // 타이머0 : mode 1, 내부 클럭사용 PCON = 0x00; // 만약에 19200보레이트인경우 SMOD =1 TH1 = 0xfd; // 9600 보레이트로 사용 SCON = 0x50; // 시리얼통신모드1 사용 SBUF = 0; // 초기값을 0설정(쓰레기값 방지) TR1 = 1; // Timer1 run } void putchar(char ch) { while (!TI); //시리얼 버퍼 SBUF가 비어질 때까지 대기 SBUF = ch; TI =0; } // 시리얼 포트의 인터럽트 벡터 void RxUart(void) interrupt 4 { BYTE ch; EA = 0; // 모든 인터럽트 디스인에이블(disable) if (RI) { g_uCh = SBUF; RI = 0; SBUF = g_uCh; } EA = 1; //모든 인터럽트 인에이블(enable) }
void Init_Uart(void){ SCON = 0x40; // mode 1, 8-bit UART, disable rcvr TMOD = 0x20; // timer 1, mode 2, 8-bit reload PCON &= 0x7f; // SMOD = 0 TH1 = 0xfd; // reload value for 19,200 baud TR1 = 1; // timer 1 run TI = 1; // set TI to send first char of UART } #include <stdio.h>void main(void){ unsigned int cnt; Init_Uart(); printf(“Hello\n”); putchar(‘O’); putchar(‘K’); putchar(‘\n’); cnt = 0; while(1) { if (! (cnt & 0x0FFF)) printf("%d ", cnt); cnt++; }}
TX Interrupt 예 #include <reg8051.h> void Init_SerialTm(void) // Serial & Timer 초기화 { TMOD = 0x20; // 타이머1 : 모드2 PCON = 0x80; // 19200인경우 SMOD =1 TH1 = 0xfd; // 19200 SCON = 0x52; // 시리얼통신모드1 사용 SBUF = 0; // 초기값을 0설정(쓰레기값 방지) ES= 1; // IE – ES:SerialPorfinterruptenablebit TR1 = 1; // Timer1 run } void putchar(char ch) { while (!TI); //시리얼 버퍼 SBUF가 비어질 때까지 대기 SBUF = ch; TI =0; } // 시리얼 포트의 인터럽트 벡터 void Uart_ISR(void) interrupt 4 { BYTE ch; SBUF = buffer[g_suCnt]; delay(50); TI = 0; if (buffer[g_suCnt +] =='₩0') g_suCnt = 0; } #include <stdio.h> #include “uart.h” int g_suCnt; char buffer[] = “8051 serial₩r₩n"; void main(void) { BYTE i,c; Init_SerialTm(); EA = 1; putchar(‘*’); // 초기화 while(1) { putchar(‘.’); //데이터송신 delay(2); P1= c; // Port1 출력 } } void delay(unsigned int k) // delay function { while (k--) ; }