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

2014년 4월 11일 업무일지 -김용우 [출석번호 6번]

by 알 수 없는 사용자 2014. 4. 11.
728x90
반응형

 

※Data Sheet 살펴보기

PDF 파일에 Chip의 기능등과 관련되 정보를 볼 수 있다.


Features(특징)

High-performance, Low-power Atmel® AVR® 8-bit Microcontroller

• 높은 성능, 낮은 전력 아트멜 ® AVR ® 8-비트 마이크로컨트롤러

 

Advanced RISC Architecture

• 고급 RISC 아키텍처

 

133 Powerful Instructions – Most Single Clock Cycle Execution

-133 강력한 지침-가장 단일 클럭 사이클 실행

 

32 × 8 General Purpose Working Registers + Peripheral Control Registers

- 8bit General Purpose Working 레지스터(32개 있다는 의미) 와  + 주변 기기 제어 레지스터(정확한 갯수가 나와있지 않다.

 

Fully Static Operation

-완전히 정적 작업

 

Up to 16MHz Throughput at 16MIPS

-16까지 갖추고 MHz 처리량 16 MIPS

 

On-chip 2-cycle Multiplier

-온-칩 2 사이클 승수

 

High Endurance Non-volatile Memory segments

• 높은 내구성 비휘발성 메모리 세그먼트

 

128Kbytes of In-System Self-programmable Flash program memory

- 시스템안에 혼자서 프로그램할수 있는 128 Kbytes 플래시 프로그램 메모리가 있다.

 

4Kbytes EEPROM

-4Kbytes EEPROM

 

4Kbytes Internal SRAM

-4Kbytes 내부 SRAM

 

Write/Erase cycles: 10,000 Flash/100,000 EEPROM

-쓰기/삭제 사이클: 10000만번 플래시/100000만번 EEPROM →플래시메모리보다 10배정도 빠르지만 비싸다.

 

Data retention: 20 years at 85°C/100 years at 25°C(1)

-데이터 보존: 85 ° 에서20년(프로그램을 한번실행시키면 최소 20년을 보장한다.)/25 °에서100 년

 

Optional Boot Code Section with Independent Lock Bits

-독립적인 잠금 비트와 선택적 부팅 코드 섹션

 

In-System Programming by On-chip Boot Program

온 칩 부팅 프로그램에 의해 시스템 프로그래밍

 

True Read-While-Write Operation

쓰기 작업 동안 진정한 읽기

 

Up to 64 Kbytes Optional External Memory Space

-64 Kbytes 선택적 외부 메모리 공간 → 64Kbytes를 추가로 사서 붙일수 있다.


※참고사항 64 x 1024 = 65536개 

65536-1 = (16진수로)FFFF = (2진수) 1111 1111 1111 1111 은 16bit

따라서 추가적으로 붙일수 있는 것은 16 bit 버스에마 사용할 있기 때문이다.

 

Programming Lock for Software Security

-프로그램을 집어넣고 Lock을 걸 수 있는데 그럼 다시 꺼낼 수 없다.

실제 AVR Studio로 읽기를 실행하면 안에 넣은 Hex실행파일을 다시 불러와서 사용할 수 있다.

교육용으로는 필요없을지 모르지만 Chip을 판매하려는 목적에서는 회사의 기술이 담긴 프로그램을 다른사람들에게 보여주지 않게 하기 위한 기능이라고 보면된다.

 

SPI Interface for In-System Programming

-시스템 프로그래밍에 대한 SPI 인터페이스

 

JTAG (IEEE std. 1149.1 Compliant) Interface

• JTAG (표준 IEEE 1149.1 규격)

 

Boundary-scan Capabilities According to the JTAG Standard

-JTAG 표준 경계 스캔 기능

 

Extensive On-chip Debug Support

-광범위 한 온칩 디버그 지원

 

Programming of Flash, EEPROM, Fuses and Lock Bits through the JTAG Interface

-플래시, EEPROM, 퓨즈 및 JTAG 인터페이스를 통해 잠금 비트 프로그래밍

 

Peripheral Features

• 주변 기능.

메모리 내에 있는 MCU안에 있는 Core의 주변에 있는 장치를 말하는 것이다.

 

Two 8-bit Timer/Counters with Separate Prescalers and Compare Modes

-2개의 8 비트 타이머/카운터,  프리와 비교 모드.

 

Two Expanded 16-bit Timer/Counters with Separate Prescaler, Compare Mode and Capture Mode

-두 개의 별도 프리 스케일 러, 비교 모드와 캡쳐 모드에서 16 비트 타이머/카운터 확장.

 

 

Real Time Counter with Separate Oscillator

-별도 발진기에 의한 실시간으로 카운터.

 

Two 8-bit PWM Channels

-두 개의 8 비트 PWM 채널.

 

6 PWM Channels with Programmable Resolution from 2 to 16 Bits

- 2에서 16 비트 분해능의 프로그래밍 가능한 PWM  6채널.

( 위에 8 bit PWM 2개와 16 bit PWM 6개 총 8개 있다)

 

Output Compare Modulator

-출력 비교 변조기입니다.

 

8-channel, 10-bit ADC

-8 채널, 10 비트 ADC. (채널은 다리수를 의미한다 chip에 빠져나와있는 다리 8개를 의미)

(10 bit ADC 8개 있다는 의미)

 

8 Single-ended Channels

8개 싱글 엔드 채널.

 

7 Differential Channels

7개 차동 채널.

 

2 Differential Channels with Programmable Gain at 1x, 10x, or 200x

증폭 1배, 10배, 200배 프로그램 가능한 2개의 차동 채널

 

Byte-oriented Two-wire Serial Interface

-바이트-지향 2-wire 직렬 인터페이스.

 

 

 

Dual Programmable Serial USARTs

-이중 프로그래밍 가능한 직렬 Usarts.

 

Master/Slave SPI Serial Interface

-마스터/슬레이브 SPI 직렬 인터페이스.

 

Programmable Watchdog Timer with On-chip Oscillator

- 온 칩 발진기 프로그래밍 가능한 워치독 타이머.

(watchdog Timer - 집지키는 개 즉 타이머의 기능을 하고 있다. 임베디드시스템이 열약한 환경이다. 늘 chip에 문제가 생기면 그때마다 고쳐줄 수 없기 때문에 chip에 오류가 걸리거나 에러가 발생해서 작동이 되지 않을때 Timer를 발동시켜서 일정시간이 지나면 Reset을 시켜버리는 기능을 가지고 있다.

☆참고로 watchdog는 reset기능을 가지고 있어서 일반적인 CPU및 제어장치들과 떨어져서 별도로 분류 해두었다.)

 

On-chip Analog Comparator

- 내장 아날로그 비교기.

 

Special Microcontroller Features

• 특별한 마이크로컨트롤러 기능.

 

Power-on Reset and Programmable Brown-out Detection

-파워 온 리셋 및 프로그래밍 가능한 브라운 아웃 검출.

Brown-out Detection은 일정적으로 지정한 전압의 기준을 걸어두어서 Reset을 시키는 프로그램이다.

이는 실제로 낮은 전압이들어가면 프로그램이 작동을 안하는 것이아니라 오작동의 요인이 되기 때문에 사용되는 기능이다.

 

Internal Calibrated RC Oscillator

-내부 보정된 RC 발진기입니다.

       오실레이터 = 수정진동자 (수정으로 만들어진 진동자라고 해서 수정진동자라고도 한다.)

External and Internal Interrupt Sources

-외부 및 내부 인터럽트 소스.

 

Six Sleep Modes: Idle, ADC Noise Reduction, Power-save, Power-down, Standby and Extended Standby

-6 Sleep Modes: 유휴, ADC 잡음 감소, 절전, 파워 다운, 대기 및 확장 대기

 

Software Selectable Clock Frequency

-소프트웨어 선택 가능한 클록 주파수.

  IBM 호환모드 

  128 보유모드

 

ATmega103 Compatibility Mode Selected by a Fuse

-ATmega103 호환성 모드 퓨즈 선정입니다.

 

Global Pull-up Disable

-글로벌 풀업 비활성화 합니다.

 

I/O and Packages

• I/O 및 패키지입니다.

 

53 Programmable I/O Lines

-53 프로그래밍 가능 I/O 라인입니다.

 

64-lead TQFP and 64-pad QFN/MLF

-64-리드 TQFP 및 64 패드 QFN/MLF.

  리드는 다리가 있는 것이고

  패드는 다리가 잘려있는 것을 의미한다.

 

Operating Voltages(운영 전압)

– 2.7V - 5.5V

Speed Grades(속도 등급)

– 0 - 16MHz


▶두번째 Page인 ATMEGA 메인 Chip에 관한 정보이다. 보드판 사진과 연결해서 보면 된다.



 

본문보기☞클릭

 

 

※ATMEGA 실습 - LED켜기

먼저 실습에 들어가기에 앞서서 기본적인 구동에 관한 Port에 대한 이해를 해보도록 하겠다.


▶먼저 일단 LED 기판과 ATMega MCU기판을 연결해보자.

일반적으로 Port 는 특수 Port를 제외하고 어떤 것을 사용해도 상관없다. 다만 연결되 Port의 정확한 주소값을 아는 것이 중요하다. 이는 데이터시트를 통해서 나중에 확인 하는 방법에 대해서 설명할 것이다.


☆아래의 그림은 회로도로 연결되어 있음을 확인 할 수 있다.

▶그럼 이제 본격적으로 Port에 연결되 MCU기판의 내부칩에서 어떤식으로 구동이 되는지 아래의 그림을 통해서 알아보도록 하자.

아래는 Port F를 기준으로 설명을 하고 있다. 일단 아래는 구조도라고 보면 되는데 점선을 기점으로 외부와 내부로 나뉘어 진다. 우리가 MCU기판을 보면 단순히 소켓만 볼 수 있지만 내부는 아래와같은 장치들로 구성이되어있으며 실제로 우리는 내부의 장치까지 건드려야지만 우리가 원하는 구동을 할 수 있다.


잘살펴보면 소켓과 바로 연결되어있는 부분을 보면 PORT F의 DRIVERS장치가 있는 것을 확일 할 수 있다. 기본적으로 Driver에 대해서 배웠지만 내부적인 장치들을 제어하고 관리하는 부분이다.

그리고 아래쪽을 더 살펴보면 Data Register와 Direction Register를 확일 할 수 있다.

여기서 이 두가지가 중요하다. 

Data RegisterPort를 통해서 입력되는 데이터를 확인하고 값을 저장하고 있는 것이다. ALU에 있는 프로그램을 통해서 해당 Data Register의 번지에 있는 데이터를 읽으며 Port Driver의 데이터상태(High인지 Low인지)를 알 수 있게 되는 것이다. 만일 출력일때는 Data Register의 번지의 값이 High인지 Low인지 판단하고 값을 주었는지 주지않았는지를 알 수 있다.

Direction Register는 아래의 도면에 화살표를 보면 단방향 즉 일방향이다. 이는 이름에서 알 수 있듯이 방향을 지정해주는 레지스터이다.

여기서 방향을 지정해준다는 것은 Port Driver의 소켓에연결된 양방향 Port가 입력값을 받는 것인지 출력값을 받는 것인지 결정을 해주는 역할을 한다. 이는 매우 중요한 부분이다. 위에서 MCU기판과 LED기판을 연결 했을 때 Port A의 첫번째 소켓에 연결을 하였다면 이 소켓이 현재 출력을 하는 소켓으로 지정을 하고자 한다. 그러면 Direction Register의 첫번째값을 1 즉 High로 둔어야지 출력을 하는 소켓으로 바뀐다고 볼 수 있다.(출력은 High = 1 , 입력은 Low = 0)


설명이 조금 어려울 수 도 있는데 실습을 통해서 이해를 해보도록 하자.


▶다시 LED를 연결하는 부분으로 돌아와서 LED의 불을 키고자 한다면 각각 LED기판과 MCU기판에 연결된 Port A의 주소를 알아야 한다고 설명했다. 

이전에 데이타 시트를 보면 Register Summary라는 부분이 있다.(p367) 여기서 우리가 알고자하는 주소값을 알아서 C언어로 프로그램을 작성할때 해당 주소를 통해 값을 전달하고 출력해주는 것이다.

아래에 파란색 네모와 빨간색 네모가 있는데 각각 호환모드 주소 고유모드 주소라고한다. 비슷한 기능을하지만 서로 다른 의미를 가지고 있다. 우리는 여기서 빨간색 네모로 쌓여있는 (괄호안에 있는) 고유 모드 주소가 필요하다.


▷아래의 그림은 우리가 연결한 Port A의 주소값이다. 참고로 ATMEL 사에서는 16진수라는 의미로 $달러 표시를 한다.

그리고 Port A의 주소 밑에 DDRA라고 있는 것을 확일 할 수 있다. 이는 Data Direction Register주소이다. 위에서 DDR을 알아볼때 해당 주소의 값으로 방향 즉 입력이나 출력 둘중하나를 선택한다고 했다. 그러니 이두개의 주소를 기억하고 넘어가야한다. 

▶해당 주소값을 알았다면 각각의 Port A에 대해서 본격적으로 알아보자. 다른 Port들도 마찬가지 겠지만 기본적으로 앞에서 배운 Port에대한 Data Register가 있고 DDR(Data Direction Register)등이 있다 우리가 Register Description에서 알아보아야 할 부분은 각각의 레지스터의 Port에 있는 읽고 쓰기 기능과 각 포트의 초기값에 대해서 알고 있어야한다.

  • Read/Write (읽기 / 쓰기) - 각 포트별로 읽고 쓰기기능을 표기해주며 Read기능은 대부분 가능하지만 간혹 Write기능이 없는 부분이 있다. 쉽게 앞글자를 따서 표기 되어있기 때문에 알고자하는 부분의 기능이 어떤게 있는지 표기되어있는 정보를 통해서 알 수 있다.

  • Initial Value(초기값) - 기본적으로 각부분의 초기값은 0 (Low)이다. 하지만 읽기만 가능한 부분인 경우 N/A로 값자체가 없는 것을 확인 할 수 있다.

 

이제 어느정도 Data sheet를 통해서 알 수 있는 정보는 습득하였다. 이러한 정보를 바탕으로 C언어로 소스코드를 작성하면서 우리가 배운 부분을 다시한번 되새겨 보자.

 

int main()

{

*((volatile unsigned char *)0x3A) = 0x01

// DDRA = 0x01 을 넣었다는 의미이다. 

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

// Port A = 0x01 을 넣었다는 의미이며 5v입력한다.

while(1); //프로그램이 종료되는 것을 막는다.

return 0;

}

 

▷처음부터 차근차근 알아보도록 하자

*((volatile unsigned char *)0x3A) = 0x01

첫줄을 살펴보면 0x3= 0x01 위의 정보에서 살펴 봤듯이 DDRA의 주소값(0x3A == $3A)에 16진수로 1을 입력하는 것이다. 하지만 C언어를 배워서 알겠지만 그냥 상수값을 두면 컴파일러가 주소값으로 인지하지 못한다. 따라서 캐스팅을 해주는 것이다.

★캐스팅 부분 참고 사항

  • 8 bit CPU이기 때문에 주소값도 8bit (8 bit는 1 byte == char형)로 해준다.

  • 그리고 주소값에는 음수가 없기 때문에 unsigned를 붙여준다.

  • Volatile[각주:1]은 휘발성을 띈다는 뜻이며 최적화[각주:2] 하지 말고 우리가 원하는 위치에 바로바로 적용시켜달라는 뜻이다.

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

두번째 줄도 마찬가지이다. 0x3B가 의미하는 것이 PortA를 의미하는 것이다.

 

소스코드에 대한 설명은 아주 간단하게 끝이났다. 소스를 컴파일해서 작동을 해보아도 아주 정상적으로 작동될 것이다. 하지만 여기서 의문점이 하나 생길것이다. 그것은 바로 Port의 주소값이다.

현재는 Port를 첫번째 0번 Port에 입력되어있지만 그 값을 2번이나 3번으로 바꾼다면 어떤식으로 수정해야지 LED의 불을 켤 수 있을까? 이다.

사실 주소값이라고 하긴 그렇지만 위의 ATMEGA는 8 bit의 구조로 되어있다. 그리고 Port도 8개이다. 이를 생각해보면 조금은 감을 잡을 수 있을지 모른다.

바로 Port의 입력값을 0000 0000으로 본다면 일곱번째의 Port자리에 선을 연결하였다고 하면, 위의 2진수자리에서 7번째(Port는 오른쪽부터 순서대로 올라간다.) 1이라는 값이 들어가면 되는 것이다. 그러면 2진수로 0100 0000 이며 16진수로 0x40을 의미한다. 그럼 PortA의 7번째에 선을 연결하였다면 아래와 같이 입력을 해주면 되는 것이다. 물론 DDR의 값도 같은 Port라인에 출력하는 값인 High 즉 1로 바꾸어주어야한다.

*((volatile unsigned char *)0x3A= 0x40;


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

 

 

▶아래의 그림은 정상적으로 불빛이 들어오는 LED를 볼 수 있을 것이다.


 

※추가로 LED를 깜박거리게 하는 소스코드를 작성해보자.

▶ 컴퓨터의 연산속도는 굉장히 빠르다. 따라서 단순히 0과 1의 값을 준다면 굉장히 빠른 속도로 연산을 하기때문에 LED의 불이 꺼지기도전에 다시 전압이 흘러서 계속해서 불이 켜져있는 것처럼 보일 것이다.

그래서 다음소스와 같이 딜레이 값을 주면 쉽게 해결할 수 있다.

int main()

{
    volatile unsigned int uiCnt;

    *((volatile unsigned char *)0x3A) = 0x01


    while(1)
    {

        for(uiCnt = 0;65000>uiCnt;uiCnt++);



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



for(uiCnt = 0;65000>uiCnt;uiCnt++);



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

}

return 0;
}





 

 

▶ 추가로 기본적으로 ATMEGA는 8 bit이기 때문에 Port또한 8개로 구성되어있다. 하지만 아래의 Port G같은 경우 8개가 아닌 5개이다. 이는 ATMEGA 내의 특수 기능을 가진 Port를 의미한다. 그리고 언더바로 체크되어있는 Port같은경우 기본적으로 정상적으로 프로그램이 작동하며 전압이 흐를때는 작동되지 않다가 전압이 끈기는등의 반응이 일어나면 작동하는 Port라고 볼 수 있다. 자세한건 다음에 설명하기로하겠다.



본문보기☞클릭

 

 


 

※이번에는 함수로의 구조체를 변수로 전달하고 반환하는 것을 알아보자.

▶제목이 어떻게보면 복잡하다고 생각할 수 있는데 간단히 말해서 함수를 만들면 매개변수에 인자값을 전달할때 구조체를 통채로 넘겨버리고 반환하는 것도 마찬가지로 구조체를 통째로 반환하는 것이다.

일단 아래의 소스코드를 보면서 자세히 알아보자.

#include <stdio.h>

typedef struct point
{
  int xpos;
  int ypos;
}Point;

void ShowPosition(Point pos);
Point GetCurrentPosition(void);

int main()
{
  Point curPos = GetCurrentPosition();
  ShowPosition(curPos);

  return 0;
}

void ShowPosition(Point pos)
{
  printf("[%d, %d] \n", pos.xpos,pos.ypos);
}

Point GetCurrentPosition(void)
{
  Point cen;
  printf("Input Current pos: ");
  scanf("%d %d"&cen.xpos, &cen.ypos);
  return cen;
}


▷소스코드를 살펴보면 구조체타입형을 ShowPosition 함수에서는 그대로 매개변수로 선언해서 받아오고 있음을 알 수 있다.

마찬가지로  GetCurrentPosition함수에서는 구조체를 통째로 반환하고 있다. 

그렇게 어려운 내용이 아니므로 이러한 구조체의 방법에 대해서 정확하게 기억하고 넘어가도록 하자.

 


 

▶기본 자료형 변수를 대상으로는 사칙연산이나 비교연산 등이 가능하다. 그렇다면 구조체를 대상으로는 어떠한 연산이 가능한지 알아보자.

사실 알아보자고 했지만 C언어에서는 구조체를 대상으로 연산에 대한 부분이 많이 제약적이다. 일반 변수는 거의 대부분이 가능하지만 구조체는 다음과 같은 연산만 가능하다.

  • 대입연산 ( = )

  • 주소값 반환을 목적으로 하는 & 연산.

  • 구조체 변수의 크기를 반환하는 sizeof 연산.

위와같은 세가지의 연산만 허용한다.

이러한 부분은 구조체를 정의할때 대충은 감을 잡았을 것이라고 생각한다. 구조체로 정의된 내부의 타입이 배열일 수 도 있고 저장된 타입의 갯수또한 다를 수 있기 때문에 사칙연산이나 비교연산을 하기는 상당히 까다로울 것이다.
(물론 C++에서는 가능하다.)

그럼 위의 대입연산과 sizeof연산의 소스코드를 한번 확인하고 넘어가도록 하자.


#include <stdio.h>

typedef struct point
{
  int xpos;
  int ypos;
}Point;

int main()
{

  Point pos1 = {1,2};
  Point pos2;
  pos2 = pos1;    // pos1의 멤버 대 pos2의 멤버간 복사가 진행됨

  printf("크기 : %d \n"sizeof(pos1));
  printf("[%d , %d] \n", pos1.xpos, pos1.ypos);
  printf("크기 : %d \n"sizeof(pos2));
  printf("[%d , %d] \n", pos2.xpos, pos2.ypos);


  return 0;

}



▷매우 간단한 소스코드이기 때문에 어렵지 않을 것이다. 그렇다면 위에서 사칙연산이 불가능하다고 했는데 정말 가능하지 않을까???

다음과 같은 방법으로 한다면 가능하다.

#include <stdio.h>

typedef struct point
{
  int xpos;
  int ypos;
}Point;

Point MinPoint(Point pos1, Point pos2);
Point AddPoint(Point pos1, Point pos2);

int main()
{
  Point pos1={5,6};
  Point pos2={2,9};
  Point result;

  result = AddPoint(pos1,pos2);
  printf("[%d, %d] \n", result.xpos, result.ypos);
  result = MinPoint(pos1,pos2);
  printf("[%d, %d] \n", result.xpos, result.ypos);


  return 0;
}

Point AddPoint(Point pos1, Point pos2)
{
  Point pos = {pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos};
  return pos;
}

Point MinPoint(Point pos1, Point pos2)
{
  Point pos = {pos1.xpos - pos2.xpos, pos1.ypos - pos2.ypos};
  return pos;
}



▷위의 방법은 함수를 이용한 방법이다. 함수를 이용해서 구조체의 내용을 각각 구조체 멤버들끼리 값을 더하거나 빼준다음에 그 구조체를 반환하여 result구조체에다가 넣어준뒤 결과 값을 출력하는 방법이다.



▶이번에는 구조체의 중첩된 형태로 사용하는 방법을 알아보도록 하자. 

→배열이나 포인터 변수가 구조체의 멤버로 선언될 수 있듯이 구조체의 변수도 구조체의 멤버로 선언될 수 가 있다.

이런한 형태를 '구조체의 중첩' 이라고 한다. 그럼 다음 내용을 보면서 확인해보자. 그렇게 어렵지 않은 내용임을 알 수 있을 것이다.

#include <stdio.h>


typedef struct point
{
  int xpos;
  int ypos
}Point;

Point MinPoint(Point pos1, Point pos2);
Point AddPoint(Point pos1, Point pos2);

int main()
{
  Point pos1={5,6};
  Point pos2={2,9};
  Point result;

  result = AddPoint(pos1,pos2);
  printf("[%d, %d] \n", result.xpos, result.ypos);
  result = MinPoint(pos1,pos2);
  printf("[%d, %d] \n", result.xpos, result.ypos);


  return 0;
}

Point AddPoint(Point pos1, Point pos2)
{
  Point pos = pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos};
  return pos;
}

Point MinPoint(Point pos1, Point pos2)
{
  Point pos = pos1.xpos - pos2.xpos, pos1.ypos - pos2.ypos};
  return pos;
}


