안녕하세요 L입니다.
오늘은 DK-128을 PC와 연결하는 직렬통신에 대해 알아보겠습니다 !!
본문내용 PDF파일은 첨부파일에 있음돠 !!
★ DK-128 직렬통신 실습
ㆍ Serial port 사용
ㆍPD2, PD3 를 활성화 시켜야한다. (위치는 아래 그림 참조)
ㆍpc → 수신버퍼 → Atmega128 →송신버퍼 → PC
ㆍ수신버퍼 → RXD1 (27) = 수신단자
ㆍ송신버퍼 → TXD1(28) = 송신단자
< Atmega128 USART >
ㆍUSART0 과 USART1 이 있는데 USART1만 직렬통신으로 사용가능
< UDR 레지스터 >
ㆍ8bit 레지스터 이다.
ㆍUDR1(0x9C) = 8bit 크기이고, 송신 Buffer(write)와 수신 Buffer(read)로 나누어져있다.
ㆍUDR1 : DATA가 담기는 레지스터 ( 수신버퍼, 송신버퍼 )
< UCSRnA레지스터 >
ㆍUCSR1A : 수신버퍼에 외부data 들어왔는지 확인.
송신버퍼에 비어있는지 확인.
ㆍUDREn (bit 5번) : 송신버퍼가 비어있으면 1이고 data가 들어있으면 0
ㆍRXcn (bit 7번) : 1이면 수신할 data가있다 0이면 수신할 data가 없다.
< UCSRnB레지스터 >
ㆍUCSR1B : RXD1 을 수신단자로 설정, TXD1을 송신단자로 설정
ㆍRXENn ( bit 4 번 ) : 1이들어가면 수신단자 설정
ㆍTXENn ( bit 3 번 ) : 1 이 들어가면 직렬통신요 송신단자로 설정
ㆍ양방향 통신이 가능하다.
ㆍ1방향 통신일경우 : TXEn 에 1을 넣어준다.
< UCSRnC레지스터 >
ㆍUCSR1C : PC와 Atmega128 간의 통신설정
ㆍ아래 내용들이 이미 초기화 되어있음으로 따로 설정 할 필요가 없다.
ㆍUMSEL : 비동기모드 0값
ㆍ0, 0이 들어갈경우 사용안함.
ㆍstop bit 에 0이 들어가면 1-bit
ㆍ문자size 설정 1일경우 8-bit문자 size이다.
< UBRRn H/L 레지스터 >
ㆍUBRR1H/L : 통신속도를 설정 ( HIGH/LOW 2가지 )
ㆍH/L 는 각각 8bit 레지스터이다. High 비트는 4비트만 사용한다.
ㆍHigh 값에 Data를 넣을때는 쉬프트 해서 넣어준다 ex) a>>8
ㆍ통신속도 설정 fosc = 16mhz, BAUD = 4800세팅 으로 위 테이블 공식으로 세팅.
< USART Block Diageam >
Ex) 단방향 직렬통신
< 헤더 파일 >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #define UBRR1L *((volatile unsigned char *)0x99) #define UBRR1H *((volatile unsigned char *)0x98) #define UCSR1A *((volatile unsigned char *)0x9B) #define UCSR1B *((volatile unsigned char *)0x9A) #define UCSR1C *((volatile unsigned char *)0x9D) #define UDR1 *((volatile unsigned char *)0x9C) #define UDRE 5 #define UPM1 5 #define UPM0 4 #define USBS 3 #define UCSZ1 2 #define UCSZ0 1 #define TXEN 3 #define UCSZ2 2 #define RXEN 4 #define TOIE0 0 #define CPU_CLOCK 16000000 // MCU의속도 #define TICKS_PER_SEC 1000 #define PRESCALER 64 /* 직렬통신 */ #define BAUD_RATE 4800 // 통신시이용할속도 #define BAUD_RATE_L (CPU_CLOCK / (16l * BAUD_RATE)) - 1 #define BAUD_RATE_H ((CPU_CLOCK / (16l * BAUD_RATE)) -1) >> 8 // 통신속도의결과값을입력하기위해상하위비트로구분 // 16l 은16 + L 이며, 연산시값이너무커져overflow가발생하므로 // 32비트연산을위해16에Long을의미하는l을붙인다. //======================================================== /* 1byte 전송함수 */ void uart_send_byte(unsigned char byte); void uart_send_byte(unsigned char byte) { while (!(UCSR1A & (1 << UDRE))); // 전송버퍼가빌때까지기다린다 UDR1 = byte; // 문자1개를전송한다. } //======================================================== /* delay */ volatile unsigned int g_elapsed_time; void sleep(unsigned int elapsed_time) { g_elapsed_time = 0; for(;g_elapsed_time<elapsed_time;); } void __vector_16 (void) __attribute__ ((signal, used, externally_visible)); void __vector_16 (void) { TCNT0 = 6; ++g_elapsed_time; } //======================================================== /* Timer/counter Control regi초기화 */ void init_TC0(void) { TCCR0 = 0x04; TCNT0 = 6; TIMSK = TIMSK | (1<<TOIE0); /*전체인터럽트활성화*/ SREG = SREG | (1<<7); /*전체인터럽트활성화*/ } | cs |
< 소스 코드 >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <L.h> int main(void) { unsigned char buf[] = "Hello DK128!\r\n"; // 전송할문자열 unsigned int i; // 반복제어변수 init_TC0(); UBRR1L = (unsigned char)BAUD_RATE_L; // baud rate 설정 UBRR1H = (unsigned char)BAUD_RATE_H; // no parity, 1 stop bit, 8bit 설정 UCSR1C = ( 0 << UPM1) | (0 << UPM0) | (0 << USBS) | (1 << UCSZ1) | (1 << UCSZ0); // rx/tx interrupt 설정, 8bit 설정 UCSR1B = (1 << TXEN) | (1 << RXEN) | ( 0 << UCSZ2); while(1) { for(i = 0 ; i < sizeof(buf) ; i++) // 문자단위로전체문자열전송 { uart_send_byte(buf[i]); // 문자1개를직렬포트로전송 } sleep(1000); // 1초대기 } return 1; } | cs |
결과
Ex) 다음 과 같은 문자열전송하는 함수를 구현하여 앞의
실습 예제에 적용하여 실행시켜보시오.
문자열전송함수선언
void uart_send_string(unsigned char *str, unsigned char len);
str: 전송하려는문자열의시작주소
len: 전송하려는문자열의길이
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <L.h> void uart_send_string(unsigned char *str, unsigned char len); int main(void) { unsigned char ch; unsigned char buf[] = "Hello DK128!\r\n"; // 전송할문자열 init_TC0(); UBRR1L = (unsigned char)BAUD_RATE_L; // baud rate 설정 UBRR1H = (unsigned char)BAUD_RATE_H; // no parity, 1 stop bit, 8bit 설정 UCSR1C = ( 0 << UPM1) | (0 << UPM0) | (0 << USBS) | (1 << UCSZ1) | (1 << UCSZ0); // rx/tx interrupt 설정, 8bit 설정 UCSR1B = (1 << TXEN) | (1 << RXEN) | ( 0 << UCSZ2); uart_send_string(buf, sizeof(buf)); // 함수호출 return 1; } // 문자열전송함수선언 void uart_send_string(unsigned char *str, unsigned char len) { while(1) { for(unsigned int i = 0 ; i < len ; i++) // 문자단위로전체문자열전송 { uart_send_byte(*(str+i)); // 문자1개를직렬포트로전송 } sleep(1000); // 1초대기 } } | cs |
결과는 위와 동일
Ex) 양방향 직렬 통신
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <L.h> #define RXC 7 // 추가 unsigned char USART_Receive( void ); void uart_send_string(unsigned char *str, unsigned char len); int main(void) { unsigned char ch; init_TC0(); UBR_UCSR(); init_LED(); while(1) { ch = USART_Receive(); PORTF = ch^0xFF; uart_send_byte(ch); sleep(1000); } return 1; } unsigned char USART_Receive( void ) { while(!(UCSR1A & (1<<RXC))); return (UDR1); } | cs |
결과 : 하이퍼터미날에 입력된 값이
아스키코드 10진수로 LED에 출력된다.
(동영상 참고)
궁금하신 점은 댓글로 남겨 주세요 !!
오늘도 좋은 하루 되세열
USART (0) | 2016.09.30 |
---|---|
아트메가128 ( 직렬통신 / 실습문제 / 예제 ) [20120607] (0) | 2016.09.30 |
아트메가128 ( PC기반 직렬통신 기초 ) [20120531] (0) | 2016.09.30 |
아트메가128 (EEPROM제어) [20120530] (0) | 2016.09.30 |
아트메가128 ( 타이머카운터 / rand활용 / 별로 엑스그리기 ) [20120524] (0) | 2016.09.29 |