태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

My Work/AVR2008/08/23 11:59

Code Vison AVR C

ATmega8535

 

ATmega8535 제어 실습

 

 

I / O 포트 제어하기

사용자 삽입 이미지
 

FND 제어

 

  FND에는 Vcc를 이용하는 애노드 (anode)형과 Gnd를 이용 하는 cathode형이 있다.

LED가 여러개 모여 있다 생각 하고 LED선택에 따라 문자와 숫자를 만들어 낼 수 있다.

최대한 많은 영문자를 만들기 위해 대문자와 소문자를 혼합한다.

(표현 가능한 문자 : A, b, C, d, E, F, H, I, J, L, o, P, r, S, t, u, y)

 

프로그램

           - 1개의 FND 0 -> 1 -> 2..... ->1 까지 1초마다 자동으로 카운트 하기

 

#include <mega8535.h>

#include <delay.h>

 

void main(void)

{

// 변수 선언

unsigned char i;

unsigned char FONT[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xD8, 0x80, 0x98};

 

//PORTA를 출력으로 설정하고 초기값은 모두 0

PORTA = 0x00;

DDRA = 0xFF;

 

//무한 루프

while (1)

           {

           // 0 - 8 까지 up-count 출력

           for (i=0 ; i<9; i++) {

           //PORTA i 0 - 9를 출력

           PORTA = FONT[i];

           delay_ms(1000);

           } //for i

           // 9-1까지 down-count 출력

           for (i=9; i>0; i--){

           PORTA = FONT[i];

           delay_ms(1000);

           } //for i

     } //while

} //main

 


 

LCD 컨트롤러 제어


문자 LCD 제어

 

LCD 모듈의 이해

  일반적으로 LCD HD44780 컨트롤러를 사용한다.

 

사용자 삽입 이미지

           <특징>

1.      5x8, 5x10 도트 문자의 표현이 가능하다.

2.      2.7 ~5.5V 전원에서 동작한다.

3.      마이크로프로세서와 4비트와 8비트 인터페이스가 된다.

4.      80x8 비트 디스플레이 RAM (최대 80문자)

5.      240 문자 폰트의 9920 비트 문자 발생기 ROM CG ROM

6.      64x8 비트 문자 발생기 RAM - CG RAM

- 8 문자 폰트 (5x8 도트)

- 4 문자 폰트 (5x10 도트)

7.      저 소비 저 전력

 

 

사용자 삽입 이미지


제어 할 때 주로 신경 쓰는 부분은 RS, RW, DB 이다.


RS (Register Select)
: LCD의 제어 명령과 데이터 입력 제어 신호를 설정한다.

R/W (Read/ Write) : 신호가 Low(0)이면 쓰기 동작, 신호가 High(1)이면 읽기 동작

DB0~DB7 : 마이크로프로세서와 LCD간의 데이터를 주고 받는 단자

           8비트와 4비트 제어 방법이 있으며 4비트 제어시 DB4~DB7 4개의 핀을 사용 한다.


LCD
제어의 이해

 

  HD44780 8비트 레지스터인 인스트렉션(명령) 레지스터 IR 와 데이터 레지스터 DR 을 가지고 있다.

  그리고 데이터가 저장되어 있거나 저장할 수 있는 DD RAM, CG ROM, CG RAM과 어드레스 카운터, 비지 플래그 등이 있다.

 

 

 

1. DD RAM (Display Data Ram)

  DD RAM LCD에 실제 출력되는 문자가 저장 되는 메모리 이다. 여기에 데이터를 기록하면 문자가 LCD에 출력 된다.

 

l  최대 0x80 x 8bit의 용량을 가지므로 모두 128개의 문자를 저장할 공간이지만 사용되지 않는 부분이 있어 80개의 문자를 저장한다.

l  첫 번째 LINE을 표시하는 DD RAM의 어드레스는 0x00 ~ 0x27

l  두 번째 LINE을 표시하는 DD RAM의 어드레스는 0x40 ~ 0x67

기본 표시 어드레스를 좌우로 1비트씩 이동 시키면서 보여 준다.

 

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

0F

10

11

12

13

...

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4F

50

51

52

53

...

초기 상태 (붉은 바탕이 표시 되는 부분이다.)

 

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

0F

10

11

12

13

...

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4F

50

51

52

53

...

오른쪽으로 2칸 이동 (2비트 쉬프트)

 

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

0F

10

11

12

13

...

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4F

50

51

52

53

...

오른쪽으로 4칸이동 (4비트 쉬프트)

 

 

           * 40 2행 짜리 표에 데이터를 기록 한다고 생각 하자!

 

 

 

 

 

2. CG ROM (Character Generator ROM)

 

  다음 표와 같이 8비트 문자 코드 192종류의 5x7 도트 매트릭스 문자 패턴을 저장하고 있다.

 

사용자 삽입 이미지

위의 표에서 "0"은 상위 3 하위 0 이 되어 0x30이 된다. ( "Z" = 0x5A, "9" = 0x39 )

 

이 값을 DD RAM에 기록하면 CG ROM에 저장된 문자가 출력 된다

 

 

 