▷여기서 Point 구조체 타입circle구조체에서 변수로 정의하였는 것을 볼 수 있다.

그리고 main함수에서 Circle로 정의된 c1의 구조체안에 값을 입력하는 모습을 볼 수 있다. 여기서 중괄호를 이용해서 구조체멤버의 초기화를 구분지을 수 있이서 이와 같이 표현을 하였다. 중괄호를 사용하지 않는다면 앞에서부터 순서대로 입력되는 식으로 그값이 들어갈 것이다.

그리고 배열과 마찬가지로 값이 입력되지 않을 경우에는 0으로 초기화가 되어서 입력이 될 것이다.



▶마지막으로 구조체는 아니지만 구조체와 비슷한 형태의 Union Type에 대해서 알아보고 마무리 짓도록 하겠다.

Union은 구조체와 비교해서 보면 아주 이해하기가 쉽다. 

선언할때 차이점은 단순히 union으로 하느냐 struct로 하느냐의 차이지만 실제 메모리의 저장방식에서 조금 차이가 있다. 

일단 소스코드를 보면서 설명하도록 하겠다.

#include <stdio.h>

typedef union smart
{
  int A;
  short B;
  char C;

}Smart;

int main()
{
  Smart test;
  test.A = 0x12345678;
  printf("%08X \n",test.A);
  printf("%08X \n",test.B);
  printf("%08X \n\n",test.C);

  test.B = 0xAAAA;
  test.C = 0xFF;
  printf("%08X \n",test.A);
  printf("%08X \n",test.B);
  printf("%08X \n",test.C);
  return 0;

}



