Hardware/Iot Hacking AVR 프로그래밍 mongii@grayhash
마이크로컨트롤러소개 MCU = Micro Controller Unit 한마디로 작은 CPU 혹은작은컴퓨터 특수목적을수행하는소형화된 CPU 주변장치를추가해나가며기능확장 (Control) 가능 주로 C언어를이용하여프로그래밍 칩내부에 RAM과 ROM 등을포함 System on a chip (SoC)
주요 MCU 들 AVR 아트멜 (Atmel) 사에서개발 마이크로컨트롤러초급자들에게인기 개발환경구축이용이하며, 관련자료가많음 8051 인텔에서만든 MCU 초창기 MCU 중하나 역시초급자들에게인기가많음 PIC 마이크로칩사에서만든 MCU 산업용으로특히많이사용됨
MCU 의구조 하나의칩에모든기본기능이내장됨 CPU, FLASH, SRAM, ROM, I/O MCU 하나만으로동작가능 MCU 자체로서하나의작은컴퓨터
MCU 와 CPU 의차이 MCU 통합형칩셋혼자동작가능임베디드장비에사용 CPU 산술, 논리연산특화혼자동작불가능일반 PC에사용 - MCU : 통합형, 혼자동작가능 - CPU : 산술 / 논리특화, 혼자동작불가능 * 결국 MCU 안에는 CPU 가포함되어있음
MCU 와 CPU 구별법 단일칩으로작동할수있느냐없느냐의차이
AVR Programming 의세계로!
AVR 의장점 AVR 은하드웨어프로그래밍분야의기본이다! 가장먼저, 그리고필수적으로학습하기를추천 Low Level 의지식들을학습할수있음 풍부한학습자료 무료개발툴 하드웨어구매비용저렴 가격대비만족스러운성능
AVR 의종류들 다양한구매자의요구를충족하기위한매우다양한종류의제품들을판매 참고 : http://www.devicemart.co.kr
패키지타입에따른분류 칩이 PCB 에연결되는방식을의미 순서대로 : DIP, SOIC, TSOP, TQFP, BGA, MLF
Atmega128A 소개 8비트마이크로컨트롤러 최대 16Mhz의속도 128Kbytes의플래시메모리내장 4Kbytes의 SRAM 내장 4Kbytes의 EEPROM 내장 133개의 instruction 제공 2.7~5.5v 전압에서동작
Atmega128 VS Atmega128A 동작전압의차이 Atmega128 : 4.2~5.5V Atmega128A : 2.7~5.5V 일부핀배열의차이 출력전류크기의차이
실습용개발보드소개 Atmega128 Rabbit Board Atmega128A MCU 기반 http://itempage3.auction.co.kr/detailview.aspx?itemno=b420146899
AVR 개발도구소개 Atmel-STUDIO Atmel 개발, 무료, 통합개발환경제공 CodeVision 예제코드자동생성가능 유료, 약 30 만원 IAR EWAVR 유료, 수백만원
입출력포트의이해 하드웨어분야에서있어서포트 (Port) 란, 전기적신호데이터가오가는통로를의미 Atmega128A 총 64 개의핀노출 총 7 개의포트 - Port A : PA0 ~ PA7 - Port B : PB0 ~ PB7 - Port C : PC0 ~ PC7 - Port D : PD0 ~ PD7 - Port E : PE0 ~ PE7 - Port F : PF0 ~ PF7 - Port G : PG0 ~ PG4
입출력포트의이해 - 범용포트와특수포트 - 범용포트 : 프로그래머마음대로사용가능 - 특수포트 : 정해진기능수행 - RX/TX - JTAG - ISP - ADC
레지스터의이해 레지스터란 MCU 내부에존재하는소형메모리로서, MCU 의상태를제어하거나혹은데이터이동의매개체역할을함 범용입출력관련레지스터들 PORTA, DDRA,... 1 : #include <avr/io.h> 2 : 3 : int main(void) 4 : { 5 : DDRA = 0xff; 6 : PORTA = 0xff; 7 : 8 : return 0; 9 : }
잠시후에해볼것 MCU 에프로그램집어넣기 (downloading) LED 제어 모터제어 부저스피커제어 UART 통신 온도센서제어 7 Segment 제어 Switch 입력처리 등등..
개발도구설치 Atmel Studio 7 https://www.microchip.com/avr-support/atmel-studio-7 http://studio.download.atmel.com/7.0.1645/as-installer-7.0.1645-web.exe EXE 바로다운로드
프로젝트생성 Atmel Studio 7 실행 File -> New -> Project -> GCC C Executable Project
ATmega128A 선택 프로젝트생성
LED 연결 LED 의긴다리 = 양극 => PORTA 에입력 LED 의짧은다리 = 음극 => GND 에입력
Hello, AVR World! 소스코드입력 #include <avr/io.h> int main(void) { DDRA = 0xff; PORTA = 0xff; } return 0;
컴파일 (Build, F7) Build succeeded 확인
USB-ISP 도구연결 VCC GND MOSI MISO SCK RST 서로같은이름에연결
ISP 란? In-System Programming 플래쉬롬을탈착하지않고프로그램기록가능한형태를의미 컴파일된프로그램을 AVR 칩에기록하는작업을 " 다운로딩 " 이라고부르며, 이를퓨징 (Fusing), 플래싱 (Flashing), 혹은프로그래밍 (Programming) 이라고부르기도함
VCC 와 GND VCC Voltage collector (+) 라인 높은전압 ex> 12v, 5v, 3.3v Vdd 라고도함 (TTL/CMOS 차이 ) GND Ground (-) 라인 낮은전압 == 기준전압 == 0v Vss 라고도함
USB-ISP 의스위치 1 번스위치 ON : USB 전원사용
Driver 인식실패시 USB to UART 드라이버설치 http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx
펌웨어 Programming 1. Tools -> Add Target STK500 COM 포트선택 2. Tools -> Device Programming Tool -> STK500 COM(n) Device -> Atmega128 Interface -> ISP Apply 클릭
펌웨어 Programming Device signature 확인
펌웨어 Programming Downloading == Programming == Fusing == Writing 개발 PC -> AVR MCU 로프로그램입력
빛나라 LED 야
소스코드설명 DDRA : Data Direction Register 0 : 데이터입력 1 : 데이터출력 PORTA 0 => 0 볼트출력 1 => 5 볼트출력 #include <avr/io.h> int main(void) { DDRA = 0xff; // 0b11111111; PORTA = 0xff; } return 0;
저항연결하기 일반적인 LED 의스펙 20mA 에서이상적으로작동 AVR 핀하나에서나오는전류량 = 50mA 저항없이사용시 장시간사용시 LED나 MCU에악영향 저품질 LED 사용시훼손 LED 발열로인한화상우려
저항연결
실습문제 오직 PA3 번에연결했을때만 LED 에불이켜지게해보세요. 즉, PA0,1,2 나 PA4,5,6,7 에선불이들어오면안됨
PA0 은 MSB 인가 LSB 인가? PORTA = 0b01100100; PA0 == LSB 이다.
실습문제 PORTA 와 PORTB 를이용하여 LED 의불을켜보세요. 즉, GND 핀을사용하지않습니다.
실습문제 PORTA 하나만이용하여 LED 에불을켜보세요. 즉, GND 나다른 PORT 를사용하지않습니다.
점멸하라 LED 여! #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> int main(void) { DDRA = 0xff; } while(1) { PORTA = 0xff; _delay_ms(1000); PORTA = 0x00; _delay_ms(1000); }
여러개의 LED 제어
빵판사용하기
여러개의 LED Show 문제 1 홀수번째 LED 만켜지게해보세요. 문제 2 짝수번째 LED 만켜지게해보세요. 문제 3 움직이는 LED 쇼를자유롭게만들어보세요.
LED 의밝기를반으로 #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> int main(void){ DDRA = 0xFF; while(1){ PORTA = 0xff; _delay_ms(10); } } PORTA = 0x00; _delay_ms(10);
달려라모터야
모터의종류 DC 모터 : 일반모터 RC 카, 선풍기등 서보모터 : 원하는각도조정가능 (EX> 90 도, 45 도 ) 로봇팔등 스테핑모터 : 원하는각도만큼미세하게조정가능 (EX> 1도 ) 프린터, CNC 공작기, 디스크헤더등
모터를돌려보세요 ~ 실습문제
부저스피커사용하기
부저스피커사용하기 반복되는전기신호를전달하여진동생성 #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> int main(void) { DDRA = 0xff; while(1){ PORTA = 0xff; _delay_ms(1); } PORTA = 0x00; _delay_ms(1); }
실습문제 주파수를변경하여다양한음을만들어보세요. 더높은음 더낮은음
참고자료 주파수에따른소리의차이 https://www.youtube.com/watch?v=qnf9n zvnd1k 슈퍼마리오연주하기 https://www.youtube.com/watch?v=ade89 -w3jia
7 Segment 제어 7 Segment = FND(Flexible Numeric Display) 0에서 9까지의숫자를표현할수있는장치 Anode 타입과 Cathode 타입이있음 Anode : 가운데핀에 + 를입력하는방식 Cathode : 가운데핀에 를입력하는방식
7 Segment 제어
실습문제 숫자 3 을출력해보세요. 숫자 9 를출력해보세요. 숫자 1 부터 9 까지를 1 초단위로출력해보세요.
쉬어가기 AVR 로만들수있는것들의예제
LED DOT MATRIX http://www.youtube.com/watch?v=cgh_svrqchs
3D 큐브 http://www.youtube.com/watch?v=6mxm-ogggrm
MP3 플레이어 http://www.youtube.com/watch?v=a5xi_2ctd7y * MP3 Codec 칩내장
RC 카 http://www.youtube.com/watch?v=pd99szygjgs
라인트레이서 http://www.youtube.com/watch?v=flvyguk_qia * 적외선발광부와수광부이용 ( 바닥이검정색일때반사되지않음 )
2 족보행로보트 http://www.youtube.com/watch?v=fccxyiuxvia
6 족보행로보트 http://www.youtube.com/watch?v=0ccfp-rnq68
쿼드콥터 http://www.youtube.com/watch?v=fexxmsqbbru * 자이로센서 ( 기울기 ), 가속도센서 ( 기울기 ), 지자기센서 ( 방향 ) 등내장
게임기 http://www.youtube.com/watch?v=ryyalqygg-k
웹서버 http://www.youtube.com/watch?v=5ur5oy0s-ag * Ethernet or WIFI 칩내장
GPS 장치 http://www.youtube.com/watch?v=q4ldyvv3hnc * GPS 센서내장
3D 프린터 http://www.youtube.com/watch?v=ozvcqc2jtx8
UART 프로그래밍 UART 란? Universal Asynchronous Receiver/Transmitter 하드웨어통신프로토콜중하나 특히디버깅메시지출력용도로많이쓰임
UART 프로그래밍 #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> int main(void) { /* Status Register 0A */ UCSR0A = 0x00; /* Status Register 0B */ /* RX/TX Enable = 00001000 */ UCSR0B = 0x08; /* Status Register 0C */ /* No parity, 8bit = 0110 */ UCSR0C = 0x06; /* 중요 : Baud Rate 설정 */ /* BPS = 9600 */ UBRR0H = 0; UBRR0L = 47; while(1) { UDR0 = 'A'; _delay_ms(1000); } }
UART 핀연결 VCC <-> VCC GND <-> GND TX <-> RX RX <-> TX ISP 연결은해제 주의 : 래빗보드와 UART 장비연결시에만예외적으로 RX<->RX, TX<->TX 로연결해주세요. 래빗보드측의 RX/TX 인쇄가문제
UART 포트접속 putty xshell
UART 포트접속
UART 프로그래밍 UART 에사용되는레지스터목록 UCSR0A UCSR0B UCSR0C UBRR0H UBRR0L UDR0 UART 에사용되는핀들 PE0 (RXD0) PE1 (TXD0)
코드설명 UCSR 레지스터 Control and Status Register 의약자 통신환경설정 UBRR 레지스터 Baud Rate Register 의약자 통신속도정의 UART CALC : http://wormfood.net/avrbaudcalc.php UDR 레지스터 UART 값전달
코드설명 UCSR0A 레지스터 송수신되는데이터의현황이기록됨 (00000000) UCSR0B 레지스터 기능설정 (00001000)
코드설명 UCSR0C 레지스터 통신설정 (00000110) => 8 비트데이터 UBRR0H, UBRR0L 레지스터 통신속도설정 초당전송되는 bit 의수 /* BPS = 9600 */ UBRR0H = 0; UBRR0L = 47;
실습문제 UART 터미널에 hello world 를출력해보세요.
실습문제 문자열출력을쉽게해주는함수를만들어보세요. Ex> Puts( hello world\r\n );
정답 void Puts(char *data) { int i; for(i=0; i<strlen(data); i++) { while((ucsr0a & 0x20) == 0); UDR0 = data[i]; } }
온도센서사용실습
온도센서사용실습 ADC 란? Analog to Digital Converter의약자 아날로그형태의데이터를디지털형태의데이터로변환하는장치를의미
Sampling (https://www.youtube.com/watch?v=zc5kfnsupno)
Quantizing(bit depth, 분해능 ) 디지털값을얼마나세밀하게표현하는지를결정
ADC 핀목록 ATmega128A 의 ADC PF0~PF7 8 채널 8 개까지연결가능
온도센서사용실습 #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> void Puts(char *data) { int i; for(i=0; i<strlen(data); i++) { while((ucsr0a & 0x20) == 0); UDR0 = data[i]; } } int main(void) { char result[20]; int value; DDRA = 0xff; PORTA = 0xff; UCSR0A = 0x00; UCSR0B = 0x88; UCSR0C = 0x06; UBRR0H = 0; UBRR0L = 47; // bps == 9600 while(1) { ADMUX = 0; // ADC 설정초기화시작 ADCH = 0; ADCL = 0; ADCSRA = 0xc7; } } // 설정이완료될때까지기다림 while((adcsra & 0x10) == 0); // ADC0 의상하위바이트값을이용하여데이터복원 value = ADCL (ADCH << 8); memset(result, 0, 20); sprintf(result, "Temporature : %d\r\n", (value*100/205)); Puts(result); _delay_ms(1000);
온도센서사용실습 -BOTTOM VIEW 임에주의 - 다리아래로부터봐야한다. -LM35 의 GND -> 보드의 GND -LM35 의 VCC -> 보드의 PORTA0 -Vout 은 PF0 에연결 - 보드의 AREF 에 PORTA1 연결
소스설명 ADMUX (00000000) ADC 설정초기화 모두 0 으로설정 ( 기준전압 = AREF) ADCSRA (11000111) ADEN : ADC 활성화 ADSC : ADC 변환시작 변환모드 : 단일변환 인터럽트 : 사용 X 분주비 : ADC 로전달되는 Clock 값설정 (50~200khz) value*100/205 : 센서로부터얻은값을섭씨온도로변환하는공식
T(temperature) = value*100/205 센서로부터얻은값을섭씨온도로변환하는공식 100 도 : 205 = T 도 : value 205*T 도 = value*100 도 T 도 = (value* 100 도 )/205
기준전압 (5v) 의필요성 2 비트 bit depth 예, 실제 Atmega128A 의 bit depth 는 10 비트 (1024)
실습문제 온도가 40 도가넘었을때부저가경고를울리게해보세요.
입력핀사용실습
스위치사용하기
스위치사용방법 스위치가옮겨진쪽의두핀이서로연결된다.
스위치사용하기 PB0 에전기신호입력시 PA0 켜기 #include <avr/io.h> int main(void) { int Input = 0; DDRA = 0xff; DDRB = 0x00; DDRC = 0xff; PORTC = 0xff; } while(1) { Input = PINB; if(input & 0x01) PORTA = 0xff; else PORTA = 0x00; }
실습문제 스위치를왼쪽으로옮기면 LED 의불이켜지고, 오른쪽으로옮기면 LED 의불이꺼지게해보세요.
입력핀사용시의주의사항 해당핀은항상 1(HIGH) 또는 0(LOW) 둘중하나의상태가되어야함. 1 또는 0 이아닐경우엔 무엇인지알수없는상태 가되어버림. Floating 상태 0v 도 5v 도아닌아무런입력이가해지지않은상태. 주변의영향에따라어떤값이될지모른다.
인터럽트 사전적으로는방해하다, 중단시키다라는 의미를가지며, MCU 가하고있던동작을잠시멈춘후다른작업을지시하는기능 전기신호가변하는시점을탐지할수있음
Rising Edge 와 Falling Edge 전기신호의 Logic이변하는시점 Rising Edge : LOW -> HIGH Falling Edge : HIGH -> LOW 데이터동기화작업에사용됨
좋지못한코드의예 PB0 에전기신호입력시 PA0 켜기 #include <avr/io.h> int main(void) { int Input = 0; DDRA = 0xff; DDRB = 0x00; DDRC = 0xff; PORTC = 0xff; } while(1) // 무한루프가프로그램의효율을떨어뜨림 { // - CPU 클럭소모 Input = PINB; // - while(1) 문안에다른시간이오래걸리는 if(input & 0x01) // 코드가추가될경우 Input 탐지 delay PORTA = 0xff; }
좋은코드의예 INT0 입력발생시 PA0 켜기 #include <avr/io.h> #include <avr/interrupt.h> ISR(INT0_vect) { PORTA = 0xff; } int main(void) { DDRA = 0xff; DDRC = 0xff; PORTC = 0xff; EIMSK = 0b00000001; /* INT0 ENABLE */ EICRA = 0b00000011; /* INT0 -> rising edge로설정 */ EIFR = 0b00000000; /* flag clear */ sei(); // 인터럽트기능활성화 } while(1){ // 다른일 }
좋은코드의예 EIMSK : MCU 의 INT0 인터럽트기능을활성화시킴 EIMSK = 0b00000001 : 첫번째인터럽트핀활성화 EICRA : 전기신호가들어오거나나가는시점중언제감지할지를결정 EICRA = 0b00000011 : EIFR : FLAG 레지스터를초기화시킴 ISR(INT0_vect) : 인터럽트신호감지시이함수가자동호출됨
실습문제 스위치를오른쪽으로옮기면 LED 의불이켜지게해보세요. => 인터럽트를사용하세요.
Arduino 프로그래밍
아두이노란? 2005 년이탈리아의한대학원 (IDII) 에서개발된하드웨어개발오픈소스플랫폼 통합개발환경 (IDE) 사용이매우쉬움 펌웨어업로딩이매우쉬움 (USB) 하드웨어구매비용이저렴함 (4000 원 ~) 다양한기본예제코드존재 커뮤니티및라이브러리생태계가활성화되어있음
다운로드및설치 https://www.arduino.cc/en/main/software
보드및포트설정
LED 점멸테스트 // 초기화함수 void setup() { // 13 번핀을출력모드로설정 pinmode(13, OUTPUT); } // main loop 함수 void loop() { digitalwrite(13, HIGH); // LED-on delay(3000); // 3초 delay digitalwrite(13, LOW); // LED-off delay(3000); // 3초 delay }
펌웨어업로딩
핀변경실습 (D13 -> D2) * LED 소자를연결하여확인
Arduino Pin map
Serial 출력실습 void setup() { Serial.begin(9600); } void loop() { Serial.print("A"); delay(1000); }
Serial 입력실습 void setup() { Serial.begin(9600); Serial.println("RX test Start!"); } void loop() { char ch; } if (Serial.available()) { ch = Serial.read(); Serial.print("RX : "); Serial.println(ch, HEX); }
부저스피커사용하기
부저스피커사용하기 반복되는전기신호를전달하여진동생성 void setup() { } pinmode(2, OUTPUT); void loop() { } digitalwrite(2, HIGH); delay(1); digitalwrite(2, LOW); delay(1);
부저스피커사용하기 주파수와음의관계
부저에 도 음출력하기 C( 도 ) = 261.6hz = 대략 262 void setup() { pinmode(2, OUTPUT); // D2 핀초기화 (OUTPUT) } void loop() { tone(2, 262, 1000); // D2 핀에 " 도 " 음을 1 초간출력 delay(2000); // 2 초대기 }
부저를이용한연주예제 슈퍼마리오 http://www.princetronics.com/supermariot hemesong/ 스타워즈다스베이더테마 https://gist.github.com/nicksort/4736535
초음파거리센서 초음파를발사한후, 반사되어돌아오는시간을재어거리측정 Echo <-> D12 Trig <-> D13
초음파거리센서 // 출처 : https://kocoafab.cc/tutorial/view/65 // 초음파센서의핀번호를설정한다. int echopin = 12; int trigpin = 13; void setup() { Serial.begin(9600); // trig 를출력모드로설정, echo 를입력모드로설정 pinmode(trigpin, OUTPUT); pinmode(echopin, INPUT); } void loop() { float duration, distance; // 초음파를보낸다. 다보내면 echo 가 HIGH 상태로대기하게된다. digitalwrite(trigpin, HIGH); delay(10); digitalwrite(trigpin, LOW); // echopin 이 HIGH 를유지한시간을저장한다. duration = pulsein(echopin, HIGH); // HIGH 였을때시간 ( 초음파가보냈다가다시들어온시간 ) 을가지고거리를계산한다. distance = ((float)(340 * duration) / 10000) / 2; } Serial.print(distance); Serial.println("cm"); // 수정한값을출력 delay(500);
무선통신실습
무선통신의원리 빛감지센서 빛을감지하면저항이작아져서회로가연결된다 Ex> 빛이있을때 : 1 빛이없을때 : 0 그렇다면빛의 on/off 를이용하여무선통신을할수있지않을까?
무선통신의원리
무선통신의원리 하지만실제로빛 ( 가시광선 ) 을이용하는것은사람의눈에영향을미치며, 항상빛을사용하고있어야한다는단점이있다. 가시광선보다낮은주파수대역의적외선을이용 사람의눈에보이지않는다 더먼곳까지전파를보낼수있다 적외선송신부와수신부 ( 수광부 ) 를이용한다.
수광부사용실습 앞에서볼때순서대로 OUT, GND, VCC 적외선신호의세기를감지하는것이아니라 38Khz 의주기로깜박이는적외선에반응하도록설계되어있다. 즉, 38khz 의적외선이있다 / 없다로반응한다. OUT 의값은평상시에 HIGH, 신호감지시 LOW 값을
수광부사용실습
적외선수신 #include <IRremote.h> // receive pin number int RECV_PIN = 11; IRrecv irrecv(recv_pin); decode_results results; void setup() { Serial.begin(9600); irrecv.enableirin(); } void loop() { } if (irrecv.decode(&results)) { Serial.println(results.value, HEX); irrecv.resume(); } 수광부의신호핀은 11 번에연결 IRremote Library - https://github.com/shirriff/arduino-irremote/archive/master.zip 참고 - https://kocoafab.cc/tutorial/view/78
적외선송신부사용실습 VCC/GND 38khz 의신호를만들어서전달한다
적외선송신 #include <IRremote.h> IRsend irsend; void setup(){ serial.begin(9600); } void loop(){ for(int i = 0; i < 3; i++){ irsend.sendsony(0x0a90, 16); // Code, Bit length delay(40); } delay(1000); } 적외선 LED 핀은 3 번에연결 참고 - https://kocoafab.cc/tutorial/view/76
AVR 과아두이노
AVR 과아두이노 요리를직접하느냐? 다되어있는걸데워먹느냐의차이 학습기간중엔되도록이면 AVR 을다루길권장!
감사합니다.