■Double Circular Linked List■

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
void initDCLL(Node **H) {
    *= (Node*)malloc(sizeof(Node));
    (*H)->next = *H;
    (*H)->prev = *H;
}
 
Node * createNode( T_DATA data ){
    Node *= (Node*)malloc(sizeof(Node));
    t->data = data;
    t->next = NULL;
    t->prev = NULL;
    return t;
}
 
void _insertNode(Node *newnode, Node *P, Node *N) {
    newnode->prev = P;
    newnode->next = N;
    P->next = newnode;
    N->prev = newnode;
}
 
typedef struct {
        char *Name;
        char *PhoneNo;
} Phonebook;
 
typedef struct _Node {   
    T_DATA data;            
    struct _Node *prev;   
    struct _Node *next;  
} Node;
 
#define insertAfterNode(newnode, T) _insertNode(newnode, T, T->next)
 
void AddPhoneBook(void)
{
Phonebook newpb;
Node *temp = NULL;

if(Head==NULL)    
     {
        temp=createNode(newpb);
         Head->next=temp;
         Head->prev=temp;
     }
    else
    {
        temp=createNode(newpb);
        insertAfterNode(temp, Head->next);
    }
}
cs

이중 환형 리스트는 이중 연결 리스트와 비슷하지만 차이점은 tail이 없다는 것입니다.


사용 예 : <재시도 페이지 교체>

-사용 가능한 페이지를 재할당하는 등의 페이지 할당/교체 방식

-Swap disk

-Page replacement algorithm

-메모리 공간의 제약으로 인해 동시에 모든 자료를 메모리에 올려 놓을 수가 없다.

(-> 빈번한 교체가 이루어져야 한다.)

-LRU페이지 교체 방식



'자료구조' 카테고리의 다른 글

[자료구조_Day5]biTree,bsTree  (0) 2018.11.06
[자료구조_Day4]Chained Hash Tables  (0) 2018.11.06
[자료구조_Day3]Stack  (0) 2018.11.06
[자료구조_Day3]Set  (0) 2018.11.06
[자료구조_Day1]Double Linked List  (0) 2018.10.28


■Double Linked List■

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
#ifndef DLIST_H
#define DLIST_H
 
#include <stdlib.h>
 
typedef struct DListElmt_ {
 
void               *data;
struct DListElmt_  *prev;
struct DListElmt_  *next;
 
} DListElmt;
 
 
typedef struct DList_ {
 
int                size;
 
int                (*match)(const void *key1, const void *key2);
void               (*destroy)(void *data);
 
DListElmt          *head;
DListElmt          *tail;
 
} DList;
cs
#Double Linked List는 Single Linked List와 비교하면 prev라는 포인터가 하나더 붙어 있으며 역방향으로의 순회가 가능하다.



대표적으로 insert를 구현하면서 이해를 해보면 delete,find등 다른 구현은 쉽게할 수있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void dlist_init(DList *list, void (*destroy)(void *data)) {
 
/*****************************************************************************
*                                                                            *
*  Initialize the list.                                                      *
*                                                                            *
*****************************************************************************/
 
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
 
return;
 
}

cs

List의 초기화 부분이며 head와 tail은 리스트의 첫과 끝을 가리키며 size는 할당된 노드의 수를 말한다.


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
int dlist_ins_next(DList *list, DListElmt *element, const void *data) {
{
DListElmt           *new_element;
    
    if ((new_element = (DListElmt *)malloc(sizeof(DListElmt))) == NULL)
   return -1;
    new_element->data = (void *)data;
    
    if (element == NULL) {
   if (dlist_size(list) == 0)
{
       list->head = new_element;
       list->head->prev = NULL;
       list->head->next = NULL;
       list->tail = new_element;
}
 
else 
{
    new_element->next=list->tail->next;
    list->tail->next=new_element;
    list->tail = new_element;
    list->tail->prev=list->head;
}
}
else {
      if (dlist_size(list) == 0)
{
       list->head = new_element;
       list->head->prev = NULL;
       list->head->next = NULL;
       list->tail = new_element;
}
 
else 
{
    new_element->next=element->next;
    element->next=new_element;
    element = new_element;
    new_element->prev=element;
}
    
}
list->size++;
return 0;
}
}
cs

