앞에 이어서 그러면 사용자 정의 문자 출력을 해 보도록 합시다.


사용자 정의 문자를 지정하는데 사용하는 메모리는 CG RAM이며, 이 CG RAM에는 5x8 도트를 사용하는 경우에는 최대 8문자, 5x10 도트를 사용하는 경우에는 최대 4문자를 쓸수 있습니다. 사용자 정의 문자는 위 그림의 00H~0fH의 영역에 할당되어 있는데 1문자가 2개의 코드 영역을 차지하므로 실제 코드값은 00H~07H(또는08H~0fH)로 사용 됩니다.

1. 사용자 정의 문자 코드는 00H~0FH 영역에 해당되며, 이중에서 아래의 3비트만이 유효하고, b3은 don't care이므로 실제 코드값은 00H~07H(또는 08H~0FH)로 지정해야 합니다.

2.  위 문자 정의에서 보시듯이 제일 아래단은 커서를 위해서 비워 두는게 좋습니다.

3. CG RAM data에 사용되는데 b5~b7은 사용되지 않는 데이터 영역이므로 b0~b4까지 데이터를 채워 주시면 됩니다.

그럼 아래 함수를 보면서 이해를 해 보도록 합시다. ^^


이 소스를 실행 시킨 실행 화면 입니다.

위 사진에서 보시듯이(해상도가 낮아서 죄송합니다.ㅎ) 8개의 구역을 이용하여 [이현]이라는 한자를 입력한 것입니다.

이렇게 Text LCD에 사용자 정의 입력을 할 수도 있지만 8글자라는 한계가 있어서 한글을 표현하려면 Graphic LCD를 이용하는 편이 좋습니다. 

결론은 Text LCD는 영어를 문자로 표현할 때 가장 좋은 것이라는 것을 느꼈습니다.

역시 영어가 중요한 것 같습니다. ㅋㅋ

서비스로 전체 소스를 올려봅니다.



  1. 곽동호 2010.02.11 13:34

    안녕하세요.

    제가 지금 TXET LCD를 구동해보려고 하는데

    소스 좀 얻을 수 있을까요...??

    메인과 헤더 모두 받고 싶습니다.

    kb2clsrn@nate.com

    바쁘시지 않다면 좀 보내주세요.

    감사합니다.

텍스트 LCD를 사용하기 위해서는 텍스트 LCD를 우선적으로 제어를 해야 합니다.
LCD를 제어하는 방법에 대해서는 각 제조사의 Data Sheet를 보면 자세하게 나와 있고, 또한 시중에서의 책을 찾아봐도 무방하지만, 각 제품의 특징이 있기 마련이니 가능하면 Data Sheet를 참조해서 제어를 시도하시길 바랍니다.

우선 제가 사용하는 LCD(HY-1602W-204)의 Data Sheet의 제어 및 출력 명령을 찾아보겠습니다.

위 데이터 시트를 통해서 LCD의 자세한 스펙을 알 수 있으므로 상당히 유용해다고 할 수 있습니다.

 LCD의 초기화 과정을 살펴 보겠습니다.

1. 전원을 투입합니다.
2. 초기화를 시작하기 전에 30 ms 이상을 기다립니다.
3. Function Set 명령을 보냅니다.
4. Display ON/OFF control 명령을 보냅니다.
5. Entry mode set 명령을 보냅니다.
6. DD RAM 어드레스를 보냅니다.
7. 표시할 문자 데이터를 보냅니다.
8. 필요할 경우 6~7 과정을 반복합니다.

텍스트형 LCD 모듈의 DD RAM은 표시할 문자들의 ASCII 코드 데이터가 저장되는 내부 메모리이며 모두 80개의 번지가 있는데, 화면의 각 행과 열의 문자 위치에는 고유한 어드레스 값이 부여되어 있습니다. 그런데, 첫번째 행은 DD RAM 어드레스가 00H부터 시작되고 2번째 행은 항생 40H부터 시작되므로, LCD 모듈이 2행 이상으로 구성되는 경우에 각 행과 행 사이에는 어드레스가 연속하여 있지 않게 되어 주의하여야 한다. 또한, 물리적으로 4행으로 되어 있는 LCD 모듈은 어드레스가 1행과 3행이 이어져 있고 2행과 4행이 이어져 있어서 논리적으로 2행으로 동작한다.





[본 프로그램의 동작환경]
 * 컴파일러 arm-elf-gcc
 * 사용된 arm : AT91SAM7S256
 * 사용된 보드 : AT91SAM7S64 BOARD



ARM은 다양한 기능을 제공한다. 그중에 USART를 이용하여 시리얼 통신을 하는 프로그램을 짜게 되었다. 
 이 프로그램은 아주 단순한 기능을 제공 한다. 
 ARM의 플래쉬 메모리에 프로그램을 싣고 ARM을 작동시킨 후 터미널에 프로그램에 설정한 대로 하이퍼 터미널에 통신 상태를 적용시킨 후 키보드로 입력을 하면 입력한 내용이 터미널 창에 뜨는 기능이다.

 프로그램 작성방법은 아래 PDF의 설명을 따라서 프로그램을 작성한다.
 다만 위 설명중 루프백 설정을 하는 부분이 있다. 그 부분을 노멀 모드로 바꿔주어야 자신이 입력한 키 입력이 터미널에 출력되는 것이 보일 것이다.

