마이크로프로세서 응용및실습 ` 13-14 주차 : 직렬통신 (2) 한철수 전자공학과
2/35 직렬통신과병렬통신 직렬통신 한가닥의선으로송수신할데이터를차례대로전송하는방식 장점 : 통신선로가적기때문에경제적임 단점 : 전송속도가느림. 송수신약속이복잡해짐 병렬통신 여러가닥의선으로동시에여러개의데이터를전송하는방식 장점 : 전송속도가빠름 단점 : 직렬통신보다비쌈
3/35 ATmega128 의통신모드 직렬통신관련용어 USART: 동기및비동기통신 ATmega128 은 USART 를지원 UART: 비동기통신 동기모드 동기신호 XCK 가있음 비동기모드 동기신호가없음
외부시리얼통신장치와의비동기통신 4/35
직렬통신회로도 5/35
ATmega128 의 USART 개요 2 개의 USART 가있음 USART0, USART1 송신과수신을동시에수행하는전이중방식임 (Full- Duplex) 동기, 비동기모드를선택할수있음 6/35
7/35 USART 의데이터프레임 시작비트 (St) 새로운프레임이시작되면반드시 0 으로, 1 비트시간을가짐 데이터비트 5~9 비트시간동안 LSB 부터 MSB 까지차례로전송 패리티비트 (P) 1 의개수가홀수또는짝수가되도록패리트비트설정 패리티비트를없음 (None) 으로설정할수도있음 정지비트 프레임과프레임사이를구분하기위해정지비트구간을둠 정지비트는 1 또는 2 일수있음
8/35 USART 의내부구조 클록생성부 송신부 수신부
USART 관련레지스터 (1/9) 9/35
USART 관련레지스터 (2/9) 10/35
11/35 USART 관련레지스터 (3/9) 통신모드 데이터비트수
12/35 USART 관련레지스터 (4/9) 패리티모드 정지비트수
13/35 USART 관련레지스터 (5/9) 클록의샘플링위치설정 ( 동기모드에서만설정 ) 클록마스터 / 슬레이브설정 ( 동기모드에서만설정 )
14/35 USART 관련레지스터 (6/9) 통신에러 UCSRnA 레지스터의 FEn, DORn, UPEn 비트가 1 일때에러가발생된상태임 UDREn 패리티에러비트, UPEn 패리티설정과다른 1 의개수가수신되었을때발생 프레임에러비트, Fen 정지비트가 1 이수신되지않았을때발생 오버런에러비트, DORn 수신레지스터 (UDRn) 가다차있는상태에서새로운데이터가또수신될때발생
15/35 USART 관련레지스터 (7/9) 전송속도 (BAUD rate, 보오레이트 ) 설정 UDREn
16/35 USART 관련레지스터 (8/9) 많이사용하는보오레이트설정을위한 UBRR
17/35 USART 관련레지스터 (9/9) 송신 UCSRnA 레지스터의 UDREn 을검사하여 1 일때, UDRn 레지스터에값을기록하면그값을전송 UDREn 수신 UCSRnA 레지스터의 RXCn 비트를검사하여값이 1 이면, UDRn 레지스터에수신된데이터가있음 UDRn 레지스터를변수에저장
18/35 실습을위한설정값 설정해야할항목 설정값 통신모드 : 비동기통신모드 데이터비트수 : 8 비트 패리티모드 : 없음 정지비트수 : 1 정지비트 전송속도 : 38,400 bps UBRR 값은?
19/35 예제 1: 폴링을이용한문자송신 LCD 에윗줄왼편에 LOVE 또는 DEATH 를출력하고, 그문자열을 PC 로송신할것 ATmega128 모듈 LOVE 또는 DEATH 전송 PC 의하이퍼터미널
예제 1 char *string="love"; int main(void) unsigned char m; unsigned int ubrr_baud=25; LCD_init(); UCSR1B = (1<<RXEN1 1<<TXEN1); UBRR1H=(ubrr_baud>>8); UBRR1L=ubrr_baud; for(m=0;m<16;m++) if(string[m]=='\0') break; LCD_data_write(string[m]); while(!(ucsr1a&(1<<udre1))); UDR1=string[m]; while(1);
21/35 예제 2: 폴링을이용한문자수신 하이퍼터미널에서키보드로문자를입력하면, 그문자를수신하여 LCD 에출력할것 ATmega128 모듈 문자수신 PC 의하이퍼터미널
예제 2 int main(void) unsigned int ubrr_baud=25; LCD_init(); UCSR1B = (1<<RXEN1 1<<TXEN1); UBRR1H=(ubrr_baud>>8); UBRR1L=ubrr_baud; while(1) while(!(ucsr1a&(1<<rxc1))); LCD_data_write(UDR1);
23/35 응용문제 하이퍼터미널에문자가입력되면그값을수신하여 LCD 의커서위치를아래와같이바꿀것 w 가입력되면커서가위로한칸 s 가입력되면커서가아래로한칸 a 가입력되면커서가좌로한칸 d 가입력되면커서가우로한칸
24/35 예제 3: 폴링을이용한문자수신 ( 수정판 ) 하이퍼터미널에서키보드로문자를입력하면, 그문자를수신하여 LCD 에출력할것 ATmega128 모듈 문자수신 while(1) while(!(ucsr1a&(1<<rxc1))); LCD_data_write(UDR1); 수정 PC 의하이퍼터미널 while(1) if(ucsr1a&(1<<rxc1)) LCD_data_write(UDR1);
25/35 예제 4: 폴링을이용한문자송수신 하이퍼터미널에서키보드로문자를입력하면, 그문자를수신하여그값에따라 LCD 에문자열을출력하고다시전송 ATmega128 모듈 a 가입력되었으면 LCD (0,0) 위치에 apple 표시하고전송 b 가입력되었으면 LCD (0,0) 위치에 banana 표시하고전송 t 가입력되었으면 LCD (0,0) 위치에 tomato 표시하고전송 키보드로문자입력하고전송 PC 의하이퍼터미널
예제 4 char *string_apple="apple"; char *string_banana="banana"; char *string_tomato="tomato"; while(1) if(ucsr1a&(1<<rxc1)) data=udr1; if(data=='a') data=0; LCD_command(0x01); LCD_command(0x02); for(m=0;m<16;m++) if(string_apple[m]=='\0') break; LCD_data_write(string_apple[m]); while(!(ucsr1a&(1<<udre1))); UDR1=string_apple[m]; else if(data=='b') data=0; LCD_command(0x01); LCD_command(0x02); for(m=0;m<16;m++) if(string_banana[m]=='\0') break; LCD_data_write(string_banana[m]); while(!(ucsr1a&(1<<udre1))); UDR1=string_banana[m]; else if(data=='t') data=0; LCD_command(0x01); LCD_command(0x02); for(m=0;m<16;m++) if(string_tomato[m]=='\0') break; LCD_data_write(string_tomato[m]); while(!(ucsr1a&(1<<udre1))); UDR1=string_tomato[m];
27/35 인터럽트를이용한통신의필요성 폴링 (polling) 방식 주기적으로데이터가수신되었는지레지스터를체크 While 루프내의처리문장이많아질경우 데이터를송수신하는시간간격이길어지고, 데이터를전송받지못하는경우도발생 인터럽트방식 While 루프와관계없이하드웨어적으로빠르게송수신할수있음
28/35 인터럽트를이용한문자송신 (1/3) LCD 에윗줄왼편에 LOVE 또는 DEATH 를출력하고, 그문자열을 PC 로송신하기 char *string="love"; #include <avr/interrupt.h> #define LENGTH_TX_BUFFER 8 unsigned char tx1_buffer[length_tx_buffer]; unsigned char tx1_head=0, tx1_tail=0;
29/35 인터럽트를이용한문자송신 (2/3) void USART_send(char data) while((tx1_head+1==tx1_tail) ((tx1_head==length_tx_buffer-1)&&(tx1_tail==0))); tx1_buffer[tx1_head]=data; tx1_head=(tx1_head==length_tx_buffer-1)?0:tx1_head+1; UCSR1B=UCSR1B 1<<UDRIE1; ISR(USART1_UDRE_vect) UDR1=tx1_buffer[tx1_tail]; tx1_tail=(tx1_tail==length_tx_buffer-1)?0:tx1_tail+1; if(tx1_tail==tx1_head) UCSR1B=UCSR1B & ~(1<<UDRIE1);
인터럽트를이용한문자송신 (3/3) int main(void) unsigned char m; unsigned int ubrr_baud=25; LCD_init(); UCSR1B = (1<<RXEN1 1<<TXEN1); UBRR1H=(ubrr_baud>>8); UBRR1L=ubrr_baud; sei(); for(m=0;m<16;m++) if(string[m]=='\0') break; LCD_data_write(string[m]); USART_send(string[m]); while(1); 30/35
31/35 인터럽트를이용한문자수신 (1/3) 하이퍼터미널에서키보드로문자를입력하면, 그문자를수신하여 LCD 에출력할것 #include <avr/interrupt.h> #define LENGTH_RX_BUFFER 8 unsigned char rx1_buffer[length_rx_buffer]; unsigned char rx1_head=0, rx1_tail=0; unsigned char trash;
인터럽트를이용한문자수신 (2/3) int USART1_receive(void) unsigned char rx_data; if(rx1_head==rx1_tail) return 0; else rx_data=rx1_buffer[rx1_tail]; rx1_tail=(rx1_tail==length_rx_buffer-1)?0:rx1_tail+1; return rx_data; ISR(USART1_RX_vect) if((rx1_head+1==rx1_tail) ((rx1_head==length_rx_buffer-1)&&(rx1_tail==0))) trash=udr1; else rx1_buffer[rx1_head]=udr1; rx1_head=(rx1_head==length_rx_buffer-1)?0:rx1_head+1; 32/35
33/35 인터럽트를이용한문자수신 (3/3) int main(void) unsigned char data=0; unsigned int ubrr_baud=25; LCD_init(); UCSR1B = (1<<RXEN1 1<<TXEN1); UBRR1H=(ubrr_baud>>8); UBRR1L=ubrr_baud; UCSR1B=UCSR1B 1<<RXCIE1; sei(); while(1) data=usart1_receive(); if(data) LCD_data_write(data);
34/35 응용문제 2: 인터럽트를이용한문자송수신 하이퍼터미널에서키보드로문자를입력하면, 그문자를수신하여그값에따라 LCD 에문자열을출력하고다시전송 ATmega128 모듈 a 가입력되었으면 LCD (0,0) 위치에 apple 표시하고전송 b 가입력되었으면 LCD (0,0) 위치에 banana 표시하고전송 t 가입력되었으면 LCD (0,0) 위치에 tomato 표시하고전송 키보드로문자입력하고전송 PC 의하이퍼터미널
질문? 전자공학과