3. CG RAM ( Character Generator RAM )

 

  CG RAM은 사용자가 프로그램에서 새로운 글자의 패턴을 만들 경우에 사용 하는 RAM이다. 5x7문자는 8 5x10 문자는 4개까지 만들 수 있다.

  CG RAM 어드레스와 CG RAM 문자패턴은 문자코드 DD RAM어드레스로 써넣어야 사용 할 수 있다.

  CG RAM에 있는 만들어진 문자 패턴을 LCD로 출력하는 방법은 다음과 같다.

           - 사용자 문자를 만들어 CG RAM에 저장한 다음

           - DD RAM에 만들어둔 문자가 저장된 CG RAM의 코드를 Write하면 출력됨

 

 

 

4. LCD 모듈의 RS,R/W 선택

 

RS

R/W

동 작

0

0

IR 선택, IR 쓰기, 내부 동작 표시 클리어

0

1

비지 플래그(BF)와 어드레스 카운터 읽기

1

0

DR 선택, DR 쓰기
내부동작: DR → DD RAM, CG RAM

1

1

DR 선택, DR 읽기
내부동작: DD RAM, CG RAM → DR

RS, RW로 어떤 동작을 수행할 것인지 정한다.

 

5. 명령 레지스터 ( IR : Instruction Register )

 

  DD RAM CG RAM에 대한 어드레스 정보와 클리어, 커서의 이동에 대한 명령 명령코드를 가지고 있다. IR은 쓰기만 되고 읽기는 되지 않는다.

 

 

LCD 모듈의 명령어의 종류

 

명령

코드

실행시간

RS

R/W

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

표시 클리어

0

0

0

0

0

0

0

0

0

1

1.64ms

커서

0

0

0

0

0

0

0

0

1

x

1.64ms

엔트리 모드 세트

0

0

0

0

0

0

0

1

I/D

S

40us

표시 온/오프 제어

0

0

0

0

0

0

1

D

C

B

40us

커서/표시 쉬프트

0

0

0

0

0

1

S/C

R/L

x

x

40us

펑션 세트

0

0

0

0

1

DL

N

F

x

x

40us

CG RAM 번지 세트

0

0

0

1

CG RAM 번지

40us

DD RAM 번지 세트

0

0

1

DD RAM 번지

40us

비지플래그/번지카운터 읽기

0

1

BF

DD RAM 번지

40us

CG RAM, DD RAM 쓰기

1

0

데이터

40us

CG RAM, DD RAM 읽기

1

1

데이터

40us

 

 

 

 

명령어 상세 설명

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

0

0

0

0

0

1

-       화면 클리어 후 커서는 홈 위치(00 번지 - 1 1)로 돌아간다. 그리고, DD RAM의 모든 어드레스에 스페이스 코드인 0x20이 들어가고 AC(Address Counter) DD RAM 어드레스에 0번지가 세트된다.

AC
DD/CG RAM으로 데이터를 쓰거나 기억된 데이터를 읽을 때, 목적지가 되는 RAM의 어드레스를 지정한다. IR에 어드레스 세트 인스트럭션을 써 넣으면, IR에서 AC로 어드레스 정보가 전송된다
.

DD/CG RAM
에 문자 데이터를 써넣으면 엔트리 모드 설정에 따라서 AC는 자동적으로 +1 혹은 -1만큼 증감한다. 그리고, AC의 내용은 RS 0, R/W 1일 때, DB0~DB7을 통해서 읽는다.

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

0

0

0

0

1

x

-       x: 무효 비트, 1이든 0이든 상관없다.

커서를 0으로 돌아가게 한다. AC DD RAM의 어드레스의 0번지가 세트된다.

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

0

0

0

1

I/D

S

-       커서의 진행방향(AC의 증감 방향과 같다) 및 표시를 쉬프트 시킬 것인지를 지정한다.
- Increment/Decrement
  I/D=1:
어드레드를
+1
  I/D=0:
어드레드를
-1
- Shift
  S
1일 때, 표시된 문자 전체를 좌/우로 이동시킨다. 단 이때 커서의 위치는 변하지 않는다
.
  I/D=1, S=1:
좌로 쉬프트

  I/D=0, S=1:
우로 쉬프트
  S=0:
표시는 쉬프트되지 않는다.

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

0

0

1

D

C

B

-       표시 ON/OFF, 커서 ON/OFF, 커서 위치에 있는 문자의 점멸을 설정한다. 커서의 ON/OFF 및 점멸은 AC로 지정되어 있는 DD RAM 어드레스에 해당하는 문자가 된다.

D=1:
표시 ON, D=0: 표시
OFF
C=1:
커서 ON, C=0: 커서
OFF
B=1:
점멸 ON, B=0: 점멸 OFF

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

0

1

S/C

R/L

x

x

-       DD RAM의 내용은 변경하지 않고, 커서 이동과 표시 쉬프트를 한다. 커서의 이동은 1행의 40번째에서 2행의 처음으로 온다. 그러나 표시 쉬프트는 두 행이 동시에 된다.

