제목 : 실험 #7 예비보고서 USART 통신제어 실험목적 - RS-232C 통신규격에대해이해한다. - ATmega128의 USART0과 USART1을이용한동기및비동기 RS-232C 통신방법을알아본다. 실험장비 - ATmega128(AVR Chip), MAX232CPE Chip, RS-232C 케이블 실험이론 - RS-232C 통신 직렬통신에는동기식과비동기식통신방법이있는데, 동기식통신방법은각장치들을기준클럭에동기를맞추어데이터를순차적으로전송하는방식을말한다. 동기식방식은높은전송속도를요구하는곳에서사용되나, 송수신기기간에동기를맞추어야하기때문에제어가어렵다. 비동기식통신방식은동기클럭없이장치간의데이터전송속도만을맞추어순차적으로전송하는방식을말한다. 동기식방식에비해제어가간편하지만비교적낮은전송속도를갖는다. 비동기식통신방식을 RS-232C라고한다. DTE DCE DCE DTE 컴퓨터 RS-232C 통신선로 RS-232C 모뎀모뎀 ( 전화회선 ) 컴퓨터 - 모뎀을통한컴퓨터와터미널의접속예 - - RS-232C 의신호및기능 (9 핀커넥터 ) 핀번호 명칭 신호방향 DTE-DCE 기호 1 캐리어검출 (Data Carrier Detect) DCD 2 수신데이터 (Received Data) RxD 3 송신데이터 (Transmitted Data) TxD 4 데이터단말준비 (Data Terminal Ready) DTR 5 신호용접지 (Signal Ground) SG 6 통신기기세트준비 (Data Set Ready) DSR 7 송신요구 (Request to Send) RTS 8 송신허가 (Clear to Send) CTS 9 Ring Indicator RI 1. DCD: 모뎀이상대편모뎀과전화선등을통해접속이완료되었을때, 상대편모뎀이캐리어신호를보 내오며이신호를검출하였음을 DTE에게알려주는신호선이다. 2. RxD: DCE에서 DTE로의입력직렬데이터의송신선 3. TxD: DTE에서 DCE로의출력직렬데이터의송신선 4. DTR: DTE가준비상태로되어있다는것을 DCE에게알리는신호. 이신호를 ON 상태로하면모뎀이 회선과접속을하고, OFF 상태로하면모뎀은회선과단절된다. 5. DSR: DCE가동작가능상태로되어있다는것을알리는신호. DTR로동작시켜서모뎀이회선솨접속 을하면이신호는 ON 상태로된다. 6. RTS: DCE의송신기능을제어하는신호. 이신호를 ON 상태로하면 DCE는캐리어를회선으로출력한 다. DCE로데이터를송신하고있는중에는이 RTS가반드시 ON 상태로되어있어야한다. 7. CTS: DCE가데이터를송신할수있는상태임을알리는신호. RTS에의해동작되며, 출력한캐리어가 안정되면 ON된다. 8. RI: 상대편모뎀이통신을하기위해먼저전화를걸어오면전화벨이울리는데, 이신호가인식되었음을 DTE에게알려주는신호선이다.
- RS-232C 의전기적규격및커넥터 상태 L H 전압범위 -25V ~ -3V +3V ~ +25V 논리 1 0 명칭 마크 스페이스 : 일반디지털논리는전압강하와노이즈때문에원격장치에데이터를전송하기어렵다. 따라서 RS-232C에서는어느정도의전압강하가발생하더라도일정거리는안전하게신호를전송할수있도록 각신호간전압차를늘려서규정하였다. 1 의값을 +12V, 0 의값을 12V로신호간의전압차를 24V로 만들면, 15m 내의거리는최대 19.2Kbps의속도를낸다. : RS-232C의전기적규격은위의표와같다. 즉, -3V이하일때논리 1, +3V 이상일때논리 1 로인식 된다. - RS-232C 의데이터 Frame 구성과순서 - RS-232C 전송신호의예 - 위그림에서볼수있듯이, 한바이트의데이터를송신하는데에는실제데이터의앞뒤에시작비트와정지비트를추가하여한문자의동기를맞춘다. 보통시작비트와정지비트는 1비트를사용하지만설정에따라 2비트로사용하기도한다. 전송데이터는 5비트 ~ 9비트를사용하고, 전송시의오류를검사하기위해데이터뒤에패리티비트를추가하기도한다. 따라서송 수신측이통신속도, 데이터비트, 정지비트, 패리티비트의사용유무를일치시켜야원활한통신이가능하다. 통신속도는 Baud rate라고도하는데, 이는초당전송비트를의미하며단위는 bps를사용한다. 일반적으로 2400, 4800, 9600, 19200, 38400, 57600, 115200 중하나를사용한다. - RS-232C의데이터프레임구조 - 데이터비전송시 (Idle) 엔 1 상태로있다가, 데이터전송이시작되면시작비트 (St) 인 0 상태가나타난다. 그뒤양단의설정에맞는길이의데이터비트가이어지고, 패리티비트의설정에따라패리티비트가붙게된다. 마지막으로역시양단의설정에맞는길이의정지비트가나타난뒤연속으로전송할데이터가있다면다시시작비트 (0), 더이상전송할데이터가없다면 Idle 상태 (1) 로돌아간다.
- RS-232C의인터페이스 IC (MAX232) TTL 신호를 RS-232C 레벨로변환하기위해서는라인드라이버 (SN75188) 와라인리시버 (SN75189) 가필요하다. 하지만회로의크기등의문제로, 보통라인드라이버와리시버가하나의칩으로구현된 MAX232 칩을사용한다. 라인드라이버 / 리시버를따로사용할때에는별도의 ±12V 전원이필요하였지만, MAX232칩을사용할경우 +5V 전원을그대로사용할수있다는장점이있다. - ATmega128 의 USART 회로 & 작동원리 - ATmega128 USART 회로의 Block diagram - ATmega128의 USART회로는크게클럭발생부 (Clock Generator), 송신부 (Transmitter), 수신부 (Receiver) 로구성되어있다. 클럭발생부는동기식슬레이브모드의동작을위해외부클럭 (XCK) 과동기를맞추는논리부와비동기식의통신속도를결정하는 Baud rate 발생기로구성되어있다. 송 / 수신부는하나의버퍼, 시프트레지스터, 패리티발생기 ( 송신부 )/ 검사기 ( 수신부 ) 와제어부로구성되어있다. 수신부의수신버퍼는안전한수신을위해이중버퍼구조로구성되어있다. 작동원리 : UBRR 레지스터를통해통신속도를설정하면 Baud rate 발생기가설정한값에맞는클럭을생성한다. : UCSR 레지스터를통해데이터비트길이, 정지비트길이, 패리티비트사용유무를설정하면송신시, 시작비트를출력한뒤, 송신버퍼의내용을송신시프트레지스터를통해한비트씩밀어내며출력하고, 패리티비트사용시패리티발생기가패리티값을생성해출력한다. 그뒤마지막으로설정한길이만큼의정지비트를출력해송신을완료한다. : 수신시에는, 수신한프레임의오류가없는지패리티검사기에의해확인된뒤수신시프트레지스터로값이이동되어순차적으로수신버퍼에쓰여진다.
- USART 통신과관련된레지스터 UDRn(USART I/O Data Register) 은송수신데이터버퍼의기능을수행한다. 송 / 수신레지스터의접근주소는동일하지만, 하드웨어적으로는서로별개인 TXBn, RXBn 레지스터로나뉘어져있다. UDR 의내용을읽으면 RXBn 레지스터의내용이읽어지고, UDR 에값을쓰면 TXBn 레지스터에저장되는것이다. - UDRn 레지스터 - UCSRnX(USARTn Control and Status Register) 는 USARTn 의송수신동작을제어하거나송수신상태정보를갖고있는레지스터이다. USARTn Receive Complete. RXCn 데이터의수신이완료되어버퍼에문자가들어와있으면 1로설정된다. 또한 RXCIEn 비트가 1로설정되어수신완료인터럽트사용시, 이인터럽트를발생하는데에사용된다. USARTn Transmit Complete. 송신시프트레지스터에있는문자가모두송신되어송신버퍼가비어있는상태가되 TXCn 면 1로설정된다. 또한 TXCIEn 비트가 1로설정되어송신완료인터럽트사용시, 이인터럽트를발생하는데에사용된다. 이비트에 1을쓰면 0으로클리어된다. USARTn Data Register Empty. 송신버퍼에새로운데이터를쓸준비가되었음을알리는플래그로, 1로설정되면송신 UDREn 버퍼가비어있어서송신데이터를버퍼에쓸준비가되었음을나타낸다. 이플래그는 UDRIEn 비트가 1로설정되어데이터레지스터준비완료인터럽트사용시, 인터럽트요청에사용된다. Frame Error. FEn UDRn 수신버퍼에현재수신된데이터프레임에오류가발생하였음을나타내는플래그이다. 프레임오류는데이터프레임의첫번째정지비트가 0으로검출되면 1로설정된다. Data OverRun Error. DORn 데이터수신시, 2중버퍼구조인수신버퍼가두개의문자로꽉차있는데수신시프트레지스터에새로운문자가들어와세번째문자의시작비트가검출되면 1로설정된다. USARTn Parity Error. UPEn 현재수신된데이터를수신하는동안에, 패리티오류가발생하였음을나타내는플래그이다. UPMn1 비트를 1로설정하여패리티를사용하도록하였을때에만동작한다. Double the USARTn Transmission Speed. U2Xn 비동기모드에서만적용되며, USARTn의클럭분주비를 16에서 8로낮춰전송속도를두배로높이는기능을한다. Multiprocessor Communication Mode. MPCMn USARTn의동작모드를다중프로세서모드로설정한다. USARTn RX Complete Interrupt Enable. 수신완료인터럽트를개별적으로허가하는비트이다. 이비트와 SREG 레지스터의 I비 RXCIEn 트가 1로설정된경우, 하나의문자가수신되어 RXCn 비트가 1로설정되면수신완료인터럽트가발생한다. USARTn TX Complete Interrupt Enable. 송신완료인터럽트를개별적으로허가하는비트이다. 이비트와 SREG 레지스터의 I비 TXCIEn 트가 1로설정된경우, 송신시프트레지스터가비어 TXCn 비트가 1로설정되면송신완료인터럽트가발생한다. USARTn Data Register Ready Interrupt Enable. 송신데이터레지스터준비완료인터럽트를개별적으로허가하는비트이다. 이비트와 UDRIEn SREG 레지스터의 I비트가 1로설정된경우, 송신버퍼가비어 UDREn 비트가 1로설정되면인터럽트가발생한다.
RXENn TXENn Receiver Enable. USARTn 수신부의사용을허가하는비트이다. 이비트가 1로설정되어야 RxDn 핀이 GPIO가아닌 USART 수신단자로동작하게되며, FEn, DORn, UPEn 비트의동작이유효하게된다. Transmitter Enable. USARTn 송신부의사용을허가하는비트이다. 이비트가 1로설정되어야 TxDn 핀이 GPIO가아닌 USART 송신단자로동작하게되며, 송신시프트레지스터가비어있지않으면이비트를 0으로설정하더라도전송이완료될때까지는적용되지않는다. Character Size. 전송문자의비트수를설정하는데사용된다. UCSZn[2:0] RXBn8 TXBn8 UMSELn Receive Data Bit 8. 전송문자길이가 9비트로설정된경우, 수신된문자의 9번째비트를저장하는데사용되며, 반드시 UDRn 레지스터보다먼저읽어야한다. Transmit Data Bit 8. 전송문자길이가 9비트로설정된경우, 송신할문자의 9번째비트를저장하는데사용되며, 반드시 UDRn 레지스터보다먼저써야한다. Mode Select. USARTn의동작모드를동기 / 비동시방식중의하나로설정한다. 0: 비동기방식, 1: 동기방식 Parity Mode. 패리티발생과검사형태를설정하는기능을한다. 패리티검사결과가일치하지않으면 UPEn 비트를 1로설정한다. UPMn[1:0] USBSn Stop Bit Select. 정지비트의수를결정한다. 0: 1비트, 1: 2비트 Clock Polarity. 동기전송모드에서만적용되며, 동기클럭에대해데이터출력의변화시점과데이터입력의샘플링시점을결정한다. UCPOLn - UCSRnX 레지스터 -
USARTn Baud Rate Register. 전체 16 비트중에서하위 12 비트만 Baud rate 발생용으로사용되며, USARTn 포트의송수신속도를설정하는레지스터이다. 값을쓸때에는상위바이트인 UBRRnH 를먼저쓴다음 UBRRnL 을써야한다. - UBRRn 값설정을위한공식 - UBRRn 레지스터 - - 직렬통신이이루어지는과정 (Polling 방식 ) 송신시 : UDREn 비트가 1이될때까지대기후데이터를송신한다. while(!(ucsr1a & (1 << UDRE1))); UDR1 = byte; 수신시 : RXCn 비트가 1 이될때까지대기후데이터를수신한다. while(!(ucsr1a & (1 << RXC1))); byte = UDR1; - 직렬통신이이루어지는과정 (Interrupt 방식 ) 송신시 : 데이터송신시에는폴링방식을사용하는것이좋다. 수신시 : RXCIE 비트를 1로설정해인터럽트를설정하고, 서비스루틴에서데이터를수신한다. ISR(USART1_RX_vect) { UDR1 = UDR1; 실험방법 - AVR Studio 4를이용하여프로그램소스코드작성후빌드하여실행파일 (.hex) 을생성한다. - AVR Studio 4의 AVR Programmer 를이용, AVR칩에프로그램을다운로드하여실험킷에서의동작을확인한다. - 하이퍼터미널등직렬통신용프로그램을통해통신상태를확인한다. 예제코드분석 폴링방식 - C 소스코드 #include <avr/io.h> #include "UART_Lib.h" #define LED_CS (*(volatile unsigned char *) 0x4800) UART 통신관련함수와 Baud rate 설정이정의된헤더파일. 실제함수는 UART_Lib.c 에정의되어있다. 외부 LED 의메모리매핑주소 void MCU_init(void);
int main(void) { unsigned char Message[] = "Initialization Complete!"; unsigned char buff = 0; MCU_init(); UART_init(); buff = UDR1; uart_send_string(message,25); uart_send_byte('\n'); uart_send_byte('\r'); LED_CS = 0x55; 처음실행시 UART 통신을통해전송할문자열 UART 통신시사용할문자버퍼 MCU 초기화. UART 설정초기화. UART_Lib.c 에정의되어있다. 코드상불필요해보이지만, 수신버퍼에존재할수있는쓰레기값을제거하기위해현재수신버퍼를비우는것으로생각된다. 상대측에 UART 초기화가완료되었음을알리는문자열과개행문자를전송한다. 외부 LED 를 ON 상태로만들어초기화가완료되었음을표시한다. while(1) { buff = uart_recv_byte(); UDR1 = buff; return 0; 상대측이전송한문자를수신버퍼에서가져온다. 수신한문자를다시상대측에 Echo back 시킨다. void MCU_init() { MCUCR = 0x80 ; UART_Lib.c #include "UART_Lib.h" void uart_send_byte(unsigned char byte) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = byte; void uart_send_string(unsigned char *str, unsigned char len) { int i; for (i = 0; i < len; i++) { if (!(*(str + i))) break; uart_send_byte(*(str + i)); unsigned char uart_recv_byte(void) { while (!(UCSR1A & (1 << RXC1))); return UDR1; void UART_init(void) { UBRR1L = (unsigned char) BAUD_RATE_L; UBRR1H = (unsigned char) BAUD_RATE_H; UCSR1C = (0 << UPM1) (0 << UPM0) (0 << USBS) (1 << UCSZ1) (1 << UCSZ0); UCSR1B = (1 << TXEN) (1 << RXEN) (0 << UCSZ2); UART_Lib.h #include <avr/io.h> #define BS 0x08 #define CR 0x0D #define CPU_CLOCK 8000000 #define BAUD_RATE 57600 #define BAUD_RATE_L (CPU_CLOCK / (16 * BAUD_RATE)) #define BAUD_RATE_H ((CPU_CLOCK / (16 * BAUD_RATE))) >> 8 MCU 초기화함수외부메모리 IO 를위해 SRE 비트를 1 로설정. Baud rate 설정과, 이파일에정의된함수를다른모듈과링크시키기위한헤더파일 UART 를통해한문자를전송하는함수송신버퍼가쓰기가능한상태가될때까지대기송신버퍼가쓰기가능한상태일때인수로받은문자를송신버퍼에전달하여상대측에전송하도록한다. UART 를통해문자열을전송하는함수 인수로받은문자열의길이만큼반복한다. 문자열의끝 (null) 을만나면반복문을빠져나간다. 한문자씩전송하도록한다. UART 를통해한문자를수신하는함수수신버퍼에수신한데이터가있을때까지대기수신한문자를반환한다. UART 통신초기화함수 UBBR 레지스터에 Baud rate 에따른계산값을설정한다. 계산값은헤더파일에정의되어있다. UCSZ 비트를 011 로설정해데이터길이를 8 비트로사용하도록한다. UPM 비트를 00 으로설정해패리티비트를사용하지않는다. USBS 비트를 0 으로설정해정지비트를 1 비트로사용한다. TXEN, RXEN 비트를 1 로설정하여 UART 송수신기능을모두사용하도록한다. Backspace 의 ASCII 제어코드 Carriage return 의 ASCII 제어코드 UBRR 레지스터값계산을위해사용할 AVR 의클럭정의 UART 통신에사용할 Baud rate 정의 Baud rate 를공식에의해 UBRRL 에적용할값계산 Baud rate 를공식에의해 UBRRLH 에적용할값계산
void uart_send_byte(unsigned char byte); void uart_send_string(unsigned char *str, unsigned char len); unsigned char uart_recv_byte(void); void UART_init(void); 폴링방식 - 어셈블리어소스코드.equ CPU_CLOCK = 8000000.equ BAUD_RATE = 57600.equ BAUD_RATE_L = (CPU_CLOCK / (16 * BAUD_RATE)).equ BAUD_RATE_H = ((CPU_CLOCK / (16 * BAUD_RATE))) >> 8.equ LED_CS = 0x4800.include "m128def.inc" 다른모듈과링크를위해 UART_Lib.c 파일에정의한함수들의원형을정의했다. UBRR 레지스터값계산을위해사용할 AVR 의클럭정의 UART 통신에사용할 Baud rate 정의 Baud rate 를공식에의해 UBRRL 에적용할값계산 Baud rate 를공식에의해 UBRRLH 에적용할값계산 외부 LED 의메모리매핑주소.cseg.org 0x0000 JMP RESET.org 0x0046 RESET: LDI R16, 0x10 OUT SPH,R16 LDI R16, 0xFF OUT SPL,R16 LDI R16, 0b10000000 OUT MCUCR,R16 CALL UART_Init LDS R16,UDR1 CLI CALL SET_MESSAGE CALL TX1_STRING LDI R16, '\r' LDI R16, '\n' MAIN_LOOP: CALL RX1_CHAR JMP MAIN_LOOP SET_MESSAGE: LDI ZL,byte3(MESSAGE << 1) OUT RAMPZ,ZL LDI ZH,high(MESSAGE << 1) LDI ZL,low(MESSAGE << 1) 프로그램의코드의시작 Reset 인터럽트 (Power on 등 ) 의인터럽트벡터주소메인프로그램의주소로이동한다. 인터럽트벡터테이블이후의주소부터사용하도록주소지정메인프로그램루틴프로그램의스택설정 외부메모리 IO 를위해 SRE 비트를 1 로설정. UART 설정초기화. UART_Lib.asm 에정의되어있다. 코드상불필요해보이지만, 수신버퍼에존재할수있는쓰레기값을제거하기위해현재수신버퍼를비우는것으로생각된다. SREG 레지스터의 I 비트를 0 으로설정해전체인터럽트를금지한다. 상대측에 UART 초기화가완료되었음을알리는문자열과개행문자를전송한다. 반복수행을위한레이블상대측이전송한문자를수신버퍼에서가져온다. 수신한문자를다시상대측에 Echo back 시킨다. 위동작을반복한다. 초기화완료메세지주소설정루틴 UART 초기화가완료되었음을알리는문자열의프로그램메모리상의주소를 Z 레지스터에설정한다. MESSAGE:.db "Initialization Complete!".db 0, 0.include "UART_LIB.asm" UART_LIB.asm UART_Init: LDI R16, BAUD_RATE_H LDI R17, BAUD_RATE_L STS UBRR1H,R16 STS UBRR1L,R17 처음실행시 UART 통신을통해전송할문자열 UART 통신관련함수를정의해놓은 asm 파일 UART 통신초기화루틴 (Polling 방식 ) 메인코드에서정의한 Baud rate 에따른계산값을가져온다. 가져온계산값을 UBBR 레지스터에설정한다. LDI R16,0b00000000 STS UCSR1A,R16 LDI R16,0b00011000 STS UCSR1B,R16 TXEN, RXEN 비트를 1 로설정하여 UART 송수신기능을모두사용하도록한다.
LDI R16,0b00000110 STS UCSR1C,R16 TX1_STRING: PUSH R16 TX1_STRING_SUB: ELPM R16, Z+ CPI R16, 0 BREQ TRANS_COMPLETE RJMP TX1_STRING_SUB TRANS_COMPLETE: UCSZ 비트를 011 로설정해데이터길이를 8 비트로사용하도록한다. UPM 비트를 00 으로설정해패리티비트를사용하지않는다. USBS 비트를 0 으로설정해정지비트를 1 비트로사용한다. UART 를통해문자열을전송하는함수. 인수로문자열의메모리주소를저장한 Z 레지스터를사용한다. 문자열의끝까지반복하기위한레이블현재주소의문자를 R16 에가져온다. 가져온문자가 null 문자인지비교하여 null 문자라면문자열의끝이기때문에루프를빠져나간다. 가져온문자를상대측에전송한다. 문자열의끝까지반복한다. POP R16 TX1_CHAR: PUSH R17 TX1_CHAR_SUB: LDS R17, UCSR1A SBRS R17, UDRE1 RJMP TX1_CHAR_SUB STS UDR1,R16 UART 를통해한문자를전송하는루틴. 인수로전송할문자값을저장한 R16 레지스터를사용한다. 송신버퍼가쓰기가능한상태가될때까지대기하기위한레이블 UDRE 비트가있는 UCSRnA 레지스터의값을 R17 에저장한다. UDRE 비트가 1 이라면송신버퍼가쓰기가능상태이기때문에루프를빠져나간다. UDRE 비트가 0 이라면레이블로돌아가서폴링방식으로체크한다. 인수로받은문자를송신버퍼에전달하여상대측에전송하도록한다. POP R17 RX1_CHAR: LDS R16, UCSR1A SBRS R16, RXC1 RJMP RX1_CHAR LDS R16, UDR1 STS LED_CS, R16 UART 를통해한문자를수신하는루틴. R16 에수신한문자를저장해서호출한루틴에반환한다. RXC 비트가있는 UCSRnA 레지스터의값을 R16 에저장한다. RXC 비트가 1 이라면문자가수신된상태이기때문에루프를빠져나간다. RXC 비트가 0 이라면루틴의처음으로돌아가서폴링방식으로체크한다. 수신버퍼의내용을 R16 에가져온다. 가져온데이터를외부 LED 에출력하여표시한다. 이예제는송수신가능상태를지속적으로확인하는폴링방식으로동작하며, 수신한문자를그대로송신측에되돌려보내는 Echo back 기능을하도록작성되어있다. USART1 을통해작동한다. 어셈블리어소스코드는추가적으로현재전송받은문자값을외부 LED 로출력한다. 초기화완료메시지가출력되고다음행에키보드로입력한문자들이 Echo back 되어터미널화면에출력되었다. 인터럽트방식 - C 소스코드 #include <avr/io.h> #include "KeyScanLib.h" #include "UART_Lib.h" #include "Delay_Lib.h" - 예제의결과화면 - #define LED_CS (*(volatile unsigned char *) 0x4800) void MCU_init() { MCUCR = 0x80 ; sei(); 외부 LED 의메모리매핑주소 MCU 초기화함수외부메모리 IO 를위해 SRE 비트를 1 로설정. SREG 레지스터의 I 비트를 1 로설정해글로벌인터럽트사용.
int main(void) { unsigned char Message[] = "Initialization Complete!"; unsigned char buff = 0; MCU_init(); UART_init_with_INT(); uart_send_string(message,25); uart_send_byte('\n'); uart_send_byte('\r'); while(1) { delay_ms(80); buff = KeyPadScan(); LED_CS = buff; if(buff!= 0) uart_send_byte(buff+'0'); return 0; UART_Lib.c ( 폴링방식코드에서추가된부분 ) ISR(USART1_RX_vect) { UDR1 = UDR1; 처음실행시 UART 통신을통해전송할문자열키패드로입력한버튼의번호를저장하기위한버퍼 MCU 초기화. 인터럽트용 UART 설정초기화. UART_Lib.c 에정의되어있다. 상대측에 UART 초기화가완료되었음을알리는문자열과개행문자를전송한다. 80ms 간격으로다음키패드상태를스캔하고, 그결과를버퍼에저장한다. 키패드값을외부 LED 에출력한다. 키패드에눌려진버튼이있다면해당버튼값숫자의 ASCII 코드를송신하기위해 0 의 ASCII 코드를더한값을송신한다. USART1 수신완료인터럽트서비스루틴수신버퍼의내용을다시송신버퍼에옮긴다. Echo back void UART_init_with_INT(void) { UBRR1L = (unsigned char) BAUD_RATE_L; UBRR1H = (unsigned char) BAUD_RATE_H; UCSR1C = (0 << UPM1) (0 << UPM0) (0 << USBS) (1 << UCSZ1) (1 << UCSZ0); UCSR1B = (1 << RXCIE) (1 << TXEN) (1 << RXEN) (0 << UCSZ2); UCSR1A = 0x00; 인터럽트방식 - 어셈블리어소스코드.equ CPU_CLOCK = 8000000.equ BAUD_RATE = 57600.equ BAUD_RATE_L = (CPU_CLOCK / (16 * BAUD_RATE)).equ BAUD_RATE_H = ((CPU_CLOCK / (16 * BAUD_RATE))) >> 8.equ LED_CS = 0x4800.include "m128def.inc" UART 통신초기화함수 UBBR 레지스터에 Baud rate 에따른계산값을설정한다. 계산값은헤더파일에정의되어있다. UCSZ 비트를 011 로설정해데이터길이를 8 비트로사용하도록한다. UPM 비트를 00 으로설정해패리티비트를사용하지않는다. USBS 비트를 0 으로설정해정지비트를 1 비트로사용한다. RXCIE 비트를 1 로설정하여수신완료인터럽트를허용하며, TXEN, RXEN 비트를 1 로설정하여 UART 송수신기능을모두사용하도록한다. UBRR 레지스터값계산을위해사용할 AVR 의클럭정의 UART 통신에사용할 Baud rate 정의 Baud rate 를공식에의해 UBRRL 에적용할값계산 Baud rate 를공식에의해 UBRRLH 에적용할값계산 외부 LED 의메모리매핑주소.cseg.org 0x0000 JMP RESET.org 0x003C JMP UART1_INT_ISR.org 0x0046 RESET: LDI R16, 0x10 OUT SPH,R16 LDI R16, 0xFF OUT SPL,R16 LDI R16, 0b10000000 OUT MCUCR,R16 CALL UART_Init_with_INT LDS R16,UDR1 SEI CALL SET_MESSAGE CALL TX1_STRING LDI R16, '\r' 프로그램의코드의시작 Reset 인터럽트 (Power on 등 ) 의인터럽트벡터주소메인프로그램의주소로이동한다. USART1 수신완료인터럽트의인터럽트벡터주소 USART1 수신완료인터럽트서비스루틴으로이동한다. 인터럽트벡터테이블이후의주소부터사용하도록주소지정메인프로그램루틴프로그램의스택설정 외부메모리 IO 를위해 SRE 비트를 1 로설정. UART 설정초기화. UART_Lib.asm 에정의되어있다. 코드상불필요해보이지만, 수신버퍼에존재할수있는쓰레기값을제거하기위해현재수신버퍼를비우는것으로생각된다. SREG 레지스터의 I 비트를 1 로설정해글로벌인터럽트를허용한다. 상대측에 UART 초기화가완료되었음을알리는문자열과개행문자를전송한다.
LDI R16, '\n' MAIN_LOOP: CALL D80MS CALL KEYPAD_READ CPI R16, 0x00 BREQ MAIN_LOOP LDI R17, '0' ADD R16, R17 RJMP MAIN_LOOP SET_MESSAGE: LDI ZL,byte3(MESSAGE << 1) OUT RAMPZ,ZL LDI ZH,high(MESSAGE << 1) LDI ZL,low(MESSAGE << 1) MESSAGE:.db "Initialization Complete!".db 0, 0 반복수행을위한레이블 80ms 의딜레이를준다. 키패드상태를스캔하고, 그결과를 R16 으로반환받는다. 키패드에눌려진버튼이없다면레이블로돌아가지속적으로키스캔을실시한다. 키패드에눌려진버튼이있다면해당버튼값숫자의 ASCII 코드를송신하기위해 0 을더한다. ASCII 코드를더해만들어진문자를송신한다. 초기화완료메세지주소설정루틴 UART 초기화가완료되었음을알리는문자열의프로그램메모리상의주소를 Z 레지스터에설정한다. 처음실행시 UART 통신을통해전송할문자열.include "UART_LIB.asm".include "KeyScan_LIB.asm".include "Delay.asm" UART_LIB.asm ( 폴링방식코드에서추가된부분 ) UART_Init_with_INT: LDI R16, BAUD_RATE_H LDI R17, BAUD_RATE_L STS UBRR1H,R16 STS UBRR1L,R17 LDI R16,0b00000000 STS UCSR1A,R16 UART 통신초기화루틴 (Interrupt 방식 ) 메인코드에서정의한 Baud rate 에따른계산값을가져온다. 가져온계산값을 UBBR 레지스터에설정한다. LDI R16,0b10011000 STS UCSR1B,R16 LDI R16,0b00000110 STS UCSR1C,R16 UART1_INT_ISR: PUSH R16 LDS R16, UDR1 STS UDR1,R16 STS LED_CS, R16 RXCIE 비트를 1 로설정하여수신완료인터럽트를허용하며, TXEN, RXEN 비트를 1 로설정하여 UART 송수신기능을모두사용하도록한다. RXCIE 비트를 1 로설정하여수신완료인터럽트를사용한다. UCSZ 비트를 011 로설정해데이터길이를 8 비트로사용하도록한다. UPM 비트를 00 으로설정해패리티비트를사용하지않는다. USBS 비트를 0 으로설정해정지비트를 1 비트로사용한다. USART1 수신완료인터럽트서비스루틴 수신버퍼의데이터를 R16 에가져온다. 가져온데이터를다시송신버퍼에옮긴다. Echo back 수신한값을외부 LED 에표시한다. POP R16 I 폴링방식과마찬가지로 Echo back 기능을하도록작성되어있다. 단, 수신방법이수신버퍼에데이터가있을때발생하는수신완료인터럽트를사용하도록변경되었다. 부가적으로, 키패드를통해입력된버튼의번호를상대측에전송하는기능이구현되었다. 참고문헌 - RS-232C 이론1: RS232 Data Interface ( http://www.arcelect.com/rs232.htm ) - RS-232C 이론2: MAX232 Datasheet