원래 오늘 부터 직접 아두이노 미니를 이용하여 해 볼 생각이었지만
ISP 다운로드 케이블 연결한 후 다운로드 할려는 순간
타는 냄새가 나서 봤더니 미니에서 연기가 나고있었다.
저번에 어떤 소자 하나가 내부가 들어나 있었는데
거기에서 연기가 발생한 듯하다.
찾아보니 RESET 핀에 C106이라는 콘덴서였다.
일단 나중에 저것만 따로 사서 고쳐서 사용하든 그냥 새로 사든지 해야겠다.
그래서 오늘은 그냥 LED를 키고 끄는 코드만 보겠다.
LED는 아두이노 미니 기준으로 D2번 핀을 사용할 것이다.(연결은 알아서)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#define F_CPU 16000000L
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRD= 0b00000100;
while(1) {
PORTD = 0b00000100;
_delay_ms(1000);
PORTD = 0b00000000;
_delay_ms(1000);
}
return 0;
}
|
cs |
위의 코드는 D2번 핀을 1초 키고 1초 끄는 것을 반복하는 것인데
일단 F_CPU는 클럭수 즉 atmega328의 기준이 되는 시간이다
아두이노 Pro Mini 328 16MHz이므로 16M 즉 16000000(16*1000*1000)을 입력하면된다.
두번째로 #include <avr/io.h>에서 io는 INPUT, OUTPUT즉
입력과 출력 관련된 것이다.
그리고 #include <util/delay.h>는 우리가 delay함수를 사용할 것이므로 불러왔다.
그 다음은 main함수인데
main함수 내부가 실제로 동작하는데 영향을 주는 곳으로 프로그래밍 할 때에는
main내부에 작성하면된다.
실제로 아두이노에서
로 시작하는데
아두이노 내부 코드를 보면
1
2
3
4
5
6
7
8
|
int main(void) {
setup();
for(;;) {
loop();
}
return 0;
}
|
cs |
이런 형식으로 되어있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define F_CPU 16000000L
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRD= 0b00000100;
while(1) {
PORTD = 0b00000100;
_delay_ms(1000);
PORTD = 0b00000000;
_delay_ms(1000);
}
return 0;
}
|
cs |
그 다음 봐야할 것은 DDRD라는 것이다.
이건 어제 올렸던 아두이노 Pro Mini 328 16MHz의 회로도를 확대한 것인데
잘 보면
PC0 | A0 |
PC1 | A1 |
PC2 | A2 |
PC3 | A3 |
PC4 | A4 |
PC5 | A5 |
PC6 | RESET |
PB0 | D8 |
PB1 | D9 |
PB2 | D10 |
PB3 | D11(MOSI) |
PB4 | D12(MISO) |
PB5 | D13(SCK) |
PB6 | XTAL1 |
PB7 | XTAL2 |
PD0 | D0(Rx) |
PD1 | D1(Tx) |
PD2 | D2 |
PD3 | D3 |
PD4 | D4 |
PD5 | D5 |
PD6 | D6 |
PD7 | D7 |
이라고 써 있는 것이 보인다.
다시 본론으로 돌아가서
DDRD는 PD0 ~ PD7까지의 INPUT(입력)과 OUTPUT(출력)을 한번에 설정해 주는 레지스터이다.
0 ~ 7까지는 총 8개의 핀이며
1이면 출력(OUTPUT) 0이면 입력(INPUT)이라는 뜻이고
우리가 사용할 핀은 PD2 ( D2 )핀이고 나머지
PD0 ~ 1
PD3 ~ PD7은 사용 안할 것이므로 0
PD2는 출력으로 사용할 것이므로 1로 설정해야하므로
DDRD = 0b00000100로 설정했다.
여기서 0b는 이진법으로 수를 표현하겠다 라는 뜻이다.
만약 D2(PD2)핀이 아니라 D3(PD3)을 LED출력 핀으로 사용할 거면
DDRD = 0b00001000이런 방식으로하면 되고
꼭 PD0 ~ 7이 아니라
PC0( A0 )핀을 LED 출력 핀으로 사용하고 싶으면
DDRC = 0b0000001 로 설정하면 된다.
따라서 DDRD = 0b00000100은
아두이노에서 따지면 pinMode(2, OUTPUT);이 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define F_CPU 16000000L
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRD= 0b00000100;
while(1) {
PORTD = 0b00000100;
_delay_ms(1000);
PORTD = 0b00000000;
_delay_ms(1000);
}
return 0;
}
|
cs |
그 다음 while은 다들 알고있으니 설명 생략
PORTD는 PD0 ~ 7핀의 출력 상태를 지정하는 레지스터이다.
1은 ON, 0은 OFF를 의미하고
우리가 사용할 핀은 PD2( D2 )핀이므로
PORTD = 0b00000100로 설정하여 PD2핀은 1
나머지 0,1,3,4,5,6,7핀들은 0으로 설정했다.
만약 이것도 PC0 ( A0 )핀이라면
PORTC = 0b0000001라고 하면 된다.
따라서 PORTD = 0b00000100은
아두이노에서 digitalWrite(2, 1);이라는 것과 비슷하다.
_delay_ms(1000);은 아두이노에서 delay함수랑 비슷하며
밀리세컨드(1/1000초)단위로 일시적으로 지연해준다.
PORTD = 0b00000100 (= 0x04)
_delay_ms(1000);
PORTD = 0b00000000 (= 0x00)
_delay_ms(1000);
을 통해 PD2( D2 )핀을 1초 키고 1초 끄는 것을 해봤다.
마지막으로 return 0;은 모든 프로그램이 끝났다는(?)것을 의미한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define F_CPU 16000000L
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRD= 0b00000100; // pinMode(2, OUTPUT);
while(1) {
PORTD = 0b00000100; // digitalWrite(2, 1);
_delay_ms(1000);
PORTD = 0b00000000; // digitalWrite(2, 0);
_delay_ms(1000);
}
return 0;
}
|
cs |
(참고로 PORT레지스터가 출력 담당이라면 PIN레지스터는 입력 담당이다.)
아두이노에는 pinMode, digitalWrite라는 편리한 함수들이 존재한다.
이러한 함수들이 존재하는데, 이렇게 레지스터에 직접 접근하여 아두이노를 제어하는 이유는 다음과 같다.
1. 속도가 굉장히 빠르다.
pinMode를 사용하는 것보다, DDRD 등을 사용하는 것이 속도면에서 10 ~ 40배 정도 차이난다.
https://blog.naver.com/twophase/221004945877
아두이노에서 제공하는 함수들은 여러 예외 사항들이나, 모든 보드에 서 동작될 수 있도록 설계되어 있기 때문에 당연히 느릴 수밖에 없다.
2. 최적화가 가능하다.
아두이노에서 제공하는 함수들은 내부 코드 길이 자체가 길기 때문에 많은 용량을 차지할 수밖에 없다. 반면 동일한 기능을 수행하는 레지스터 설정은 단지 한 줄의 용량만을 차지한다.
3. 한 번에 처리 가능
본문에서 설명했듯, pinMode는 하나의 포트에 대해서만 설정할 수 있지만, DDRD의 경우 0~7까지, 총 8개의 핀을 한 번에 설정할 수 있어 경재적이다.
4. 연산 가능
예시를 들어 설명하면 아두이노에서 LED를 키고 끄는 코드를 구현하면 보통 다음과 같다.
digitalWrite(2, HIGH);
digitalWrite(2, LOW);
레지스터를 사용하면 다음과 같이 구현할 수 있다.
PORTD ^= 0b00000100;
'atmega328(아두이노 미니 이용)' 카테고리의 다른 글
스터디 상생 플러스 1 - 1 (MCU에 대한 지식 습득) (0) | 2020.04.09 |
---|---|
avr 로터리 엔코더 사용하기 05 (6) | 2017.10.09 |
비트 연산자 테스트 04 (0) | 2017.08.12 |
atmega 비트연산자 03 (0) | 2017.08.11 |
아두이노 미니로 atmega328 사용하기 (avr studio) 01 (0) | 2017.08.09 |