S/C=0, R/L=0:
커서 위치를 좌로 이동
(AC -= 1)
S/C=0, R/L=1:
커서 위치를 우로 이동
(AC += 1)
S/C=1, R/L=0:
표시 전체를 좌로 이동, 표시는 커서에 따라 움직인다
.
S/C=1, R/L=1:
표시 전체를 우로 이동, 커서는 움직이지 않는다.

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

0

1

DL

N

F

x

x

-       DL=1: 8비트(DB[0:7]) 인터페이스 세트
DL=0: 4
비트(DB[4:7]) 인터페이스 세트, 상위 4비트 전송 후 하위 4비트 전송
N:
표시 행수의 설정(0: 1, 1: 2)
F:
문자 폰트를 설정 (0: 5×7도트, 1: 5×10도트)

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

0

1

A5

A4

A3

A2

A1

A0

-       A[5:0]로 표시되는 CG RAM의 어드레스가 AC에 설정되고 이후 읽기/쓰기 데이터는 CG RAM에 쓰이고 읽혀지게 된다.

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

1

A6

A5

A4

A3

A2

A1

A0

-       A[6:0]로 표시되는 DD RAM의 어드레스가 AC에 설정되고 이후 읽기/쓰기 데이터는 DD RAM에 쓰이고 읽혀지게 된다.

-       DB7 1이 고정 되어 있으므로 프로그램 에서는 0x80을 더하여 주소를 설정 해야 한다. (code visionAVR C lcd_gotoxy(x,y,)를 이용 하는것과 마찬가지)

 

 

6. 데이터 레지스터 (DR : Data Register)

 

  DD RAM CG RAM에 쓰기 할 데이터나 읽어온 데이터를 일시 기억하는데 사용한다.

 

 

7. 비지 플래그 (Busy Flag)

 

  비지 플래그는 LCD모듈이 다음 명령을 받을 수 있는 상태인지를 표시한다. 점검방법은 IR레지스터의 7번 비트가 '1' 인지 '0'인지를 검사한다. ( 1 : 다음 명령을 받을 수 없음, 0 : 받을 수 있음)

  그러나 LCD출력 프로그램 에서는 이와 같은 절차로 점검하여 다음 동작을 하는 것은 번거러움으로 명령과 명령 사이에 지연 시간을 두도록 설계 하는 것이 보통이다.

 

 

8. 어드레스 카운터 (Address Counter)

 

  DD RAM CG RAM의 어드레스를 지정할 때 사용한다.

 

 

Code Vision AVR C LCD기능

 

  Code Vision AVR C에서 사용되는 LCD 제어 함수들은 <lcd.h>에 정리되어 있다. <lcd.h>에서 지원되는 LCD 1x8, 1x16, 2x18, 2x20, 4x20, 2x24, 2x20 등이다.

 

  LCD 함수들

1.     lcd_init(unsigned char lcd_columns)

  LCD 모듈을 초기화 시킨다. 모든 문자를 초기화하고 커서를 1 1열로 위치시킨다.

 ex) 2x16 LCD의 초기화

           lcd_init(16);

 

2.     lcd_clear(void)

  표시된 모든 문자를 지우고, 문자의 출력 위치를 1 1열으로 위치 시킨다.

 ex) lcd_clear( );

 

3.     lcd_gotoxy(unsigned char x, unsigned char y)

  커서의 표시 위치를 설정한다. 여기서 x columns이고 y line이다. (0,0 부터 시작)

 ex) 첫 째줄 6번째 칸으로 이동

           lcd_gotoxy(5,0);

 

4.     lcd_putchar(char c)

  커서가 위치한 지점에 문자를 출력함

 ex) 커서가 위치한 지점에 'A'를 출력 (반드시 작은 따옴표 (' ')를 사용)

           lcd_putchar('A');

 

5.     lcd_puts(char *str)

  커서가 위치한 지점에 SRAM의 문자열을 출력함. 문자열을 먼저 선언 하여야함

 ex) 커서가 위치한 지점에 문자열 "I LOVE NC!"을 출력 (" ")를 사용

           char a[ ] = "I LOVE NC!"

           lcd_puts(a);

 

6.     lcd_putsf(char flash *str)

  커서가 위치한 곳에 FLASH의 문자열을 출력함.

 ex) 커서가 위치한 곳에 문자열 "Robot Study"를 출력

           lcd_putsf("Robot Study");

 

7.     _lcd_ready(void)

LCD모듈이 데이터 수신을 위한 준비를 한다. 이 함수는 LCD에 데이터를 쓰기 전에 반드시 사용해야 한다.

8.     _lcd_write_data(unsigned char data)

  LCD IR 레지스터에 byte 데이터를 Write 한다.

 ex) LCD의 커서를 나타나게 할 경우

           _lcd_ready( );

           _lcd_write_data(0xE); //0xE는 커서의 출력 Enable 명령

 

9.     lcd_write_byte(unsigned char addr, unsigned char data)

  D.D.RAM 이나 C.G.RAM byte 데이터를 Write한다.

 

10.   unsigned char lcd_read_byte(unsigned char addr)

D.D.RAM 이나 C.G.RAM byte 데이터를 읽어오기 한다.

 

 

문자 LCD 출력 실습

 

