LuvSea

DDRA, PORTA를 찾아보자. 본문

sTudy

DDRA, PORTA를 찾아보자.

사랑海 2009. 8. 10. 15:18
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

DDRA, PORTA는 도대체 어디에 정의되어 있을까?
헤더파일에서 직접 찾아보자.

소스코드를 보면 <stdio.h>처럼 많이 사용하는 io함수들을 사용하기 위해 아래와 같이 include한다.

#include <avr/io.h>

따라서 io.h를 살펴보면,

#elif defined (__AVR_ATmega128__)
#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)

이렇게 정의된 부분이 있다.

따라서 PORTA = 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;
세문장은 모두 같은 문장이 된다.

그렇다면 _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;
는 모두 같은 문장이 된다.

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

조건은 호환모드인가 노멀모드인가를 판별하는 것이고
그에 따른 값을 정의한다. 따라서, 노멀모드이므로 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;

즉, 0x3B주소지에서 1바이트 공간에 0xFF를 쓰겠다는 뜻이다.

그렇다면 0x3B는 무엇인가.
이는 atmega128의 스펙을 살펴봐야한다.
스펙을 살펴보면, PORTA 레지스터와 연결되어있음을 알수있다.

즉 0x3B에 데이터를 쓰게 되면 PORTA 레지스터에 데이터를 쓰는 것과 같은 것이다.

이를 활용하여 헤더파일을 작성할 수 있다.


 
  1. /* test.h*/  
  2. //중복을 막는다.    
  3. #ifndef _TEST_H_   
  4. #define _TEST_H_   
  5.   
  6. #define DDRA (*(volatile unsigned char*) 0x3A)   
  7. #define DDRB (*(volatile unsigned char*) 0x37)   
  8. #define DDRC (*(volatile unsigned char*) 0x34)   
  9. #define DDRD (*(volatile unsigned char*) 0x31)   
  10. #define DDRE (*(volatile unsigned char*) 0x22)   
  11. #define DDRF (*(volatile unsigned char*) 0x61)   
  12. #define DDRG (*(volatile unsigned char*) 0x64)   
  13.   
  14. #define PORTA (*(volatile unsigned char*) 0x3B)   
  15. #define PORTB (*(volatile unsigned char*) 0x38)   
  16. #define PORTC (*(volatile unsigned char*) 0x35)   
  17. #define PORTD (*(volatile unsigned char*) 0x32)   
  18. #define PORTE (*(volatile unsigned char*) 0x23)   
  19. #define PORTF (*(volatile unsigned char*) 0x62)   
  20. #define PORTG (*(volatile unsigned char*) 0x65)   
  21.   
  22. #define PINA (*(volatile unsigned char*) 0x39)   
  23. #define PINB (*(volatile unsigned char*) 0x36)   
  24. #define PINC (*(volatile unsigned char*) 0x33)   
  25. #define PIND (*(volatile unsigned char*) 0x3B)   
  26. #define PINE (*(volatile unsigned char*) 0x21)   
  27. #define PINF (*(volatile unsigned char*) 0x20)   
  28. #define PING (*(volatile unsigned char*) 0x63)   
  29.   
  30. #endif  







    Source Insight 란 프로그램을 이용하면 더 편하게 추적할 수 있다
Comments