Notice
Recent Posts
Recent Comments
LuvSea
DDRA, PORTA를 찾아보자. 본문
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
DDRA, PORTA는 도대체 어디에 정의되어 있을까?
헤더파일에서 직접 찾아보자.
소스코드를 보면 <stdio.h>처럼 많이 사용하는 io함수들을 사용하기 위해 아래와 같이 include한다.
#include <avr/io.h>
따라서 io.h를 살펴보면,
#elif defined (__AVR_ATmega128__)
#include <avr/iom128.h>
#include <avr/iom128.h>
이라고 정의된 부분을 볼 수있다.
iom128.h를 찾아보자.(다른 MCU라면 해당 헤더파일을 찾으면 된다.)
imo128.h를 보면, (ctrl+f로 찾자)
/* Input Pins, Port A */
#define PINA _SFR_IO8(0x19)
/* Data Direction Register, Port A */
#define DDRA _SFR_IO8(0x1A)
/* Data Register, Port A */
#define PORTA _SFR_IO8(0x1B)
#define PINA _SFR_IO8(0x19)
/* Data Direction Register, Port A */
#define DDRA _SFR_IO8(0x1A)
/* Data Register, Port A */
#define PORTA _SFR_IO8(0x1B)
이렇게 정의된 부분이 있다.
따라서 PORTA = 0xFF 라는 문장은,
_SFR_IO8(0x1B) = 0xFF 라고도 쓸수있다.
_SFR_IO8(0x1B) = 0xFF 라고도 쓸수있다.
그렇다면, _SFR_IO8는 무엇일까.
아까 io.h를 다시 살펴보면,
#include <avr/sfr_defs.h> 라고 된 부분이 있다.
특수기능 레지스터에 대한 헤더파일인데, 이것을 열어보자.
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
이라고 된 부분을 보자.
이것은 매크로 함수인데, 뒷부분의 _MMIO...부분을 수행하는 것이다.
따라서,
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
세문장은 모두 같은 문장이 된다.
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
세문장은 모두 같은 문장이 된다.
그렇다면 _MMIO_BYTE와 __SFR_OFFSET는 무엇일까.
sfr_defs.h에서 _MMIO_BYTE를 다시 찾아보면,
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
라고 정의된 부분을 찾을 수 있다.
따라서,
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
(*(volatile uint8_t *)((0x1B) + __SFR_OFFSET)) = 0xFF;
는 모두 같은 문장이 된다.
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
(*(volatile uint8_t *)((0x1B) + __SFR_OFFSET)) = 0xFF;
는 모두 같은 문장이 된다.
volatile에 대해서는 여기를 참조하도록하자. <volatile 한정자 보기>
uint8_t는 unsigned 타입의 정수형(int) 8bit의 타입이라는 것이다.(이 부분이 정의된 부분은 아직 못찾았다.)
즉, unsigned char의 포인터형이란 뜻이고, 괄호가 되있으므로 캐스팅(형변환)을 하겠다는 뜻이다.
__SFR_OFFSET을 찾아보자.
마찬가지로 sfr_defs.h에 정의되어있다.
#ifndef __SFR_OFFSET
/* Define as 0 before including this file for compatibility with old asm
sources that don't subtract __SFR_OFFSET from symbolic I/O addresses. */
# if __AVR_ARCH__ >= 100
# define __SFR_OFFSET 0x00
# else
# define __SFR_OFFSET 0x20
# endif
#endif
/* Define as 0 before including this file for compatibility with old asm
sources that don't subtract __SFR_OFFSET from symbolic I/O addresses. */
# if __AVR_ARCH__ >= 100
# define __SFR_OFFSET 0x00
# else
# define __SFR_OFFSET 0x20
# endif
#endif
조건은 호환모드인가 노멀모드인가를 판별하는 것이고
그에 따른 값을 정의한다. 따라서, 노멀모드이므로 0x20이 된다.
따라서,
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
(*(volatile uint8_t *)((0x1B) + __SFR_OFFSET)) = 0xFF;
(*(volatile uint8_t *)((0x1B) + 0x20)) = 0xFF;
(*(volatile uint8_t *)0x3B) = 0xFF;
PORTA = 0xFF;
_SFR_IO8(0x1B) = 0xFF;
_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xFF;
(*(volatile uint8_t *)((0x1B) + __SFR_OFFSET)) = 0xFF;
(*(volatile uint8_t *)((0x1B) + 0x20)) = 0xFF;
(*(volatile uint8_t *)0x3B) = 0xFF;
즉, 0x3B주소지에서 1바이트 공간에 0xFF를 쓰겠다는 뜻이다.
그렇다면 0x3B는 무엇인가.
이는 atmega128의 스펙을 살펴봐야한다.
스펙을 살펴보면, PORTA 레지스터와 연결되어있음을 알수있다.
즉 0x3B에 데이터를 쓰게 되면 PORTA 레지스터에 데이터를 쓰는 것과 같은 것이다.
이를 활용하여 헤더파일을 작성할 수 있다.
- /* test.h*/
- //중복을 막는다.
- #ifndef _TEST_H_
- #define _TEST_H_
- #define DDRA (*(volatile unsigned char*) 0x3A)
- #define DDRB (*(volatile unsigned char*) 0x37)
- #define DDRC (*(volatile unsigned char*) 0x34)
- #define DDRD (*(volatile unsigned char*) 0x31)
- #define DDRE (*(volatile unsigned char*) 0x22)
- #define DDRF (*(volatile unsigned char*) 0x61)
- #define DDRG (*(volatile unsigned char*) 0x64)
- #define PORTA (*(volatile unsigned char*) 0x3B)
- #define PORTB (*(volatile unsigned char*) 0x38)
- #define PORTC (*(volatile unsigned char*) 0x35)
- #define PORTD (*(volatile unsigned char*) 0x32)
- #define PORTE (*(volatile unsigned char*) 0x23)
- #define PORTF (*(volatile unsigned char*) 0x62)
- #define PORTG (*(volatile unsigned char*) 0x65)
- #define PINA (*(volatile unsigned char*) 0x39)
- #define PINB (*(volatile unsigned char*) 0x36)
- #define PINC (*(volatile unsigned char*) 0x33)
- #define PIND (*(volatile unsigned char*) 0x3B)
- #define PINE (*(volatile unsigned char*) 0x21)
- #define PINF (*(volatile unsigned char*) 0x20)
- #define PING (*(volatile unsigned char*) 0x63)
- #endif
Source Insight 란 프로그램을 이용하면 더 편하게 추적할 수 있다
'sTudy' 카테고리의 다른 글
ATmega128은 Little endian일까 Big endian일까?? (0) | 2009.08.10 |
---|---|
Volatile 한정자 (0) | 2009.08.10 |
부호 확장(Sign extension) (0) | 2009.08.10 |
[C언어] 구조체의 메모리 저장방식과 #pragma pack (5) | 2009.08.10 |
C++ 연산자 오버로딩 (0) | 2009.08.10 |
Comments