1. 전달된 노드의 값이 NULL인지 존재하는지를 구분한다. (노드가 존재하면 그 노드를 기준으로 insert 한다.)
2. size가 0인지를 즉, List안에 처음으로 들어갈 노드인지 아닌지를 체크한다.
3.
  if (dlist_size(list) == 0)
{
       list->head = new_element;
       list->head->prev = NULL;
       list->head->next = NULL;
       list->tail = new_element;
}
size가 0, List안에 처음으로 들어갈 때의 노드를 A라고 하자, 하나 밖에 없으므로 head와 tail은 A_node를 가리키고,
A_node의 앞,뒤에는 아무것도 없으므로 NULL값을 넣어준다. 
list->head(list의 head=new_element head가 new_element를 가리킨다.)
list->head->prev = NULL(head가 가리키는 노드의 prev에 NULL을 넣는다.)
4.
else 
{
    new_element->next=list->tail->next;
    list->tail->next=new_element;
    list->tail = new_element;
    list->tail->prev=list->head;
}

기존에 A_node가 있을 때 B_node가 들어간다고 가정한다면

먼저  B_node의 next에 list->tail->next(즉, A_node의 next값을 넣어준다(현재 A_node의 next값은 NULL이다)

list->tail->next(A_node의 next)는 B_node를 가리킨다.

list->tail(List의 끝은)B_node를 가리키고

list->tail->prev(B_node의 prev)는 list->head(A_node)를 가리킨다.


*전달된 노드가 있을 시 list->tail를 element로 바꿔주면 되고 현재는 insert_next로 구현하였고 insert_prev로 구현할 수도 있다.

예) insert_next : insert- 1 2 3 4    insert된 node -4 3 2 1 


'자료구조' 카테고리의 다른 글

[자료구조_Day5]biTree,bsTree  (0) 2018.11.06
[자료구조_Day4]Chained Hash Tables  (0) 2018.11.06
[자료구조_Day3]Stack  (0) 2018.11.06
[자료구조_Day3]Set  (0) 2018.11.06
[자료구조_Day2]Double Circular Linked List  (0) 2018.10.28

■Volatile■

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
#include<stdio.h>
 
int main(void)
{
    volatile unsigned int i;
//  unsigned int i;
    for(i=0;i<0x10000000;i++);
    //Dead Code 
    
    /************************
    1.vlatile 없이 
    gcc -o test test.c
    ./test.c
    =>delay가 생김. 
    
    2. gcc -o test test.c -O3
    =>최적화(delay x)
    
    3.volatile 작성
    gcc -o test test.c -O3
    =>delay가 생김 
    **************************/ 
printf("\n");
printf("end...");
}
cs

<Volatile의 역할>
1.컴파일러의 최적화를 막아준다.
위 코드를 보면 dead code같은 코드를 보면 컴파일러가 최적화 레벨에 따라
생략해서 컴파일하게 된다.

2.캐시를 거치지 않는다.
임베디드에서 프로세서의 레지스터를 직접 제어하는 경우가 많은데 캐시에 저장되어 있으면
레지스터 제어가 잘 되지않기 때문에 써주는 것이 좋다.



■LED + keypad 회로도 (비트필드 구조체 사용)■

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "2450addr.h"
typedef struct    
{
    unsigned gpg0 : 2;
    unsigned gpg1 : 2;
    unsigned gpg2 : 2;
    unsigned gpg3 : 2;
    unsigned gpg4 : 2;
    unsigned gpg5 : 2;
    unsigned gpg6 : 2;
    unsigned gpg7 : 2;
 
}gpgcon_t;
typedef struct 
{
    unsigned gpg0 : 1;
    unsigned gpg1 : 1;
    unsigned gpg2 : 1;
    unsigned gpg3 : 1;
    unsigned gpg4 : 1;
    unsigned gpg5 : 1;
    unsigned gpg6 : 1;
    unsigned gpg7 : 1;
}gpgdat_t;
 