/*********************************************

This program was produced by Talsu

Date    : 2008-02-28

LCD에 문자를 출력 하는 프로그램 입니다.

lcd_putchar 함수로 한 문자씩 출력 ("I ")

lcd_puts 함수로 SRAM의 문자열 출력 ("love")

lcd_putsf 함수로 flash의 문자열 출력 (" NClab")

*********************************************/

 

#include <mega8535.h>

#asm

   .equ __lcd_port=0x15

#endasm

#include <lcd.h>            //LCD사용을 위한 헤더파일

 

char *lv = "love";          //SRAM문자열 출력을 위한 문자열 변수

void main(void)

{

lcd_init(16);

lcd_putchar('I');             //lcd_putchar 함수를 이용한 문자 출력

lcd_putchar(' ');

lcd_puts(lv);                 //lcd_puts 함수를 이용한 SRAM문자열출력                                                                        lcd_putsf(" Talsu");        //lcd_putsf 함수를 이용한 Flash 문자열 출력

}

크리에이티브 커먼즈 라이선스
Creative Commons License

'My Work > AVR' 카테고리의 다른 글

ATmega8535 - FND, LCD제어  (2) 2008/08/23
ATmega8535 - 시리얼통신 (UART)  (1) 2008/08/23
ATmega8535 - 타이머,카운터 제어 시계 설계  (0) 2008/08/23
ATmega162  (0) 2008/08/23
Posted by 탈수
My Work/AVR2008/08/23 11:56

Code Vison AVR C

ATmega 8535

 

RS232 시리얼 통신

 

컨넥터와 신호선

RS232 통신을 위한 컨넥터는 9핀과 25핀 컨넥터가 있으나, 최근에는 9핀 컨넥터를 많이 사용한다. 실제 데이터가 송 수신 되는 핀은 TXD(3) 와 RXD(2) 이고 기능은 다음과 같다.

9핀 컨넥터의 모습

 

TXD - Transmit Data

비동기식 직렬 통신 장치가 외부 장치로 데이터를 보낼 때, 직렬 통신 데이터가 나오는 신호선

RXD - Receive Data

외부 장치에서 들어오는 직렬 통신 데이터를 입력받는 신호선

케이블을 만들 때에는 반대쪽 커넥터에 연결하기 전에 한번 교차 시켜야 한다. (Rx ->Tx , Tx->Rx)

ATmega8535에서의 RXD, TXD

MAX232

 

MAXIM사에서 생산되는 RS-232통신을 가능토록 해주는 송수신 IC이다. 송수신 드라이브를 각각 2개씩 가지고 있다.

AVR과 컴퓨터가 인식하는 0과 1의 값이 다르기 때문에..

 

마이컴

컴퓨터

0

0V

-10V

1

5V

10V

이 차이를 해결해주는 것이다.

 

TTL IC의 전원단자와 다르게 15번 핀이 GND, 16번이 VCC이므로 주의하자

 

 

IC 내부에는 VOLTAGE DOUBLER와 VOLTAGE INVERTER가 있다.

DOUBLER는 5V를 10V로 증폭 INVERTER는 증폭된 신호를 반전

내부에 5V를 충전했다 10V로 보내기 위한 콘덴서가 있다.

 

MAX232는 전압을 바꾸어 주는 역할만을 하며 통신을 하는것은 아님에 주의!

 

 

 

프레임 형식

 

직렬 데이터 프레임은 동기비트 (스타트, 스톱 비트) 와 에러 검사를 위한 패리티 비트(선택가능)와 데이터 비트를 포함하는 1문자를 의미한다.

 

컴퓨터 쪽에서는 다음과 같이 설정한다.

 

 

보레이트 9600 데이터 비트는 8비트 패리티 비트 사용 안 함 STOP비트는 1로 설정한 모습

 

시리얼 통신을 위한 레지스터

 

ATmega8535에는 시리얼 통신용 컨트롤러가 포함 되어 있다.

CPU 내부에서 CPU의 코어 부분과 시리얼 통신용 컨트롤러가 데이터를 주고 받고, 컨트롤러는 RxD, TxD의 핀을 통해 외부와 통신을 하고 있다.

시리얼 통신을 위한 레지스터에는 설정용 레지스터와 데이터 통신용 레지스터가 있고 설정용 레지스터를 이용해 설정을 하고 통신용 레지스터를 이용해 실제 통신을 한다

 

 

UDR

7

6

5

4

3

2

1

0

RXB (Read)

TXB (Write)

 

UDR레지스터는 데이터를 입력하면 설정한 값에 맞게 데이터를 전송하는 레지스터이다.

UDR레지스터를 읽으면 수신 데이터 버퍼 레지스터(RXD)의 내용을 볼수 있다. 즉, 송신 데이터를 UDR레지스터에 쓰기하면 송신데이터 버퍼 (TXB)에 저장하고, 수신 데이터를 UDR 레지스터에 쓰기하면 수신 데이터 버퍼(RXB)에 수신되어 있는 값이 읽혀진다.

 

 

 

UCSR 레지스터

UCSR은 A,B,C세 개로 구성 되어 있고, 상태 설정과 제어의 기능을 한다.

 

