47일차
------------------------
ATMega128 LCD 제어
------------------------
- 코드 최적화
소스 코드에 중복된 부분이 많으니
중복된 부분을 지워주는 최적화
- main.c
소스코드에서 으로 된 부분은 다 중복된 부분이다.
- 이것을 간결화 한 코드
으로 된 부분이 수정된 곳.
- smart.h (헤더파일에 추가된 부분)
......
#define INST_CLEAR 0x01 // Clear
#define INST_RETURN 0x02 // Return
#define INST_ENTRY 0x06 // I/D = 1(Increase 1, Decrease 0), S = 0
#define INST_FUNCTION 0x3C // 8bit, 2Line, 5x11
#define INST_CURSOR 0x14 // Cursor SET, Moving right.
#define INST_DISPLAY 0x0F // Display light ON, cursor ON, blinking of cursor ON
......
- main.c
으로 블록된 부분만 수정하면 인자로 문자를 받아 출력이 가능하다.
- 좀 더 기능을 추가해 문자열을 출력.
void LCD_Str(const unsigned char * cString)
{
while(0 != *cString)
{
LCD_Data(*cString);
++cString;
}
}
- 또 기능을 추가해 숫자를 출력.
숫자의 경우 153이란 숫자를 출력하려면
문자 3글자가 출력되어야 한다.
간단히 char형으로 (최대 255까지 가능하니 3글자만 필요) 구현해 보자.
void LCD_Num(unsigned char ucNum)
{
static unsigned char ucBuff[] = "123"; // 3자리 확보 보기 쉽게
ucBuff[
0] = '0' + (ucNum / 100);ucBuff[1] = '0' + ( (ucNum % 100) / 10);
ucBuff[2] = '0' + ( (ucNum % 100) % 10);
LCD_Str(ucBuff);
}
ucBuff[] = "123" 초기값을 123으로 넣어준 이유는
3글자를 받는데 이것도 문자열로 취급해야 하니 맨 마지막에 NULL이 들어가야 하므로
"123" 해주면 3자리 확보하고 맨 마지막에 NULL이 들어간다.
static을 붙여준 이유는 자주 쓰게 되면 메모리를 계속 할당 해제할 경우
느려지게 되므로 속도를 높이고자 사용하였다.
자주 쓰지 않는다면 static을 붙이지 않는게 좋다.
실습 화면
- LCD_Num을 이용해 자료형들의 크기 확인
int main(void)
{
LCD_Init();
LCD_Num(sizeof(char));
LCD_Num(sizeof(int));
LCD_Num(sizeof(double));
LCD_Num(sizeof(char *));
LCD_Num(sizeof(int *));
LCD_Str(" ");
LCD_Num(sizeof(short));
LCD_Num(sizeof(float));
LCD_Num(sizeof(long));
LCD_Num(sizeof(long double));
LCD_Num(sizeof(long long));
while(1);
return 0;
}
char : 1
char * : 2
int : 2
int * : 2
short : 2
long : 4
float : 4
double : 4
long double : 4
long long : 8 (단위 : byte)
- DDRAM
LCD_Inst(INST_SET_DDRAM | 0x40);
이런식으로 명령을 주게 되면 2번째 줄부터 출력을 실행한다.
--------------------------------------------------
--- Cursor or Display R/L, S/C 옵션에 대하여...
도대체 R/L, S/C 의 옵션이 뭘 하는지 알아보기
우선 Cursor or Display 옵션은 DDRAM의 메모리를
바꾸지 않고 화면에 출력하는 위치를 조절할 수 있다.
LCD_Init();
// LCD_Inst(0x06); // entry I/D = 1(2 1/0), S = 0(1 ON(1)/OFF(0))
// LCD_Inst(0x14); // S/C = 0(8 1/0), R/L = 1(4 1/0)
// 여기까지 이게 적용됨.
LCD_Inst(INST_SET_DDRAM | 0x02);
LCD_Str("abc");
LCD_Inst(INST_SET_DDRAM | 0x42);
LCD_Inst(0x06); // entry I/D = 1(2 1/0), S = 0(1 ON(1)/OFF(0))
LCD_Inst(0x??); // S/C = (8자릿수 1/0), R/L = (4자릿수 1/0).
LCD_Str("123");
- C, R 옵션을 줬을 경우
123이 C,R 옵션이 적용됨.
원래 옵션에서 R의 옵션이 더 더해져 오른쪽으로 한 칸 더 이동했다.
- C, L 옵션을 줬을 경우
123이 C,R 옵션에서 L 옵션이 더해져 왼쪽으로 한 칸 더 이동했다.
- S, R 옵션을 줬을 경우
123 뿐만 아니라 abc 까지. 화면 전체가 오른쪽으로 더 이동했다.
- S, L 옵션을 줬을 경우
위와 마찬가지로 abc, 123 화면 전체가 왼쪽으로 더 이동했다.
- C
--------------------------
Single Linked List
--------------------------
--- 리스트에 삽입과 삭제
- 삽입의 경우
1. 중간에 삽입
2. 맨 뒤에 삽입
3. 맨 앞에 삽입
이 세가지 경우의 순서에 따라 코드를 작성.
각 앞뒤의 리스트를 잃어버리지 않고 잘 연결하는 것이 중요.
- 삭제의 경우
1. 중간에 삭제
2. 맨 끝 삭제
3. 맨 앞 삭제
4. 없는 문자 삭제
이 경우에 따라 작성.
- 삽입
Node * Node_Insert(Node * Head, char cData)
{
Node * stpNew;
Node * stpFront;
Node * stpRear;
stpFront
= Head;stpRear = Head;
stpNew = malloc(sizeof(Node));
stpNew-
>data = cData;stpNew->next = NULL;while(0 != stpRear) // 삽입 위치 검색
{
if(stpNew->data < stpRear->data) // 삽입 위치 판단
{
break;
}
stpFront = stpRear;
stpRear = stpRear->next;
}if(Head != stpRear) // 처음인지 그 이후인지 확인.
{ // 중간, 끝
stpNew->next = stpRear;
stpFront->next = stpNew;
}
else // 맨 앞
{
stpNew->next = Head;
Head = stpNew;
}return Head;
}
- 삭제
Node * Node_Del(Node * Head,
char cData){
Node * stpFront;
Node * stpRear;
stpFront
= Head;stpRear = Head;while(0 != stpRear) // 삭제 위치 검색
{
if(cData == stpRear->data) // 삭제 위치 판단
{
break;
}
stpFront = stpRear;
stpRear = stpRear->next;
}if(0 == stpRear) // 없는 문자일 경우
{
return Head;
}
else if(Head != stpRear) // 중간, 끝
{
stpFront->next = stpRear->next;
}
else // 처음
{
Head = Head->next;
}
free(stpRear);
return Head;}