typedef struct 
{
    unsigned gpf0 : 2;
    unsigned gpf1 : 2;
    unsigned gpf2 : 2;
    unsigned gpf3 : 2;
    unsigned gpf4 : 2;
    unsigned gpf5 : 2;
    unsigned gpf6 : 2;
    unsigned gpf7 : 2;
}gpfcon_t;
typedef struct 
{
    unsigned gpf0 : 1;
    unsigned gpf1 : 1;
    unsigned gpf2 : 1;
    unsigned gpf3 : 1;
    unsigned gpf4 : 1;
    unsigned gpf5 : 1;
    unsigned gpf6 : 1;
    unsigned gpf7 : 1;
}gpfdat_t;
 
#define GPGCON  (*(volatile gpgcon_t *)0x56000060)
#define GPGDAT  (*(volatile gpgdat_t *)0x56000064)
#define GPFCON  (*(volatile gpfcon_t *)0x56000050)
#define GPFDAT  (*(volatile gpfdat_t *)0x56000054)
void LED_Port_Init(void);
void LED_ON_Off(int num);
int Get_Key_byPolling(void);
 
void Main()
{
    int key;
    LED_Port_Init();
    while(1)
    {
 
    GPGDAT.gpg0 = 0x1;
    GPFDAT.gpf7 = 0x0;
    key = Get_Key_byPolling();    
    LED_ON_Off(key);
 
    GPGDAT.gpg0 =0x0;
    GPFDAT.gpf7 = 0x1;
    key = Get_Key_byPolling();    
    LED_ON_Off(key+1);
 
    }
}
 
void LED_Port_Init() 
{    
    GPGCON.gpg0 = 0x1;
    GPGCON.gpg4 = 0x1;
    GPGCON.gpg5 = 0x1;
    GPGCON.gpg6 = 0x1;
    GPGCON.gpg7 = 0x1;
 
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    
    GPFCON.gpf2 = 0x0;
    GPFCON.gpf3 = 0x0;
    GPFCON.gpf4 = 0x0;
    GPFCON.gpf5 = 0x0;
    GPFCON.gpf6 = 0x0
    GPFCON.gpf7 = 0x1;
    
 
    GPFDAT.gpf0= 0x0;
    GPFDAT.gpf1= 0x0;
    GPFDAT.gpf2= 0x0;
    GPFDAT.gpf3= 0x0;
    GPFDAT.gpf4= 0x0;
    GPFDAT.gpf5= 0x0;
    GPFDAT.gpf6= 0x0;
    GPFDAT.gpf7= 0x0;
}
 
 
void LED_ON_Off(int num)
{
    switch(num)
    {
    case 0:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 1:
    GPGDAT.gpg4 = 0x0;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 2:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x0;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 3:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x0;
    GPGDAT.gpg7 = 0x1;
    break;
    case 4:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x0;
    break;
    case 5:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x0;
    GPGDAT.gpg7 = 0x0;
    break;
    case 6:
    GPGDAT.gpg4 = 0x0;
    GPGDAT.gpg5 = 0x0;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    }
}
 
int Get_Key_byPolling(void)
{        
    unsigned char key=(GPFDAT.gpf2)|(GPFDAT.gpf3<<1)|(GPFDAT.gpf4<<2)|(GPFDAT.gpf5<<3)|(GPFDAT.gpf6<<4);
    if(key==0x1e)     
        {return 1;}
    if(key==0x1d)
        {return 2;}
    if(key==0x1b)
        {return 3;}
    if(key==0x17)
        {return 4;}
    if(key==0xf)
        {return 5;}
}
cs