UCSRA

7

6

5

4

3

2

1

0

RXC

TXC

UDRE

FE

DOR

PE

U2X

MPCM

7. RXC : 수신 완료 표시 비트

6. TXC : 송신 완료 표시 비트

5. UDRE : 송신 데이터 레지스터 준비 완료 표시 비트

4. FE : 프레임 에러 표시 비트

3. DOR : 데이터 오버런 에러 표시 비트

2. PE : 패리티 에러 표시 비트

1. USX : 송신 속도 2배 설정

0. MPCM : 멀티 프로세서 통신 모드

    *1번과 0번을 설정하고 나머지는 읽기 전용이다. (사용 할 때 1 아닐 때 0)

 

UCSRB

7

6

5

4

3

2

1

0

RXCIE

TXCIE

UDRIE

RXEN

TXEN

UCSZ2

RXB8

TXB8

7. RXCIE 수신 완료 인터럽트 인에이블 비트

6. TXCIE 송신 완료 인터럽트 인에이블 비트

5. UDRIE 송신 데이터 레지스터 준비 완료 인터럽트 인에이블 비트

4. RXEN 수신기 인에이블

3. TXEN 송신기 인에이블

2. UCSZ2 전송 데이터 길이 선택 비트

1. RXB8 수신 데이터 비트 8

0. TXB8 송신 데이터 비트 8

 

UCSRC

7

6

5

4

3

2

1

0

URSEL

UMSEL

UPM1

UPM0

USBS

UCSZ1

UCSZ0

UCPOL

7. UREL 레지스터 선택 비트

6. UMSEL 시리얼 통신 모드 설정 비트

5. UPM1 패리티 모드 설정 비트

4. UPM0 패리티 모드 설정 비트

3. USBS 정지 비트 선택

2. UCSZ1 전송 데이터 비트 수 설정

1. UCSZ0 전송 데이터 비트 수 설정

0. UCPOL 클럭 극성 선택

 

보레이트 속도 설정 관련 레지스터

 

보레이트 - 신호 하나의 속도

보레이트 속도를 조절 하는 레지스터는 UBRRH와 UBRRL 2개로 이루어져 있다. UBRRH의 4비트와 UBRRL의 8비트를 합친 12비트를 이용하여 속도를 설정한다.

 

UBBRH

7

6

5

4

3

2

1

0

URSEL

사용하지 않음 ( 0 )

UBRR의 값 (11 ~8 비트)

 

UBBRL

7

6

5

4

3

2

1

0

UBRR의 값 (7 ~0 비트)

 

UBRRH는 UCSRC레지스터와 같은 번지를 사용 하고 있다. 그렇기 때문에 UCSRC로 사용 할 것인지 UBRRH로 사용 할 것인지 선택을 해야 하는데, 이 기능을 하는 것이 7번 URSEL비트이다.

URSEL이 0일 때 UBRRH의 기능을 갖고 1일 때 UCSRC의 기능을 갖는다.

 

UBRR의 값은 보레이트와 시스템 클럭을 이용하여 계산 한다.

예를 들어 시스템 클럭이 16Mhz 이고 보레이트를 9600 bps로 잡았을 때

 

UBRR의 값은 103.1666.... 이 된다.

여기서 소수점 이하를 버리고 103을 2진수로 변환하면 1100111이 된다.

결국 UBRRH의 4 비트에는 모두 0이 들어가고 UBRRL에는 01100111이 들어가므로, 다음과 같이 입력 한다.

    UBRRH=0;

    UBRRH=103;    //물론 0b01100111으로도 입력 가능하다.

 

데이터 전송 레지스터

 

직렬 통신에 사용하는 입출력 함수

 

void puts(char *str)

 

외부로 SRAM의 문자열을 출력 하는 기능을 가진다. 문자열의 끝 부분에는 null(0x0A)를 추가하여 출력한다. null 문자는 터미널 화면에서 줄바꾸기를 한다.

하지만 줄의 맨 앞이 아닌 최종 출력지점의 바로 다음 줄로 출력 된다.

 

Ex)    Hello NClab!

         Hello NClab!

 

터미널의 제일 첫줄로 줄바꿈을 하기 위해서는 제어 문자인 "\r"=>"0x0D+0x0A"를 끝 부분에 첨가하거나 다음 문장에 "0x0D"를 출력 하여 커서를 맨앞으로 이동 시킨다.

 

void putsf(char flash *str)

 

외부로 Flash의 문자열을 출력 하는 기능을 가진다.

줄바꿈 형식은 puts와 동일

 

void printf(char flash *fmtstr [,arg1,arg2,....])

fmtstr 문자열에 있는 문자열을 출력 하는 기능을 가진다. 특히, fmtstr은 상수이며 Flash 메모리에 위치해 있어야 한다.

Ex) int_val = 112;

    printf("Interger value =%5i", int_val);

    // %5i 는 5칸에 정수를 출력 하라는 뜻

 

 

직렬 통신 프로그램

 

출력 함수들을 사용해보자

 

#include <mega8535.h>

#include <stdio.h>

 

void rs232_putchar(void)        //한글자씩 출력하는 putchar() 사용한 함수