그럼 소스파일을 한번 보자.
이 소스는 헤더파일을 분리하였기 때문에 헤더파일도 같이 보아야 한다.
이 프록그램은 makefile을 사용하여 프로그램을 컴파일을 할 수 있도록 한다.
그럼 makefile을 보자
Universal Synchronous and Asynchronous serial Receiver and Transmitter = USART
이 USART는 산업표준인[=UART] 비동기방식만을 제공하는게 아니라 동기와 비동기를 모두 제공해주는 직렬 통신 포트이다.

[제공기능]
- 전이중 통신이 가능
- 동기와 비동기를 지원
- Master와 Slave Clocked Synchronous Operation4
- High Resolution Baud Rate Generator
등등 다양한 기능을 제공해 준다. 

[동기와 비동기의 작동방식]
1) 동기식
- master : 전송속도를 결정할때 내부 클럭을 사용
- slave : XCKn 단자로 입력되는 클럭 신호에 의해 동작
2) 비동기식
- 항상 내부 클럭에 의하여 Baud Rate가 결정됨

[USART의 레지스터]
1) USARTn I/O Data Register - UDRn
 - UDRn은 Data 송수신을 위한 레지스터이다.
 - 이 레지스터는 2byte로 되어 있다.(ATMEL128에서의 2byte는 INT형이다.)
   2Byte의 공간중 1Byte는 Read를 위한 공간이고, 1Byte는 Write를 위한 공간이다.

2) USART Control and Status Register A - UCSRnA
- 포트의 송수신 동작을 제어, 송수신 상태를 저장하는 기능
 
3) USART Control and Status Register B - USCRnB
- 포트의 송수신 동작을 제어
- 전송데이터를 9비트로 설정한 경우에 전송 데이터의 9번째 비트값을 저장하는 기능 수행
 
4) USART Control and Status Register C - USCRnC
- 포트의 송수신 동작을 제어
 
5) USART Baud Rate Registers - UBRRnH and UBRRnL
- 16비트중 12비트만 유효
- 포트의 송수신 속도를 설정하는 기능을 수행
- 레지스터 write 하는 경우 상위 바이트인 UBRRnH부터 먼저 write 하고 그다음 UBRRnL write 함
  
[USART 인터럽트]
- USART의 인터럽트는 3가지가 있다.
1) TX Complete (송신완료)
2) TX Data Register Empty (송신 데이터 레지스터 준비완료)
3) RX Complete (수신완료)
 
[USART를 3부분으로 나누기]
1) 클럭 발생부 - Baud Rate Generator, 동기모드에서 클럭과 동기를 취하는 회로를 구성
2) 송신부 - 송신 버퍼, 송신 시프트 레지스터, 패리티 발생기(오류체크)
3) 수신부 - 수신 버퍼, 수신 시프트 레지스터, 패리티 검사기

[하드웨어]
= HIN232C
이 칩은 120kbps의 최대 속도를 낼 수 있고, 0 ~ 70도의 온도를 견딜 수 있다.
  1. 우하앤랴ㅣ다 2009.05.06 09:38

    님들 근데 이거 다 긁어서 올리고 다 읽어는 보신거임?

1.     프로그램의 개요

- 이프로그램은 IO Port를 제어를 위해 사용하는 DDRx PORTx DDRF PORTF를이용해

다이오드를 순차적으로 점등 시키는 프로그램을 작성한다.

2.     프로그램의 내용

- 먼저프로그램의 avr io를 저어하기 위해 avr/io.h를 선언한다.

그리고 DDRFoutput을 하게 설정을 한다.

PORTF0xFF를 넣어서 점멸을 시켜 놓은 뒤에 1 0부터 7까지의 위치로 shift연산시켜^(xor)연산을 시킨다.

      -  이 작업을 반대로 시킨다.

- DDRx Port xData Direction Register로서 입출력의 방향을 설정하는 레지스터이고, PORTxPort x Data Register 데이터 출력에 해당하는 레지스터이고, PINx Port x Input Pins Address로서 포트핀의 입력에 해당하는 PINx 레지스터이다. 이것에 대한정의는 <avr/io.h>를 통해서 찾아 볼수 있다.

이 헤더 파일은avr폴더 밑에 io.h라는 파일을 찾을 있다. 하지만 이 헤더파일은 각 버전에 대한 io헤더파일의 연결자 헤더파일이었다. 이중 MCU의 해당 버전을 찾게 도와주는 파일이있는데 makefile이 바로 그것이다.  그 중 지금 공부하는 프로세서가atmega128이니 iom128.h가 헤더 파일로 되어있을있다. 안에 DDRx DDRA에 대해 설정 되어 있는 내용을 찾아보니

/* Data Register, Port A */

#define PORTA    _SFR_IO8(0x1B)

/* Data Direction Register, Port A */

#define DDRA     _SFR_IO8(0x1A)