■CallBack 함수■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
void LibFunc(void (*pFunc(void))
{
    //...
    pFunc();
}
void MyEvent()
{
    Uart_Printf("call me..");
}
void User_Main()
{
    LibFunc(MyEvent);
}
cs
#CallBack 함수란 간단히 말하자면 LibFunc라는 CallBack 함수를 정해두고 거기서 함수를 불러서 사용하는 것입니다.

즉, Main에서는 LibFunc라는 CallBack함수만 사용하면 되는 것입니다.


리눅스 임베디드에서 CallBack은 중요한데 리눅스 커널을 디버깅 하는데 많은 시간이 필요하고 양도 방대합니다.

그래서 디버깅중에 모듈을 넣고 빼고 하는데에 CallBack을 사용합니다.


그래서 디바이스 드라이버를 형태(틀)만 짜서(CallBack함수를 이용해) User1든 User2든 자신만의 각각 필요한 기능을

구현해서 개발하기가 수월합니다.


CallBack함수에 대한 자세한 설명이 링크에 있어서 참고합니다.

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_QnA_etc&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=3059

LED + Keypad 회로도■

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
#include "2450addr.h"
#define GPGCON (*(volatile unsigned int *)0x56000060)
#define GPGDAT (*(volatile unsigned int *)0x56000064)
#define GPFCON (*(volatile unsigned int *)0x56000050)
#define GPFDAT (*(volatile unsigned int *)0x56000054)
void Init(void);
void LED_ON_Off(int num);
int Get_Key_byPolling(void);
 
void Main()
{
    int key;
    Init();
    
    while(1)
    {
    GPFDAT &= ~(0x1 <<7);
    GPGDAT |= 0x1;
    key = Get_Key_byPolling();    
    LED_ON_Off(key);
 
    GPFDAT |= (0x1 <<7);
    GPGDAT &= ~(0x1);
    key = Get_Key_byPolling();    
    LED_ON_Off(key+1);
    }
}
 
void Init() 
{    
 
    GPGCON |= 0x5500;
    GPGDAT |=0xf0;
    
    GPFCON |=0xffff;
    GPFCON &= ~(0x3ff << 4);
 
    GPFCON &= ~(0x2 <<14);
    GPGCON |= 0x1;
 
    GPFDAT &= ~(0xff);
}
 
 
void LED_ON_Off(int num)
{
    GPGDAT |=0xf0;
    switch(num)
    {
    case 0:
    GPGDAT &=(0xf0);
    break;
    case 1:
    GPGDAT &=(0xe0);
    break;
    case 2:
    GPGDAT &=(0xd0);
    break;
    case 3:
    GPGDAT &=(0xb0);
    break;
    case 4:
    GPGDAT &=(0x70);
    break;
    case 5:
    GPGDAT &= (0x30);
    break;
    case 6:
    GPGDAT &=0xc0;
    break;
    }
}
 
int Get_Key_byPolling(void)
{        
        if((GPFDAT & 0x7)==0x3)
        return 1;
        if((GPFDAT & 0xf)==0x7)
        return 2;
        if((GPFDAT & 0x1f)==0xf)
        return 3;
        if((GPFDAT & 0x3f)==0x1f)
        return 4;
        if((GPFDAT & 0x7f)==0x3f)
        return 5;    
}
cs
<스위치 작동원리>


스위치를 누르지 않은 상태일때는 스위치에 해당하는 핀의 전압이 VDD이므로 1(HIGH) 상태이다.


스위치를 누를경우 스위치에 해당하는 핀이 4~8번일경우 GPF7과, 9~13번일경우 GPG0 과 연결되는데,


GPF7, GPG0의 값이 0(LOW)이면, 연결된 핀의 전압이 0V가 되므로 0(LOW)상태가 된다.


GPFDAT7, GPGDAT0을 1(HIGH)상태로 둘경우 연결된 핀의 전압은 여전히 VDD이므로 핀의 상태는 HIGH(1)가 된다.



ex)