{

putchar('I');

putchar(' ');

putchar('L');

putchar('O');

putchar('V');

putchar('E');

putchar(' ');

putchar('N');

putchar('C');

putchar(0x0A);        //줄바꿈

putchar(0x0D);        //커서 제일 앞으로

}

 

 

void main(void)

{

char data[] = "I LOVE NC 2";    //SRAM 문자열을 출력 하기 위한 문자열 배열

 

// USART initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART Mode: Asynchronous

// USART Baud Rate: 9600

UCSRA=0x00;

UCSRB=0x18;

UCSRC=0x86;

UBRRH=0x00;

UBRRL=0x33;

 

    rs232_putchar();    //한글자씩 출력 하는 함수 호출

    

    puts(data);    //SRAM 문자열 출력

    putchar(0x0D);    //줄바꿈

 

    putsf("I LOVE NC 3 \r");    //Flash 문자열 출력 (줄바꿈 문자 \r)포함

}

 

결과

I LOVE NC

I LOVE NC 2

I LOVE NC 3

 

 

입력은 어떻게 받는지 알아보자

 

#include <mega8535.h>

#include <stdio.h>

 

unsigned char rx_data;        //수신된 문자를 받기 위한 전역 변수

 

void led_control(void)

{

rx_data = getchar();    //getchar() 수신 데이터를 받는 함수 이다(UDR).

putchar(rx_data);        //받은 문자를 출력 함으로써 에코 효과

switch (rx_data) {    //받은 문자에 따라 행동

case 0x30: PORTA = 0x00;        //0X30 '0' 해당하는 ASCII코드임

break;                //'0'일때 PORTA 0 출력

case 0x31: PORTA = 0x01;        //0X31 '1' 해당하는 ASCII코드임

break;

case 0x32: PORTA = 0x02;        //0X32 '2' 해당하는 ASCII코드임

break;

case '3': PORTA = 0x03;    //직접 '3'이라는 문자를 적어 있음

break;

case '4' :PORTA = 0x04;

break;

case '5': PORTA = 0x05;

break;

case '6': PORTA = 0b00110011;    //물론 출력은 2진수로도 쓸수 있다.

break;

default: PORTA = 0x00;

};

}

 

void main(void)

{

PORTA=0x00;

DDRA=0xFF;        //PORTA 모두 출력 모드

 

// USART initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART Mode: Asynchronous

// USART Baud Rate: 9600

UCSRA=0x00;

UCSRB=0x18;

UCSRC=0x86;

UBRRH=0x00;

UBRRL=0x33;

 

while (1)        //무한루프로 입력을 감지 한다.

{

led_control();    //함수 호출

};

}

 

결과

0~6까지의 입력에 따라 LED가 반응한다.

응용 프로그램 : 입력을 받아 LCD에 표시 해보자

#include <mega8535.h>

#asm

.equ __lcd_port=0x15

#endasm

#include <lcd.h>

#include <stdio.h>

 

unsigned char getdata;        //입력된 ASCII코드를 담을 변수

 

void char_input (void)        //입력 받은 문자에 따라 행돌할 함수

{

    getdata = getchar();    //입력된 문자를 받고

switch (getdata){

case 0x0D:        //Enter

    lcd_gotoxy(0,1);    //2 1열로 커서 옮김 (줄바꿈)

    break;

case 0x1B:        //Esc

    _lcd_ready();    //LCD 데이터 수신 준비

    _lcd_write_data(0b00000001);    //클리어 명령

    break;

case 0x09:                //TAB

    _lcd_ready();

    _lcd_write_data(0b00011000);    //전체 화면 왼쪽으로 쉬프트

    break;

    case 0x08: _lcd_ready();            //BackSpace

        _lcd_write_data(0b00010000);    //커서를 왼쪽으로 한칸 옮김

        lcd_putchar(0x20);        //공백문자 입력

        _lcd_ready();

        _lcd_write_data(0b00010000);    //커서를 왼쪽으로 한칸 옮김

        break;

default:

    lcd_putchar(getdata);    //받은 문자를 LCD 출력

    putchar(getdata);        //컴퓨터 화면에 출력 (에코)

    PORTA = getdata;    //LED 출력 (ASCII code 볼수 있다.)

};

 

}        

 

void main(void)

{

PORTA=0x00;

DDRA=0xFF;     //LED ASCII code출력을 위해 모두 출력모드로

 

// USART initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART Mode: Asynchronous

// USART Baud rate: 9600

UCSRA=0x00;

UCSRB=0x18;

UCSRC=0x86;

UBRRH=0x00;

UBRRL=0x33;

 

lcd_init(16);

_lcd_ready();

_lcd_write_data(0b00001111);    //표시 ON/OFF제어 표시,커서,점멸 모두 ON

printf("Enter : ");        //입력하라는 안내문 표시

while (1)                //무한루프로 입력을 감지

{

    char_input();    //함수 호출     

};

}

 

