본문 바로가기
코스웨어/16년 스마트컨트롤러

20160316_김도관_업무일지_LCD_문자열출력

by 알 수 없는 사용자 2016. 3. 23.
728x90
반응형

작업:

LCD를 통한 문자열 출력



개요:

Atmega의 입출력을 외부인터럽트를 사용해서 LCD에 출력



LCD Pin






lcd.h

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
#ifndef __LCD_H__
#define __LCD_H__
 
#include "main.h"
 
#define RS 4
#define RW 5
#define EN 6
 
#define BUS PORTA
#define CTL PORTC
 
// 케릭터lcd명령어 pdf 파일참고 
#define    LCD_CLR     0x01    //화면지우기
#define    LCD_HOME    0x02    // 03가능// 홈
#define    LCD_ENT     0x06    //S:0Shift OFF, I/D:1 Increase Mode  // 엔트리모드셋 2진수 0110
#define    LCD_DSP     0x0F    //D:1 Display On C:1 Cursor on B:1 Blink On 1 // 2진수 1111
#define    LCD_CUR     0x14    //S/C:0 Shift Cursor OFF R/L:1 // 2진수 0001 0100
#define    LCD_FUNC    0x38    //DL:1 Data length 8bit  N:1 2Line F:0 Font 5X8 // 2진수 0011 1000
 
void LCD_Init(void);
void LCD_Inst(unsigned char ucInst);
void LCD_Data(unsigned char ucData);
void LCD_Str(char const *cString);
 
#endif //__LCD_H_
cs


6~8번   : 각각 pin 번호 부여 LCD 모듈 컨트롤하기위한 RS,RW,E

10번     : PORTA를 BUS로 지정

11번     : PORTC를 제어로 지정

14번     : C영역 0000 0001 clear displayer 명령 실행

15번     : C영역 0000 0010 Return Home 명령 실행

16번    :  C영역 0000 0110 Entry Mode 1 커서방향은 오른쪽으로 이동 SHIFT가 0이므로 쉬프트 X

17번    :  C영역 0000 1111 디스플레이 제어 - Display ON ,화면 ON,커서 ON,커서 깜박임 ON 

18번    :  C영역 0001 0100 Cursor or Display Shift 명령 실행 - 오른쪽으로 커서 이동

19번    :  C영역 0011000 Function Set 명령어 실행 ,Bus Size 8Bit, 2Line,5*10 font dots

21~24번 : 각각의 함수원형


lcd.c

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "lcd.h"
 
void LCD_Init(void)
{
    DDRC = ( 1 << RS )|1 << RW )|1 << EN ); //rs,rw,en 열기 
    DDRA = 0xFF;
    CTL  = ( 0 << RS )|0 << RW )|0 << EN ); //Low 상태CTL == PORTC
    BUS  = 0x00;
    LCD_Inst(LCD_FUNC);
    LCD_Inst(LCD_DSP);
    LCD_Inst(LCD_ENT);
    LCD_Inst(LCD_CUR);
    LCD_Inst(LCD_CLR);
    LCD_Inst(LCD_HOME);
    
    return;
}
 
void LCD_Inst(unsigned char ucInst)
{
    //unsigned char int ucInst = 0x41; // ucInst
    volatile unsigned int uiCnt;
    //A 구간
    CTL = CTL & (~ (1 << RS)); // CTL == PORTC
    CTL = CTL & (~ (1 << RW));
    CTL = CTL & (~ (1 << EN));
    BUS = ucInst; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //B 구간
    //CTL = CTL & (~ (1 << RS)); // CTL == PORTC     //*****  RS/RW/DB 는유지되므로****//
    //CTL = CTL &    (~ (1 << RW));
    //CTL = CTL & (~ (1 << EN));                     //**** 중복제거 *****//
    //BUS = ucInst; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //c 구간
    //CTL = CTL & (~ (1 << RS)); // CTL == PORTC
    //CTL = CTL &    (~ (1 << RW));
    CTL = CTL |    (1 << EN);  // high 값을 가지므로 
    //BUS = ucInst; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //D 구간
    //CTL = CTL & (~ (1 << RS)); // CTL == PORTC
    //CTL = CTL &    (~ (1 << RW));
    CTL = CTL & (~ (1 << EN));
    //BUS = ucInst; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //E 구간
    //CTL = CTL & (~ (1 << RS)); // CTL == PORTC
    //CTL = CTL &    (~ (1 << RW));
    //CTL = CTL & (~ (1 << EN));
    //BUS = ucInst; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    return;
}
 