▷위의 소스코드를 확인해보면 출력 결과물이 이상하다고 느껴질 것이다. 이러한 이유는 기본적으로 struct의 구조체 메모리 저장방법을 기억할 것이다. 각각의 메모리저장위치를 따로잡으면서 저장되는 구조체와는 달리

union은 메모리의 저장구조가 가장 큰 공간을 차지하는 type을 기준으로 그안에 작은 type의 구조들이 하나씩 자리를 잡는 형식이다.

아래의 그림을 보면 좀 더 이해하기가 쉽다.

그렇다면 위에서 2번째 출력부분에서 B와 C의 값에 각각 AAAA와 FF를 출력했는데

왜?? B의 값은 FF FF AA FF가 나오고 C의 값은 FF FF FF FF가 나오는 것일까??

그것은 AA FF 를 2진수로 바꿔보면 1010 1010 1111 1111 즉 컴퓨터가 입력받기로는 음수값으로 입력을 받은 것으로 되어버린다. 따라서 32bit 컴퓨터의 특성상 남은 앞의 자리는 1로 체워지게되면서 앞의 값들이 F로 가득 체워지는 것이다.

 

본문보기☞클릭

 

오늘 공부하신다고 고생많으셨습니다. 틀린거 지적해주세요~

(개인블로그 글도 작성할겸 하다보니 반말로 적혀있습니다. 기분나쁘셔두 참고봐주세요 ;;)

주말 잘보내십시오~~ 다들 파이팅입니다^^



  1. ★참고사항 : 반드시 CPU와 센서에 접근하는 변수는 volatile을 붙여야한다. 그렇지 않으면 캐시메모리에 저장된 옛날 값을 불러오는 경우가있기 때문이다. [본문으로]
  2. ★최적화란? 캐시메모리에서 왔다갔다 하면서 데이터를 보류하여 최종적인것만 저장하는 것을 의미한다. [본문으로]
728x90