/*********************************************

This program was produced by Talsu

RS232시리얼 통신을 이용하여 키보드의 입력을 받아

LCD화면에 표시 해주는 프로그램 입니다.

키 입력이 자유 롭게 되고.

Enter키 = 줄바꿈

Backspace = 한글자 지우기

space = 띄우기

TAB = 화면 쉬프트

*********************************************/

크리에이티브 커먼즈 라이선스
Creative Commons License

'My Work > AVR' 카테고리의 다른 글

ATmega8535 - FND, LCD제어  (2) 2008/08/23
ATmega8535 - 시리얼통신 (UART)  (1) 2008/08/23
ATmega8535 - 타이머,카운터 제어 시계 설계  (0) 2008/08/23
ATmega162  (0) 2008/08/23
Posted by 탈수
My Work/AVR2008/08/23 11:53

Code Vison AVR C

ATmega 8535

 

타이머/카운터

표시된 포트들을 사용 한다.

 

 

타이머 카운터 0

타이머/카운터 0 는 범용이며 싱글채널 8비트 타이머/카운터 모듈이다.

타이머/카운터 0은 overflow 인터럽트(타이머/외부 입력 카운터), 비교일치 인터럽트, PWM으로 사용된다.

ATmega8535에는 타이머/카운터 0에는 출력을 위한 OC0(PB3)핀과 카운터 입력을 위한 T0(PB0)핀이 있다.

이것이 타이머로 동작할 경우는 시스템 클럭 소스로 사용하며, 시스템 클록은 프리스케일러에 의해 1, 18, 64,256, 1024 중의 하나로 분주하여 클록 소스로 공급된다. 클록 입력을 차단하면 타이머/카운터 기능이 정지된다.

TCNT0 레지스터에 동작 모드에 따라 클록에서 입력되는 값이 저장되며 0xFF에서 0x00되는 순간 overflow 인터럽트가 발생한다. 또 출력 비교 일치 레지스터 OCR0와 비교하여 그 값이 일치하면 출력비교일치 인터럽트가 발생한다.

 

 

 

TCCR0 레지스터 (Timer/Counter 0 Control Register)

타이머 제어 레지스터로써 다름과 같은 구조로 되어 있고 역시 8비트로 셋팅한다.

FOC0

WGM0

COM1

COM0

WGM1

CS2

CS1

CS0

  1. FOC (Force Output Compare) : Normal과 CTC모드에서 이 비트가 1로 셋팅 되는 순간 OC0에 출력값이 나오게 하는 것으로 그다지 많이 사용 되지 않는다.
  2. WGM0, WGM1 (Waveform Generation Mode): 타이머의 동작 모드를 결정하는 비트로써 4가지 모드를 선택 한다.

WGM0

WGM1

MODE

0

0

Normal

1

0

PWM

0

1

CTC

1

1

Fast PWM

Normal 모드 : 0에서 255까지 도달하게 되면 인터럽트를 발생하고 다시 0으로 돌아가는 모드로 초기 값을 조절 하여 주기를 더 짧게 만들 수 있다. 업 카운터로만 동작하며, 카운트가 동작 중 클리어 되지 않으며, 항상 0x00에서 0xFF로 반복 한다.

CTC 모드 : 0에서 프로그래머가 셋팅해 둔 값에 도달하면 인터럽트를 발행 시키고 다시 0으로 돌아가는 모드, 0x00 -> OCR0의 값으로 카운터를 반복 수행 한다.

PWM 모드 : 디지털적으로 아날로그를 제어하는 방법 (전구의 밝기, 모터의 속도..)

 

  1. COM1, COM0 (Compare Match Output Mode) : OC0 핀의 기능을 정한다.

COM1

COM0

MODE

0

0

범용 I/O 포트로 동작(OC0 핀 차단)

0

1

OC0 핀 출력 토글

1

0

OC0 핀 출력을 0으로 클리어

1

1

OC0 핀 출력을 1로 설정

  1. CS0, CS1, CS2 (Clock Select): 클럭의 분주를 설정한다. CPU에 사용한 크리스탈의 주파수를 얼마만큼 분주 할 것인지 설정한다.

CS2

CS1

CS0

기능

0

0

0

클럭 입력 차단(타이머 사용 안함)

0

0

1

시스템클럭 / 1

0

1

0

시스템클럭 / 8

0

1

1

시스템클럭 / 64

1

0

0

시스템클럭 / 256

1

0

1

시스템클럭 / 1024

1

1

0

외부 입력 클럭 하강 엣지

1

1

1

외부 입력 클럭 상승 엣지

 

OCR0 (Output Compare Register)레지스터

분주된 클럭이 몇 번 발생한 후 인터럽트를 발생하게 하는지를 설정하는 레지스터

Ex) OCR0 = 125;         // 클럭이 125번 발생하면 인터럽트를 발생한다.

(결국 분주의 기능을 가지고 있음)

 

TCNT0 (Timer/Counter Register)레지스터

TCNT0 레지스터는 프로그램이 실행되는 동안 분주된 클럭의 주기로 0에서 부터 몇 번째 주기가 발행 했는지 나타낸다. 이 레지스터는 쓸 수도 있고 읽을 수도 있다. 값을 쓰면 주기를 더 빠르게 할 수 있다. 레지스터의 값은 인터럽트가 걸리면 자동으로 0으로 클리어 되고 다시 분주된 주기마다 한 개씩 값이 늘어난다.

 