4번 스위치가 열린상태 : GPF2에 걸리는 전압이 VDD 이므로 1(HIGH)


4번스위치 닫힘, GPF7의 상태가 LOW : GPF2에 걸리는 전압이 0V 이므로 0(LOW)


4번스위치 닫힘, GPF7의 상태가 HIGH : GPF2에 걸리는 전압이 VDD 이므로 1(HIGH)



1. LED 설정


GPGCON4~GPGCON7 을 01(output mode) 로 초기화


GPGDAT의 4~7번 비트를 1(HIGH)로 초기화



2. keypad 설정


GPFCON2 ~ GPFCON6 을 00(input mode)로 초기화


GPFDAT의 2~6번 비트는 회로상 이미 1(HIGH)상태




GPFCON7, GPGCON0 을 00(output mode) 로 초기화


GPFDAT의 7번비트를 0으로 할 경우 4~8번 스위치가 작동


GPGDAT의 0번비트를 0으로 할 경우 9~13번 스위치가 작동




3. GPFDAT


회로상 GPFDAT의 2~6번비트는 기본상태가 1(HIGH)이다.


각 핀에 해당하는 스위치를 누를 경우 해당 비트가 0(LOW)가 된다.


ex)5번 스위치를 누를경우 GPFDAT의 3번비트만 0이 된다.



while문을 통해서 

GPFCON7, GPGCON0 을 01

GPFCON7, GPGCON0 을 10

인 상태에서 key값을 받아서


조건문을 통해 각 스위치에 맞게 LED를 설정한다.



#환경 설정


Ubuntu10 압출 풀기 -> 새로만들기 -> 이름 버전 입력(32bit linux)-> 메모리 4G -> 하드 디스크(기존 가상 하드 디스크 파일 사용)

-> virtualBox 실행


(Ubuntu)

장치 -> 게스트 확장 클릭 -> 바탕화면의 CD 더블클릭 ->autorun.sh 터미널에서 실행


(virtualBox)

virtualBox의 설정 ->네트워크 -> 브리지 어댑터 ->ASIX 설정

/*

이전에 드라이버가 설치 되어 있는지 확인(windows의 장치 관리자 확인)

*/

장치 ->공유 폴더 ->추가 ->(window 폴더 설정)->자동마운트,항상사용하기 선택


(Windows)

Tera Term 설치 -> Serial 클릭 -> setup Serial prot 115200으로 설정 

S3c2450 전원 키기


(Ubuntu)

# cd /etc/xinetd.d/

# gedit tftpd 


service tftp


{


protocol = udp


port = 69


socket_type = dgram


wait = yes


user = nobody


server = /usr/sbin/in.tftpd


server_args = /tftpboot


disable = no


}



# mkdir /tftpboot/

# chmod 777 /tftpboot/

# /etc/init.d/xinetd restart


 * Stopping internet superserver xinetd                                  [ OK ] 


 * Starting internet superserver xinetd                                  [ OK ]




# netstat -au


#halt =>종료

(reboot 할것)


(bootroad) =>보드의 reset 버튼 누르고 enter해서 진입(명령대기 상태)

/*

bootroad의 부팅은 2가지 1.자동부팅 2.명령대기 상태(프롬프트 상태)

*/


#printenv

#setenv serverip 192.168.10.107

#setenv ipaddr 192.168.10.117


#saveenv

/*

ip를 직접 잡아줍니다.

*/


(Ubuntu)

# ifconfig eth0 192.168.10.107 up

# ifconfig

# cd /media/sf_D_DRIVE/

# ls


MDS2450.bin ==>(윈도우의 공유파일에 직접 넣어준 파일)



# cp MDS2450.bin /tftpboot/

# chmod 777 /tftpboot/MDS2450.bin ‬ ==>Access violation오류시



(bootroad)

#tftp 30000000 MDS2450.bin //PC로 부터 다운로드

#go 30000000 //실행





led.zip와 arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2를 리눅스에 생성된 공유파일(sf_D_DRIVE)에 넣는다.