void LCD_Data(unsigned char ucData)
{
    volatile unsigned int uiCnt;
    //A 구간
    CTL = CTL | (1 << RS); 
    CTL = CTL & (~ (1 << RW));
    CTL = CTL & (~ (1 << EN));
    BUS = ucData; 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++); // BUS를 통해 DATA와 Instruction 구간적 시간벌이 
 
    //B 구간
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //c 구간
    CTL = CTL |    (1 << EN);  // high 값을 가지므로 
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //D 구간
    CTL = CTL & (~ (1 << EN));
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    //E 구간
    for(uiCnt = 0 ; uiCnt < 30000; uiCnt++);
 
    return;
}
 
void LCD_Str(char const *cString)
{
    while(0 != *cString)
        {
            LCD_Data(*cString);
            ++cString;
        }
    return;
}
cs


3번 : lcd_Init 함수 - LCD 초기화 

5번 : PortC의 4,5,6핀에 각각 RS, RW, E 출력 설정

6번 : PortA 모두 출력

7번 : 제어 모두 Low로 설정

8번 : Bus도 0로 초기화

9~14번 : 각각의 기능들을 초기화


19번 : LCD_Inst 함수

24번~26번 : A구간  비트&연산에 의해 RS,RW,E는 모두 0

27번 : 문자를 버스에 넣음

28번 : 딜레이

35번 : B구간은 A가 유지되므로 딜레이만 시킴

40번 : C구간에서 E는 High 값을 가짐 LCD Enable

47번 : D구간에서 E는 Low 값을 가짐 LCD disable

56번 : E 구간 현상유지 딜레이만 함


61번 : LCD_Data 함수 

65번 : A구간 RS 에 high값을 줘서 DATA전달  RW,E는 0

68번 : Bus에 문자넣음

72번 : B구간 현상유지하며 딜레이

75번 : C구간에서 E는 High 값을 가짐 LCD Enable

79번 : D구간에서 E는 Low 값을 가짐 LCD disable

83번 : E구간 현상유지 딜레이만 함


88번 : LCD_Str 함수 

  cString에 값이 있는지 판단후 있으면 cString문자열을 LCD_Data함수에 문자열을 하나씩 담아서 보냄


main.h

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
#ifndef __MAIN_H__
#define __MAIN_H__
 
#define PINA     (*((volatile unsigned char *)0x20))
#define DDRA     (*((volatile unsigned char *)0x21))
#define PORTA     (*((volatile unsigned char *)0x22))
 
#define PINC     (*((volatile unsigned char *)0x26))
#define DDRC     (*((volatile unsigned char *)0x27))
#define PORTC    (*((volatile unsigned char *)0x28))
 
#define EICRA    (*((volatile unsigned char *)0x69))
#define EICRB    (*((volatile unsigned char *)0x6A))
#define EIMSK    (*((volatile unsigned char *)0x3D))
 
#define SREG    (*((volatile unsigned char *)0x5F))
 
#define INT7 7
#define INT6 6
#define INT5 5
#define INT4 4
#define INT3 3
#define INT2 2
#define INT1 1
#define INT0 0
 
#define ISC7 6
#define ISC6 4
#define ISC5 2
#define ISC4 0
#define ISC3 6
#define ISC2 4  
#define ISC1 2
#define ISC0 0
 
#define sei()   __asm__ __volatile__ ("sei" ::)
#define sleep()    __asm__ __volatile__ ( "sleep" "\n\t" :: )
 
//void Init (void);
 
//void Port_Init(void);
 
//void INT_Init(void);
 
void __vector_1 (void) __attribute__((signal, used, externally_visible));
void __vector_2 (void) __attribute__((signal, used, externally_visible));
 
#endif //__MAIN_H_
cs


4~16번 : 각각 해당하는 PinA,C및 EICRA,EICRB,EIMSK ,SREG 주소 설정

18~34번 : 사용할 값들 정의

36~37번 : sei및 sleep 정의

45~46번 : 인터럽트 벡터(interrupt vector) 인터럽트가 발생했을 때, 그 인터럽트를 처리할 수 있는 서비스 루틴들의 주소를 가지고 있는 공간 

vector1과 vector2로 할당


main.c

1
2
3
4
5
6
7
8
9
10
11
#include "main.h"
#include "lcd.h"
 
int main(void)
{
    LCD_Init();
    //LCD_Data('A');
    LCD_Str("AAAAAAAAA");
    while(1);
    return 0;
}
cs



1~2번 : main.h 와 lcd.h 헤더 불러옴

6번 : LCD_Init() 함수 호출 - 초기화시킴

8번 : LCD_STR("") 문자열 출력


출력:



728x90