TIMSK (Timer/Counter Interrupt Mask Register)레지스터

 

TOIE1

OCIE1A

OCIE1B

OCIE2

TICE1

TOIE2

TOIE0

OCIE0

 

TOIE0(Timer0 Overflow Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽트를 인에이블 하면 Normal모드의 타이머 인터럽트가 작동.

OCIE0(Timer0 Output Compare Match Interrupt Enable) 비트를 1로 셋팅하고 시스템 인터럽트를 인에이블 하면 CTC모드의 타이머 인터럽트가 작동.

 

사용 함수

sei( ) : 인터럽트를 인에이블 시키는 함수

sli( ) : sei의 반대 되는 것으로 시스템 인터럽트를 디스에이블 시킨다.

SIGNAL( ) : 인터럽트가 발생 했을 때 이 함수로 점프한다.

SIG_OUTPUT_COMPARE0 : 내부, 외부 관계 없이 인터럽트가 발생하면 해당 번호에 따른 번지로 점프하게 된다.

 

 

타이머/카운트를 이용한 LCD 시계를 만들어 보자

/*********************************************

This program was produced by Talsu

Date : 2008-02-22

*********************************************/

 

#include <mega8535.h>

#include <stdio.h>

#asm

.equ __lcd_port=0x15 ;PORTC

#endasm

#include <lcd.h>

unsigned char key;

unsigned char sec_cnt;

unsigned char sec0;

unsigned char min0;

unsigned char hour0;

unsigned char bang_cnt;

unsigned char bang;

unsigned char backslash[8]={ //CG RAM에 입력할 글자 패턴을 저장하는 함수

0b00001110,

0b00010001,

0b00011011,

0b00010001,

0b00010101,

0b00010101,

0b00001110,

0b00000000};

 

unsigned char ms1;

 

void define_char(unsigned char *pc,unsigned char char_code)

/*CG RAM에 글파 패턴을 입력하는 함수*/

{

unsigned char i,a;

a=(char_code<<3) | 0x40;

for (i=0; i<8; i++) lcd_write_byte(a++, *pc++);

}

interrupt [TIM0_OVF] void timer0_ovf_isr(void)        //카운터 인터럽트에 반응 하는 함수

{

sec_cnt++;

if(sec_cnt == 125){         //0.1초를 맞추기위한 분주

ms1++;

bang_cnt++;

sec_cnt = 0;

PORTA = ~PORTA;

}

TCNT0 = 256 - 25;

}

 

void main(void)

{

char lcd_text[16];

char lcd_text2[1];

 

PORTA=0x55;

DDRA=0xFF;

 

DDRD=0x00;

PORTD=0xFF;

 

// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: 31.250 kHz

// Mode: Normal top=FFh

// OC0 output: Disconnected

TCCR0=0x04;

TCNT0=256-250;

OCR0=0x00;

 

// Timer(s)/Counter(s) Interrupt(s) initialization

TIMSK=0x01;

 

// Analog Comparator initialization

// Analog Comparator: Off

// Analog Comparator Input Capture by Timer/Counter 1: Off

ACSR=0x80;

SFIOR=0x00;

 

// LCD module initialization

lcd_init(16);

 

#asm("sei")

define_char(backslash,0); //CG RAM에 원하는 패턴을 입력

lcd_clear();

 

while (1)

{

    key = PIND & 0xFF;

    if(key == 0b11111110){

        hour0++;

        }

if (ms1 == 10){         //0.1초가 10번 카운트되면

sec0++;     //1초 증가

ms1 = 0;        //0으로 초기화

}

if (sec0 == 60){

min0++;

sec0 = 0;

}

if (min0 == 60){

hour0++;

min0 = 0;

}

if (hour0 ==24){

hour0 = 0;

}

if (bang_cnt == 4){

bang_cnt = 0;

}

switch (bang_cnt){

case 0: bang = '|'; break;

case 1: bang = '/'; break;

case 2: bang = '-'; break;

case 3: bang = 0xA4; break;    //저장된 패턴을 불러옴

}

 

    lcd_gotoxy(0,0);

    sprintf(lcd_text, " %2dh %2dm %2d.%is ",hour0,min0,sec0,ms1);    //시간을 출력

    lcd_puts(lcd_text);

    sprintf(lcd_text2,"%c",bang);

    lcd_gotoxy(0,1);

    lcd_puts(lcd_text2);

    lcd_putchar(0);

lcd_puts(lcd_text2);

lcd_putsf("...nclab..");

lcd_puts(lcd_text2);

lcd_putchar(0);

lcd_puts(lcd_text2);

};

}

크리에이티브 커먼즈 라이선스
Creative Commons License

'My Work > AVR' 카테고리의 다른 글

ATmega8535 - FND, LCD제어  (2) 2008/08/23
ATmega8535 - 시리얼통신 (UART)  (1) 2008/08/23
ATmega8535 - 타이머,카운터 제어 시계 설계  (0) 2008/08/23
ATmega162  (0) 2008/08/23
Posted by 탈수