/* Input Pins, Port A */

#define PINA     _SFR_IO8(0x19) 로 정의 되어 있었다.

DDRA를 우선적으로 살펴보면 _SFR_IO8(0x1A)define한다는 의미인 것이다. 하지만 이 부분은 매크로함수 _SFR_IO8과 이 매크로의 인자인 0x1A로 되어있다는 사실을 알 수 있을 것이다. PORTx PINx 또한 마찬가지로 구성 되어있음을 알 수 있을 것이다.

0x1A를 데이터 시트에서 찾아보면 교재마다 다르겠지만본인의 교재 중 363p - 데이터 시트의 Register Summary의 내용 중 $1A(아트멜에서는 16진수의 표시를 $로 한다.)의이름은 DDRA로 되어 있음을 확인 할 수 있었다. 매크로함수를 통해 DDRA 포트 레지스터로 접근한는 내용임을 짐작하게 한다.

그럼_SFR_IO8()이란 함수를 찾아보아야 자세한 내용을 찾아볼 수 있을 것 같다. 이 함수에대해서 알아보기 위해 iom128.h에서 include하고있는 sfr_def.h이란 헤더파일을 찾아봐야한다. 이 헤더파일은 macros for accessing AVR special function registers에 대한 헤더파일이라는 것을 알 수 있었다. 그럼 _SFR_IO8()이란 무엇인가를 찾아봐야 할 차례인 것 같다.

찾으면 2가지의코드가 나올 것인다.

#define _SFR_IO8(io_addr) ((io_addr) +__SFR_OFFSET) : 이코드는 우리가 찾는 코드가 아니다.

#define_SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET) : 이코드가 찾는 내용이다.

음 점입가경이다._SFR_IO8(io의 주소)(_MMIO_BYTE매크로에 io의 주소를 넣은 값)(__SFR_OFFSET)을 더한 값이 된다. 그중 모르는 내용이 2가지나 나왔는데 _MMIO_BYTE __SFR_OFFSET에 대한 정보가 필요해 졌다. 하지만 걱정 하지 말자. 이번에 찾을 내용은 sfr_def.h안에 다 있는 내용이다.

_MMIO_BYTE를 찾게 되면

#define _MMIO_BYTE(mem_addr) (*(volatileuint8_t *)(mem_addr))를 찾게 된다.

이 매크로를 읽어보면 voliatile타입의 uint8_t인데 이 것을 해석해보면 unsigned int 8bit type이라는 것이다. 결론적으로 unsigned char라는 의미가 될 것이다. (이것도 헤더파일을따라가다 보면 나오는데 별 의미없는 소모적인 일이 될 것 같으므로 생략하겠다.

이번에는 __SFR_OFFSET을찾아보자. 이 부분은 굳이 보지 않아도 되는 내용이지만 읽어보면 도움은 될

이라고 생각된다.이 매크로는 Atmel의지원해주는 기능에 관련된 내용인데 이 Atmega 프로세서는nomal modecompatibility mode를 지원해 준다. 즉 일반모드와 확장모드를 지원해 준다는 의미이고, 기본적으로 일반모드를사용하게 된다.

#ifndef __SFR_OFFSET

#  if__AVR_ARCH__ >= 100

#   define __SFR_OFFSET 0x00  // 이부분이 확장모드이다

# else

#   define __SFR_OFFSET 0x20  // 이부분이 전용모드이다.

# endif

#endif

결론적으로 __SFR_OFFSET은 일반 모드를 쓰면0x20인 것이다. 그럼 모든 의미를 다 찾아 보았다.

그 중 volatile키워드에 대해 잠시 알아보면 volatile은 휘발성이란 의미를 가지고 있는데 이 키워드를 사용해서 정의한 변수는 그것을 사용하는 문장 외에다른 것에 의해서(운영체제나 하드웨어) 변경될 수 있으므로키워드를 사용해서 정의한 변수는 눈에 보이는 문장만을 상대로 함부로 최적화 시키지 말아하 한다는 것을 의미한다., 함부로 컴파일러가 코드 최적화 시키지 않게 하는 키워드인 것이다.그리고 unit8_t란 변수 타입은unsigned char와 같은 의미를 지닌다.

지금껏 찾은 내용을 소스로 정리를 해 보았다.

//PORTA= 0xff;

//_SFT_IO(0x1B) = 0xff;

//_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xff;

//(*(volatile uint8_t *))((0x1B) + __SFR_OFFSET) = 0xff;

//(*(volatileuint8_t *)(0x3B)) = 0xff;

(*(volatile unsigned char *)(0x3B)) = 0xff;

이 소스코드가 각 줄이 동일한 의미를 가진다는 것을 이때까지의 내용을 통해서 이젠 알아 볼 수 있을 것이라고 생각한다.

자 이제 모든 함수헤더를 찾아본 것 같다. 이제까지의 내용을 정리해 보면 DDRx PORTx, PINx는 매크로함수이고, 데이터 타입은 (*(voliatile unsigned char *)이며, 인자를받아서 그 인자를 해당 레지스터에 채워주는 명령인 것이다

+ Recent posts