전자회로실험

Atmega128

Atmega128 칩은 설정에 따라 변경 가능한 8비트 I/O포트 6개(Port A~F)와 5비트 I/O 포트 1개(Port G)를 가지고 있다. 즉 설정에 따라 출력으로 혹은 입력으로 사용할 수 있는 I/O 라인이 53개이다.

각 I/O 핀들은 DDR(Data Direction Register), PORT(Data Register), PIN(Port Input Pins Register)과 같은 레지스터에 의해 제어된다.

DDRx은 핀이 입력용으로 사용할지 출력용으로 사용할지와 같은 핀의 신호 방향을 결정하는 레지스터 이고, PORTx는 I/O핀이 출력용으로 사용될 경우에 출력할 데이터를 저장하는 레지스터이며, PINx은 I/O핀이 입력용으로 사용될 경우에 핀을 입력된 데이터를 저장하는 레지스터이다.

오늘 실험에서는 C핀을 출력으로 설정하고, LED를 제어하는 실험을 해보았다.
기본 컴파일러의 라이브러리를 이용하지 않고, 각 핀 주소를 #define을 사용하여 제어하였다.
LED를 일정 시간 단위로 불을 켰다 끄는 것을 반복하는 코드를 작성하였는데 이를 위해 딜레이를 주기위한 코드를 작성하였다.

port.h파일

#define DDRA  (*(volatile unsigned int *)0x3A)
#define PORTA  (*(volatile unsigned int *)0x3B)

#define DDRB  (*(volatile unsigned int *)0x37)
#define PORTB  (*(volatile unsigned int *)0x38)

#define DDRC  (*(volatile unsigned int *)0x34)
#define PORTC  (*(volatile unsigned int *)0x35)

#define DDRD  (*(volatile unsigned int *)0x31)
#define PORTD  (*(volatile unsigned int *)0x32)

#define DDRE  (*(volatile unsigned int *)0x22)
#define PORTE  (*(volatile unsigned int *)0x23)

#define DDRF  (*(volatile unsigned int *)0x61)
#define PORTF  (*(volatile unsigned int *)0x62)
//
기존 컴파일러에서 제공하는 헤더 파일을 이용하지 않고, atmega128 datasheet 나와 있는 핀별 주소를 직접 #define 했다.

main.c파일

#include "port.h"

int main(void)
{
  unsigned int us = 0;  // 10^-6
  unsigned int ms = 0;  // 10^-3
  int flag = 0;

  DDRC = 0xFF;

  while(1)
  {
    us++;
    if(us >= 1000)
    {
      ms++;
      us = 0;
    }
    if(ms >= 500)
    {
      if(flag)
      {
        PORTC = 0x00;
        flag = 0;
      }
      else
      {
        PORTC = 0xFF;
        flag = 1;
      }
      ms = 0;
    }
  }

  return 0;
}

// atmega128의 동작 클럭은 16MHz로 1초에 16000000번의 마이크로연산이 가능하다. 그러므로 일반적인 사람의 눈으로 LED 불을 on/off 시키는 것을 보기 위해서는 불을 켠 후 어느정도 딜레이를 주고 다시 불을 끄는 동작을 해야 한다. 이 딜레이를 덧셈 연산의 반복을 이용하여 구현한다.

 

c언어 실습

다중 if 문

#include <stdio.h>

int
main()
{
    int score;
    char grade = 'X';

    printf("Please enter examination score: ");
    scanf("%d", &score);

    if((score <= 100) && (score >= 90))
    {
            grade = 'A';
    }
    else if((score < 90) && (score >= 80))
    {
            grade = 'B';
    }
    else if((score < 80) && (score >= 70))
    {
            grade = 'C';
    }
    else if((score < 70) && (score >= 60))
    {
            grade = 'D';
    }
    else if((score < 60) && (score >= 0))
    {
            grade = 'F';
    }
    else
    {
            printf("wrong score\n");
    }
    printf("The grade is %c\n", grade);

    return 0;
}


포인터

포인터는 메모리의 주소를 의미하고, 포인터 변수는 이 메모리 주소들을 저장할 수 있는 변수를 뜻한다.

#include <stdio.h>

int main()
{
    int a = 100;    // int형 변수 a선언 & 100으로 초기화
    int *p;    // int형 포인터 변수 p 선언
    p = &a;    // 포인터 변수p에 a변수의 주소를 대입한다
    *p = 0x99;    // 포인터 변수p에 저장된 메모리 주소의 메모리에 0x99를 대입(즉 변수a에 0x99를 대입)
    *((int *)0x18FF38) = 0x77;    // 변수a의 메모리 주소를 int형 포인터 변수로 캐스팅 연산한 후, 이 주소의 메모리에 0x77을 대입

    printf("a value : %x\n", a);
    printf("a address(16) : %x\n", &a);
    printf("p address(16) : %x\n", p);

    return 0;
}


변수 a에 77이 대입된 걸 알 수 있다.
포인터 변수 p에 int형 변수a의 주소값이 저장 되어 있는 것을 알 수 있다.

+ Recent posts