(Ubuntu)

#cd /media/sf_D_DRIVE

#cp led.zip /root


# cp arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 /root


#cdtar  /root


#tar xvjf arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2


/*


tar.bz2 ->xvjf


tar.bz  ->xvzf


*/


#cd /etc


#gedit environment



PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/root/arm-2011.03/bin"


/*

수정

*/




#source /etc/environment


#arm-none-eabi-gcc




#cd /root



#unzip led.zip


#cd led


#cd SOURCE




#ls -al

#gedit Main.c

/*

소스 입력

*/



#make clean


#make


/*

Makefile : 컴파일 자동화 유티리티

clean후 컴파일

*/


#cp MDS2450.bin /tftpboot



/*

tftp(file transfer protocol)를 통해 board에 보내어 board에서 실행한다


PC(host)/ TFTP server  || targetboard()/client

*/



(bootroad)




#tftp 30000000 MDS2450.bin

/*

다운로드

*/


#go 30000000





<Main.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
#include "2450addr.h"    //S3c2450의 모든 register주소가 들어있는 헤더파일
#define GPGCON (*(volatile unsigned int *)0x56000060)
#define GPGDAT (*(volatile unsigned int *)0x56000064)
 
void LED_Port_Init(void);
void LED_ON_Off(int num);
 
void Main()
{
    
    LED_Port_Init();
    while(1)
    {
        int i;
        LED_ON_Off(5);
        for(i=0; i<300000; i++);
        LED_ON_Off(6);
        for(i=0; i<300000; i++);
        LED_ON_Off(1);
        for(i=0; i<300000; i++);
        LED_ON_Off(2);
        for(i=0; i<300000; i++);
        LED_ON_Off(4);
        for(i=0; i<300000; i++);
        LED_ON_Off(3);
        for(i=0; i<300000; i++);
    }
}
void LED_Port_Init() 
{
    GPGDAT |= 0xf0;
    GPGCON |= 0x5500;
}
 
void LED_ON_Off(int num)
{    
    GPGDAT |= 0xf0;
    switch(num){
        case 1:
            GPGDAT &= (0xe0);
            break;
        case 2:
            GPGDAT &= (0xd0);
            break;
        case 3:
            GPGDAT &= (0xb0);
            break;
        case 4:
            GPGDAT &= (0x70);
            break;
        case 5:
            GPGDAT &= (0x30);
            break;
        case 6:
            GPGDAT &= (0xc0);
            break;
    }
}
 
cs





# 비트 set ,claer 연습

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
 
int main()
{
    unsigned char data1 = 0xad;
    unsigned char data2 = 'a';
    
    //B5로 만들기
    data1 &=~(0x7<<3); //3bit를 clear
    data1 |= 0x6 <<3;  //110 삽입
//clear를 하고 삽입한는 방식이 일반적
 
    //대문자 A로 만들기
    data2 ^= 0x1 <<5//a는 0x61,A는 0x41
                      //5번째 자리 반전 
    
    printf("%0x\n",data1);
    printf("%c\n",data2);
}
cs
<개념>

1.set

data = data | 0x20;    //data 5번 bit만 set
=> data = data | 0x1 << 5;
=> data |= 0x1 << 5;   (이런 표기법을 쓰도록 하자)

2.claer


data &= ~(0x1 <<5);


3.reverse


data ^= 0x1 <<5;



*응용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//값을 입력하여 신호등을 표시합니다.//
 
#include <stdio.h>
void main()
{
    int i;
    unsigned char sign;
    unsigned char data;
    char str[4][9]={"녹색불""자회전불""노란불""빨간불"};
    printf("값을 입력하세요(1, 2, 3, 4, 8) : ");
    scanf("%d"&sign);
    for(i=3;i>=0;i--)
    {
        data=(sign&(1<<i))>>i;
        printf("%s : ", str[i]);
        data==1 ? printf("on\n"): printf("off\n");
    }
}
cs


+ Recent posts