전자회로실험
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의 주소값이 저장 되어 있는 것을 알 수 있다.