아두이노는 원하는 작업을 쉽게 구현을 하고 편리한 IDE프로그램을 이용해 코딩도 쉽게 할 수 있다.
그러나 이는 단순히 '쉽게'구현 할 수 있을 뿐 실제 임베디드 개발을 하기 위해서는 제약이 많다.
그래서 이제부터 아두이노 언어를 사용하지 않고 AVR코딩을 하도록 습관을 갖자.
아두이노 - Microchip Studio 연동
아두이노에서 사용하는 칩셋은 Atmel사에서 제작한 'Atmega328P'이다.
자세한 데이터시트는 다음과 같으며 회로도도 보면서 설계하면 많은 도움이 된다.
ATmega328P (microchip.com)(데이터시트)
arduino-uno-schematic.pdf(회로도)
또, 아두이노와 마이크로칩스튜디오와 연동하기 위해서 다음 블로그를 참고하자.
Microchip Studio를 통해 아두이노에 프로그램 업로드 하기 (LED 제어) :: Design (tistory.com)
버튼으로 LED제어하기
지난 포스팅에서 간단하게 DDRB와 PORTB를 통해서만 LED를 제어했었다.
이번에는 버튼을 누르면 LED를 번갈아가며 킬 수 있도록 만들어 보자.
논리적으로 단순히 코딩을 하면 다음과같이 작성 할 수 있다.
#define F_CPU 16000000UL
#include <stdio.h>
#include <util/delay.h>
#include <avr/io.h>
char circular_shift_left(char pattern){
return((pattern << 1)|(pattern >> 2)); // led3개만 사용하므로 3비트 원형 쉬프트
}
int main(void){
DDRB = 0xFF; // 포트B 출력모드
DDRD &= ~0x04; // 포트D 3번비트(PF2) 입력모드
char pattern = 0x01;
PORTB = pattern;
while(1){
if((PIND & 0x04)>>2 == 1){ // 버튼이 눌려진 경우
pattern = circular_shift_left(pattern); //함수 호출 후 대입
PORTB = pattern;
}
}
return 0;
}
영상을 봐도 알겠지만 뭔가 이상한 부분이 있다.
작성한 코드대로라면 led가 순차적으로 쉬프트되면서 점등되어야 하지만 이것은 랜덤하게 켜지는 것 같다.
그 이유는 바로 MCU(Atmega328P)가 16MHz로 매우 빠른 속도로 클럭이 흐르기 때문에 버튼을 누르는 몇초 동안에도 수십만번 버튼의 상태를 체크하면서 연산을 하고 있다.
또, 우리가 버튼은 한번 눌렀다고 0, 1이 변하는 것이 아니라 실제로 버튼의 스프링, 주변의 자기장등 여러 변수에 의해서 디지털 논리 값이 바뀌게 된다. 이런 현상을 바운스현상(bounce effect) 혹은 채터링(chattering)이라고 한다.
위와같은 채터링을 고려하면서 코딩하면 다음과 같이 작성 할 수 있다.
#define F_CPU 16000000UL
#include <stdio.h>
#include <util/delay.h>
#include <avr/io.h>
char circular_shift_left(char pattern){
return((pattern << 1)|(pattern >> 2));
}
int get_button_state(void){ // 버튼의 상태를 두번 검사
if((PIND & 0x04)>>2 == 1){
_delay_ms(10);
if((PIND & 0x04) >> 2 == 1){
return 1;
}
}
return 0;
}
int main(void){
DDRB = 0xFF; // 포트B 출력모드
DDRD &= ~0x04; // 포트D 3번비트(PF2) 입력모드
char pattern = 0x01;
PORTB = pattern;
char state_previous = 0, state_current;
while(1){
state_current = get_button_state(); //버튼 상태 읽기
if(state_current == 1 && state_previous == 0){
pattern = circular_shift_left(pattern);
PORTB = pattern;
}
state_previous = state_current; //버튼 상태 업데이트
}
return 0;
}
이렇게 버튼의 동시입력, 채터링을 고려해서 led를 제어해 보았다.
사실 채터링코드부분에서 if문을 두번 작성했는데 하나만 써도 어느정도 효과를 볼 수 있지만 두번함으로써 더 확실히 제어를 할 수 있다.
MCU를 통한 제어는 단순히 논리적으로 코드를 작성해 나가면 원하는 동작이 나오지 않는 문제가 있다.
바로 이런 문제 때문에 하드웨어, 통신방식, 스펙을 자세히 이해를 해야 할 필요가 있다.
'AVR(Microchip Studio)' 카테고리의 다른 글
[AVR] Atmega8 테스트보드 만들기(납땜 & 테스트장비) (0) | 2022.01.08 |
---|---|
[AVR] Atmega328P UART통신 & 헤더파일 나누기(putty) (0) | 2021.12.29 |
[AVR] Atmel Studio7 레지스터 제어, Simulator 디버깅 (0) | 2021.12.23 |
[µ-Processor] 내부구조(ALU) (1) | 2021.07.20 |
[µ-Processor] AVR내부연산 & Opcode (0) | 2021.07.17 |