Lecture Note ATmega128 인터페이스 프로그래밍 원서 : 알기쉽게배우는 AVR ATmega128, 신동욱, 오창헌, Ohm 사 2014. 3.
CodevisionAVR C compiler 사용법 ( 요약 ) (1) 1.1 마이크로프로세서시스템회로도및동작 1 1.2 마이크로콘트롤러 ATmega128 내부회로도 2 2.1 AVR 의구조및종류 3 2.2 ATmega128 Pin 배치및내장 I/O 종류 4 2.3 ATmega128 실험보드구성품및 Base 회로도 5 ATmega128 헤더파일 7 ATmega128 포트종류및포트 I/O 프로그래밍기본방법 8 (1) 7-Seg LED 해설 11 (2) 7-Seg LED 프로그래밍실습 13 (1) LCD 해설 14 (2) LCD 프로그래밍실습 (LCD 의 8-bit 데이터방식사용!) 17 (3) 숫자 ( 정수, 실수 ) 를 LCD 에 display 하기 19 (4) LCD display 프로그램 (4-bit 데이터방식 ) - 실용!! 20 (1) A/D 변환개요 22 (2) ATmega128 내장 A/D Converter 해설 : 23 (3) A/D 변환프로그래밍실습 24 (1) D/A 변환방법원리 ( 사다리형 D/A 변환기 ) 26 (2) D/A 변환프로그래밍실습 27 (1) ATmega128 : 인터럽트해설 : 28 (2) 인터럽트프로그래밍실습 30 (1) ATmega128 : 타이머해설 : 31 (2) ( 타이머 + 인터럽트 ) 프로그래밍실습 32 (1) PWM 이란 33 (2) ATmega128 : 타이머 / 카운터 1, 3 및 PC PWM 해설 : 33 (3) PWM 프로그래밍실습 35 (1) 직렬통신과 RS-232 : 개요 36 (2) ATmega128 USART(RS-232) 해설 : 37 (3) 직렬통신 (RS-232) 프로그래밍실습 39 [ 참고 ] PC 에서 RS-232 직렬통신프로그램구현방법 [main() 에서구현 산술연산자 / 논리연산자 / 비트연산자
USB 방식의 AVR 다운로더 = 먼저, CodeVisionAVR 을실행하여 [Settings] 메뉴의 [Programmer] 를선택. 그후, [USBISP V3.0 사용시 ] : =USB 포트사용시!! AVR Chip Programmer Type : Atmel STK500/AVRISP 로설정. Communication Port : 해당 com 포트로설정 (ex: com4).. 이는장치관리자의포트 (COM 및 LPT) 의 'USB Serial port (COMx)' 와일치해야함! <COMx 찾는방법 > ( 모니터하단의 ) 시작 제어판 시스템 하드웨어 장치관리자 클릭 포트 (COM 및 LPT) 더블클릭 그러면알수있음!! OK 버튼! 먼저, [File] 메뉴의 [New] 를선택 Project 를선택 [OK] 버튼! 그러면, CodeWizardAVR 의실행여부를묻는창이나타남 [No] 버튼! ( 즉, 불용!) ( 참고 : CodeWizard = Code를자동으로만들어주는모드 ) 그러면, Create New Project 창이나타남 : 먼저, 이창맨위의 저장위치 를내가작업하려는폴더로지정함. 그후, 이창아래에프로젝트명 (.prj) 을기입. ( 이름 =.c와동일파일명으로, 확장자만다르게 ) [ 저장 ] 버튼! 그에따라, Configure Project... 창이나타나면 : [ 파일 ] 항목에서 [add] 버튼을눌러,.c 파일을이프로젝트에추가함. [C Compiler] 항목을열어, Chip= ATmega128, Clock= 16 MHz 로설정. ( 나머지 = 그대로 ) [After Make] 항목을열어, Program the Chip' 을체크함. ( 그아래에나타나는것들 = 그대로 ) [OK] 버튼! 이제프로젝트만들기는완료! 화면상에 C-소스파일 (.c) 이열림. 먼저, C-소스파일을작성 ( 편집, 수정 ) 한다. 그후, [Project] 메뉴의 [Compile] 을선택...[Compile] 은소스코드를 Object code 로바꿔주는기능을함. 그러면, 컴파일수행결과창이나타남. 중간쯤에 No errors, No warnings 가있으면성공! [OK] 버튼! 그후, [Project] 메뉴의 [Make] 를선택....[Make] 는 Object code를어셈블하여 HEX code를만들어줌. 그러면, 메이크수행결과창이나타남. 중간쯤에 No errors, No warnings 가있으면성공! [Program the chip] 버튼! 그러면, 작성된프로그램을 AVR에다운로딩함!!! long은안됨!!??..char, int, float만됨! char,int,float의데이터길이 = 1,2,4 byte ( 엄격!!) unsigned = 엄격히적용됨!! 즉, char=(-128)~(+127), unsigned char=0~255! int=(-32768)~(+32767), unsigned int=0~..
< 마이크로프로세서구조 > 마이크로프로세서 (μ-p) = 메모리에서데이터를가져와서이를처리하는중앙처리소자. 메모리 = μ-p 가해야할일을수록해놓은 S/W(program: 명령어의집합 ) 이들어있는창고. I/O port = μ-p 와외부 device( 장치 ) 를연결해주는매개역할을하는부분. (port = 항구!) < 동작예 1> μ-p가메모리에서읽기동작순서 : (I/O Port도마찬가지방식으로동작함 ) 1 μ-p는 CS신호로원하는메모리를선택하고,( 이때 CS신호는 Address신호에의해만들어짐!) 2 이메모리내의한장소에해당하는 Address신호를주고, 3 이메모리에게 Data를읽고싶다는것을의미하는 RD신호를준다. ( 그러면, 메모리는이에따라 Data를내보낼것이다 ) 4 그후, μ-p는이 Data를받는다. < 동작예 2> μ-p가메모리에쓰기동작순서 : (I/O Port도마찬가지방식으로동작함 ) 1 μ-p는 CS신호로원하는메모리를선택하고,( 이때 CS신호는 Address신호에의해만들어짐!) 2 이메모리내의한장소에해당하는 Address신호를주고, 3 이메모리에게 Data를쓰고싶다는것을의미하는 WR신호를주고, 4 이메모리에게 Data를내보낸다. ( 그러면, 메모리는 Data를받아서자기내의지정된장소 (Address) 에저장함 )
ATmega128 인터페이스프로그래밍
: 저전력고속의 CMOS/ C 언어를고려한설계 / 다양한기능을포함 = RISC 구조 & 하버드구조 < 참고 > CMOS 의장점 : 소비전력이매우적다 / 전달특성이우수하다 / 잡음여유가크다 / 집적도가높다 / 입력임피던스가크다 / 동작전압의범위가넓다 CMOS 의단점 : 정전기에의해서산화막의절연이파괴되기쉽다 / RISC 구조 : 복합명령어를쓰지않고간단한명령어만을사용하므로명령어의수를필요한최소한줄임. 주소지정방식또는필요한최소한의국한하는컴퓨터구조 하버드구조 = 프로그램메모리와데이터메모리가확연히구분되는구조. ( 즉, 프로그램메모리에데이터를넣을수없고데이터메모리에프로그램을넣을수없음 ) < 장점 > 동일시간대에프로그램메모리와데이터메모리를동시에접근할수있음. 데이터메모리를레지스터파일형태로통합관리하기때문에 레지스터에서레지스터로바로작용하므로따로이상호전송부가필요없음. 프로그램메모리와데이터의메모리의대역폭의변화가가능하므로 입력은 8bit 이지만내부처리는 16bit 등더빠른사이클에작동가능함. : 1 ATtiny 계열 : 4bit 범용마이크로컨트롤러 / 간단한제품에많이사용 2 AT90S 계열 : 8bit 마이크로컨트롤러 / ATtiny와 ATmega의중간급 3 ATmega 계열 : 메가급 8bit 범용마이크로컨트롤러 / 거의모든특수기능을내장 / 복잡한기능을사용하는제품에사용 이들계열은서로간에사용법이거의유사함!! 각계열 AVR의주요 Spec. 표 = 맨뒤 부록 참조!! ATmega8L = Low Power! 가격 (2008 년 4 월현재 ) : ATmega16 = 2500 원, ATmega32 = 3800 원, ATmega64 = 4000 원, ATmega128 = 3800 원, ATmega8515 = 2300 원, ATmega8535 = 2200 원
핀이름 설명 Vcc 디지털공급전압핀 GND 접지핀 AVcc ADC 에대한공급전압 AREF ADC 참조전압 포트 A,B,C,D, E,F,G (PA7~PA0) (PB7~PB0) (PC7~PC0) (PD7~PD0) (PE7~PE0) (PF7~PF0) (PG7~PG0) 특별기능 ( 상기의포트겸용 ) RESET 리셋입력 8 비트양방향성 I/O 포트. 인터럽트, 타이머 / 카운터 PWM 등파형발생기직렬포트 (serial 통신 ) AD 변환기 (10 비트, 8 채널 ) 아날로그비교기등.. XTAL1 반전발진증폭기및내부클록회로에대한입력 XTAL2 반전발진증폭기로부터의출력
- 구매처 : AVRmall 社 =www.avrmall.com 다음부품들을 BreadBoard 에설치하고, 필요한추가회로를구성하여실습함. M128 Board V2.2 : ATmega128 의기본확장보드, 128K 플래시, 16MHz, 4.5~5.5V M128KN 보드 [M128 Board V2.2 업보드 ] : M128 Board V2.2 를 1 열로확장한보드, 통신칩내장 구매시, M128KN KIT" 로구매하면, 위 2 개를함께판다! ( 약간더쌈!) USBISP V3.0 : USB 방식의 AVR 다운로더 = M128 Board V2.2 와 PC 사이에연결하여 PC 에서작성한프로그램을 AVR 에다운로드시킴 기타부품 (R, C, LED, LCD 모듈, 전용 RS-232 케이블등 ) <USBISP V3.0> =USB 방식의 AVR 다운로더 ATMEL 사의 STK500 호환가능 AVR ISP 프로그래머 AVR Studio V4.11 이상동작가능 CodevisionAVR C compiler V1.24.6 이상동작가능 모든 ISP 포트를잇는 AVR MCU 프로그램기능 내부 Fuse Bit, Lock Bit Read/Write 별도의 ISP 사용으로펌웨어업그레이드가능 ATMEL 6Pin ISP 지원 : 1 MISO VCC 2 3 SCK MOSI 4 5 RST GND 6 지원 Device : 많은 AVR류 ATtiny12, ATtiny13, ATtiny15,... AT90S1200 등등 ATmega8, ATmega16,...ATmega128,...ATmega644,.. AT86RF401, 89S51, 89S52, AT90USB162 등., M128 Board V2.2 <M128KN 보드 > M128 Board V2.2 업보드 <M128 Board V2.2> --- 주요기능 :---------- ATmega128 포트확장보드 지원 CPU : ATmega128-16AI, 16MHz ATMEL 6Pin ISP 포트지원 (& JTAG 포트지원 ) 1 MISO VCC 2 3 SCK MOSI 4 5 RST GND 6 통신포트지원 : 4 핀 TYPE(RX,TX,VCC,GND) 리셋스위치지원 동작전원 : 4.5 ~ 5.5V 에서동작 <M128KN> 보드 = M128 Board V2.2 업보드 ---주요기능 :----------- M128 Board V2.2 업보드장착하여사용해야함 (M128 Board V2.2가착탈이가능하여사용자가상황에따라사용가능 ) M128 Board V2.2는별도구매 브레드보드를이용손쉽게시스템구축 RS232통신포트 2채널지원 ( 시리얼케이블별매 ) RTC-32.768KH 내장 ATMEL 6PinISP 포트 (& JTAG 포트지원 )
< 참고 > M128 Board V2.2 회로도 = 사실상, 아래회로에포함되어있음!
ATmega128 인터페이스프로그래밍 -< 상호관련 > ATmega128 의내부레지스터 ATmega128 헤더파일 (.h) 아래헤더파일에서정의되는명칭 = C 프로그램에서변수처럼사용됨!! mega128.h : ATmega128 헤더파일 -for CodeVisionAVR C Compiler = ATmega128 의 I/O registers definitions sfrb PINF=0; sfrb =1; //Port E sfrb =2; sfrb =3; sfrb ADCL=4; sfrb ADCH=5; sfrw ADCW=4; // 16 bit access sfrb =6; //ADC sfrb =7; sfrb ACSR=8; sfrb UBRR0L=9; sfrb UCSR0B=0xa; sfrb UCSR0A=0xb; sfrb UDR0=0xc; sfrb SPCR=0xd; sfrb SPSR=0xe; sfrb SPDR=0xf; sfrb =0x10; sfrb =0x11; sfrb =0x12; sfrb PINC=0x13; sfrb DDRC=0x14; sfrb PORTC=0x15; sfrb PINB=0x16; sfrb DDRB=0x17; sfrb PORTB=0x18; sfrb =0x19; sfrb =0x1a; sfrb =0x1b; sfrb EECR=0x1c; sfrb EEDR=0x1d; sfrb EEARL=0x1e; sfrb EEARH=0x1f; sfrw EEAR=0x1e; // 16 bit access sfrb SFIOR=0x20; sfrb WDTCR=0x21; sfrb OCDR=0x22; sfrb OCR2=0x23; sfrb TCNT2=0x24; sfrb TCCR2=0x25; sfrb ICR1L=0x26; sfrb ICR1H=0x27; sfrw ICR1=0x26; // 16 bit access sfrb =0x28; //PWM sfrb =0x29; sfrw OCR1B=0x28; // 16 bit access sfrb OCR1AL=0x2a; sfrb OCR1AH=0x2b; sfrw OCR1A=0x2a; // 16 bit access sfrb TCNT1L=0x2c; sfrb TCNT1H=0x2d; sfrw =0x2c; // 16 bit access sfrb =0x2e; sfrb =0x2f; sfrb ASSR=0x30; sfrb OCR0=0x31; sfrb TCNT0=0x32; sfrb TCCR0=0x33; sfrb MCUCSR=0x34; sfrb MCUCR=0x35; sfrb TIFR=0x36; sfrb TIMSK=0x37; sfrb EIFR=0x38; sfrb EIMSK=0x39; sfrb EICRB=0x3a; sfrb RAMPZ=0x3b; sfrb XDIV=0x3c; sfrb =0x3d; sfrb =0x3e; sfrb =0x3f; #pragma used- #define DDRF (*(unsigned char*)0x61) #define PORTF (*(unsigned char*)0x62) #define PING (*(unsigned char*)0x63) #define DDRG (*(unsigned char*)0x64) #define PORTG (*(unsigned char*)0x65) #define SPMCSR (*(unsigned char*)0x68) #define EICRA (*(unsigned char*)0x6a) #define XMCRB (*(unsigned char*)0x6c) #define XMCRA (*(unsigned char*)0x6d) #define OSCCAL (*(unsigned char*)0x6f) #define TWBR (*(unsigned char*)0x70) #define TWSR (*(unsigned char*)0x71) #define TWAR (*(unsigned char*)0x72) #define TWDR (*(unsigned char*)0x73) #define TWCR (*(unsigned char*)0x74) #define OCR1CL (*(unsigned char*)0x78) #define OCR1CH (*(unsigned char*)0x79) #define TCCR1C (*(unsigned char*)0x7a) #define ETIFR (*(unsigned char*)0x7c) #define ETIMSK (*(unsigned char*)0x7d) #define ICR3L (*(unsigned char*)0x80) #define ICR3H (*(unsigned char*)0x81) #define OCR3CL (*(unsigned char*)0x82) #define OCR3CH (*(unsigned char*)0x83) #define OCR3BL (*(unsigned char*)0x84) #define OCR3BH (*(unsigned char*)0x85) #define OCR3AL (*(unsigned char*)0x86) #define OCR3AH (*(unsigned char*)0x87) #define TCNT3L (*(unsigned char*)0x88) #define TCNT3H (*(unsigned char*)0x89) #define TCCR3B (*(unsigned char*)0x8a) #define TCCR3A (*(unsigned char*)0x8b) #define TCCR3C (*(unsigned char*)0x8c) #define UBRR0H (*(unsigned char*)0x90) #define UCSR0C (*(unsigned char*)0x95) #define UBRR1H (*(unsigned char*)0x98) #define UBRR1L (*(unsigned char*)0x99) #define UCSR1B (*(unsigned char*)0x9a) #define UCSR1A (*(unsigned char*)0x9b) #define UDR1 (*(unsigned char*)0x9c) #define UCSR1C (*(unsigned char*)0x9d) //interrupt vectors definitions #define 2 #define EXT_INT1 3 #define EXT_INT2 4 #define EXT_INT3 5 #define EXT_INT4 6 #define EXT_INT5 7 #define EXT_INT6 8 #define EXT_INT7 9 #define TIM2_COMP 10 #define TIM2_OVF 11 #define TIM1_CAPT 12 #define TIM1_COMPA 13 #define TIM1_COMPB 14 #define TIM1_OVF 15 #define TIM0_COMP 16 #define TIM0_OVF 17 #define SPI_STC 18 #define USART0_RXC 19 #define USART0_DRE 20 #define USART0_TXC 21 #define 22 #define EE_RDY 23 #define ANA_COMP 24 #define TIM1_COMPC 25 #define TIM3_CAPT 26 #define TIM3_COMPA 27 #define TIM3_COMPB 28 #define TIM3_COMPC 29 #define TIM3_OVF 30 #define 31 #define USART1_DRE 32 #define USART1_TXC 33 #define TWI 34 #define SPM_RDY 35
Port 개수 = 총 7개 : PORT A,B,C,D,E,F,G -각각 = 8 bit, 양방향 IO Port!! 특수기능들 = 위 Port와겸용! Timer/Counter PWM output = 6개 (=PE3,4,5 및 PB5,6,7) RS-232 = 2개 (=PE0,1 및 PD2,3) interrupt = 8개 (=PE4,5,6,7 및 PD0,1,2,3) A/D Converter 입력 = 8개 (=PF0-7)..etc.. 레지스터 : -각레지스터 = 8비트. DDRA = 포트 A의데이터방향설정레지스터. (DDR=Data Direction Register) -각비트설정법 : (0= 입력, 1= 출력 ) 으로설정함!! ( 기타, 포트 B,C,D,. = DDRB,DDRC,DDRD,.. 임 ) PINA = 포트 A pin으로부터의데이터입력레지스터. ( 기타, 포트 B,C,D,. = PINB,PINC,PIND,.. 임 ) PORTA= 포트 A pin으로의데이터출력레지스터. ( 기타, 포트 B,C,D,. = PORTB,PORTC,PORTD,.. 임 ) 프로그램예 main() unsigned char led = 0xF0; //0xF0 = 0b11110000; unsigned char data; DDRA = 0xFF; // 포트 A의모든비트를출력으로설정. 0xFF = 0b11111111 DDRB = 0x00; // 포트 B의모든비트를입력으로설정. 0x00 = 0b00000000 data = PINB; // 포트 B로부터데이터를입력하여 data에넣음. PORTA = led; // 포트 A로데이터 led를출력. // ( 그러면 H/W적으로포트 A의 pin으로이데이터가나감! // (0=0V, 1=5V) } 위 C- 프로그램의컴파일러 = 사용법 = 본책맨앞에있음! long은안됨!!??..char, int, float만됨! char,int,float의데이터길이 = 1,2,4 byte ( 엄격!!) unsigned = 엄격히적용됨!! 즉, char=(-128)~(+127), unsigned char=0~255! int=(-32768)~(+32767), unsigned int=0~..
기능 : C 포트에연결되어있는 LED 를순차점멸한다. H/W 결선상태 : - C 포트의각비트에서 '0' 이출력될때, 해당 LED 가켜짐!! //===LED.c========================================= #include <mega128.h> #include <delay.h> //delay_ms(), delay_us() //----------------- void main(void) unsigned char led = 0b00000001; //0xFE; //LED 초기출력값 DDRC = 0xFF; //C 포트의모든핀을출력으로설정. 각비트설정법 : 0= 입력, 1= 출력 while(1) PORTC = ~led; //C 포트로 led 값을출력 : ~ = 비트반전 (C-언어의비트연산자 ) delay_ms(100); //delay led = led << 1; //led 변수를좌쉬프트 : << = 좌쉬프트 (C-언어의비트연산자 ) if(led == 0b00000000) led = 0b00000001; //led 변수초기화 }//while() }//main() < 참고 > delay 함수 : 상기의 delay_ms() 대신, 다음과같이 delay함수를만들어서사용해도됨! void Delay(unsigned int cnt) //delay 함수 unsigned int i, j; for(i=0; i<cnt; i++) // 딜레이횟수지정 j=50000; // 딜레이속도조절 while(--j); }//for() }//Delay() 다음각기능을수행하는프로그램을작성하여실험하시오. [ 문제 1] (D0-D7) 을모두다한꺼번에 ON -> OFF 반복하기 [ 문제 2] (D0-D3)->(D4-D7) 순으로 (4 비트씩 ) 깜박이기. 반복.? [ 문제 3] (D0 D7)->(D1 D6)->(D2 D5)->(D3 D4) 순으로 (2 비트씩 ) 깜박이기. 반복. [ 문제 4] D0-D2-D4-D6 순으로 (1 비트씩 ) 건너가며깜박이기. 반복. [ 문제 5] 랜덤갯수의 LED 깜박이기 : <hint> rand()=stdlib.h [ 문제 6] 랜덤으로 LED 한개씩깜박이기 : <hint> rand()=stdlib.h [ 문제 7] 1 비트씩이동하며깜박이기 : D0 -> D7 -> D0 순서로반복.
기능 : E 포트 (PE4,5,6,7) 에연결되어있는스위치를누르면 그상태를 C 포트의상위 LED 4 개에서점등한다. < 예 > PE4 에연결된스위치를누르면 PC4 에연결된 LED 만켜지고나머지는모두꺼짐. 같은방법으로, PE5 PC5, PE6 PC6, PE7 PC7 만이켜진다. H/W 결선상태 : 8 개의 LED 가 C 포트에연결되어있음...C 포트의각비트에서 '0' 이출력될때, 해당 LED 가켜짐!! 4 개의스위치가 E 포트 (PE4,5,6,7) 에연결되어있음.. 스위치를누르면 E 포트의해당비트는 '0' 됨!!.. 평소에는 '1' 임. ('0'=GND, '1'=Vcc) //===Key_LED.c========================================= #include <mega128.h> void main(void) unsigned char key; //--- 설정 DDRC = 0xFF; //C 포트핀전부를출력으로설정 : 0= 입력, 1= 출력 DDRE = 0b00001111; //E 포트의 PE4~PE7 비트 = 입력으로설정 (PB Switch 가연결되어있음 ) //E 포트의 PE0~PE3 비트 = 출력으로설정 PORTC = 0xFF; //C 포트의 8 개 LED = off //---잠깐테스트 : E포트의상위 4비트 = 입력설정, 하위 4비트 = 출력설정임. //PORTE = 0b00001000; //E 포트의 bit 3으로 '1' 출력 ( 테스트!!) = OK!! //---키보드입력테스트!! while(1) key = PINE 0x0F; //E 포트핀 ( 스위치상태 ) 읽어오고하위 4비트를 F로! PORTC = key; //C 포트에출력 ( 하위 4개의 LED는 Off) }//while() }//main 다음기능을하는프로그램을작성하여실험하시오. [ 문제 1] 스위치-1(PE4) 을누르고있는동안 => LED 의모든 bit (bit 0,1,2,3...7) 이켜짐스위치-2(PE5) 를누르고있는동안 => LED 의 bit 0,1,2,3 이켜지고나머지는꺼짐스위치-3(PE6) 을누르고있는동안 => LED 의 bit 4,5,6,7 이켜지고나머지는꺼짐스위치-4(PE7) 을누르고있는동안 => LED 의 bit 0,2,4,6 이켜지고나머지는꺼짐아무스위치도안누르면 => 모든 LED = OFF! [ 문제 2] 스위치 -1(PE4) 을한번눌렀다가떼면 => LED 8 개전체가깜박깜박.( 반복 ) 스위치 -2(PE5) 를한번눌렀다가떼면 => LED 가 D0-D1-D2-D3..-D7 순서로깜박임.( 반복 ) 그외다른스위치 (PE6,PE7) 를한번눌렀다가떼면 => LED 가모두꺼짐.
7-Segment LED = 7 개의 LED 를조합하여다양한패턴을나타낼수있게일체형으로만든것. 표현할수있는패턴 = 숫자.(0,1,2,3,4,5,6,7,8,9) 영문자.(A,B,C,D,E,F,G) 그외특수패턴일부. 통상 8 개의 LED 로구성됨 : 숫자 / 문자표시용 7 개 + 소수점 (dot) 표시용 1 개. 7-Seg LED 를구성하는각 LED 의특성은앞서의 LED 와동일. 7-Seg LED 의크기및 pin 치수 = 일반 IC 와동일. 7-Seg LED 의배치및패턴예 7-Seg LED 의종류 Common Anode 形 : 7 개의 LED 단자중 Anode 부분을모두묶어하나의외부 pin 으로만든것. Common Cathode 形 : 7 개의 LED 단자중 Cathode 부분을모두묶어하나의외부 pin 으로만든것. 각 LED 를선택적으로 ON/OFF 시킴으로써, 원하는패턴을나타내게할수있다.( 위그림 ) Common Anode 경우 : - 공통 Anode 단자에 Vcc 를걸고, - 점등하기를원하는 Segment(a,b,..) 에 GND 를건다. 소등하기를원하는 Segment(a,b,..) 에 Vcc 를건다. Common Cathode 경우 : - 공통 Cathode 단자에 GND 를걸고, - 점등하기를원하는 Segment(a,b,..) 에 Vcc 를건다. 소등하기를원하는 Segment(a,b,..) 에 GND 를건다. 7-Seg LED 제품예 : MAN6660 = Common Anode 形 ( 참고 : Driver IC = 7447) MAN6680 = Common Cathode 形 ( 참고 : Driver IC = 7448) Common Anode형의 Segment 불량검사방법 : - 3번 pin에 Vcc를달고, 다른 pin을 GND로하여검사. - 이때, GND한 pin에대응한 Segment가점등하면그 Segment = OK! 두경우 Pin 배치는동일하다.( 단지, Vcc,GND 유의 )
7-Seg LED Decoder/Driver 의필요성 : 7-Seg LED 로표시할수있는숫자 = 10 개.(0,1,..,9) 7-Seg LED 로이들숫자를표시하려면, 7-Seg LED 내의각 LED 를선택적으로 ON/OFF 시켜야한다. ( 매우번거로움 ) 한편, 10 개의숫자를나타내기위해서는 4 개의 bit 가필요하다. 즉, 0000 0 0001 1 0010 2 : 1001 9 이러한 4-bit 데이터로 7-Seg LED 를직접동작시키면편리하겠다. 7-Seg LED Decoder/Driver IC: 이러한기능을하는 IC = 7-Seg LED Decoder/Driver!! = 4-bit 데이터를입력으로받아서, 그에맞게 7-Seg LED 를동작시키는데이터를출력시키는 IC. (2 가지종류가있다 ) TTL = Common Anode 形 7-Seg LED 용 driver. 각 LED 에대해전류제한용저항이필요. TTL = Common Cathode 形 7-Seg LED 용 driver. 각 LED 에대해전류제한용저항이불필요!! (IC 에저항이내장되어있음 ) <pin 배치도 > 7447/7448 과 7-SegLED 접속도
기능 : 7-seg LED 2개를이용하여 2자리수를표시함. H/W 결선상태 : 7-seg LED를 ATmega에 A포트에다음과같이연결함. 10자리 LED = A포트상위 4비트에연결함. 1자리 LED = A포트하위 4비트에연결함. //===Display_7_SegLED.c======================= #include <mega128.h> #include <delay.h> //delay_ms() main() char i,k, Data; int ival; char N10, N1; //10,1자리수 //---포트설정------ DDRA = 0xFF; //A 포트 = 출력으로설정 : PA0-PA7= 7-segLED //===(1) Simple Usage======= ival = 12; //---display용환산 N10 = ival / 10; //10자리수추출 N1 = ival % 10; // 1자리수추출 //---display 시행 PORTA = (N10 << 4) + N1; //===(2) 0-20까지증가하면서 Display======= for(ival = 0; ival <= 20; ival++) //---display용환산 N10 = ival / 10; //10자리수추출 N1 = ival % 10; // 1자리수추출 //---display 시행 PORTA = (N10 << 4) + N1; delay_ms(200); //delay 200[ms] } //===(3) 구구단 Display : 표시방식예 : 23 표시후 6 표시 ======= for(i=2; i<=9; i++) for(k=1; k<=9; k++) //---입력값 Data = i; Data = (Data << 4) + k; PORTA = Data; //display delay_ms(500); //delay //---결과값? Data = i * k; N10 = Data / 10; //10자리수추출 N1 = Data % 10; // 1자리수추출 PORTA = (N10 << 4) + N1; delay_ms(500); //delay }//for(k) }//for(i) }//main()
-ref = 책 "AVR ATmega128", p.307,317, 신동욱, 오창헌저, Ohm사. -ref = 책 알기쉽게배우는 AVR ATmega128" p.307-335, 신동욱 / 오창헌공저, Ohm사 LCD = 16문자 x 2행 LCD 특징 : 표준화된인터페이스!! / 5V 구동 / 폰트 =5x7 or 5x10 / 데이터버스 = 8-bit or 4-bit / C.G.RAM, C.G.ROM, D.D.RAM 내장 (C.G=Character Generator, D.D=Data Display) LCD 모듈의핀번호, 기능 : 14 pin ( 표준화된인터페이스!!) : [Pin No]-[ 기호 ]-[ 기능 ] 1 Vss GND 2 Vdd +5V 3 Vo 밝기조절용.(=GND 연결무난 OK!) 4 RS Register Select : 0=instruction /1=Data 5 R/W' 0=Write /1=Read ( 주체 =CPU) 6 E LCD Enable 신호 : 0=LCD가동작안함 /1=LCD가동작함 7 DB0 Data 0 8 DB1 Data 1 : : : 14 DB7 Data 7 15,16 A,K (= 백라이트용 LED = 불용OK!) (2 개 ) : IR,DR 의선택 = RS(pin 4) 에의해선택됨. IR (Instructiion Register) : 여러개의제어명령어를입력하는곳. DR (Data Register) : 이곳에써넣은데이터는 LCD 에표시됨. (CPU 는읽기 / 쓰기가능 ) [ 표 ] RS와 R/W' 에의한레지스터선택 RS R/W' 동작 0 0 IR 쓰기동작 0 1 BF(Busy Flag) 와 Address Counter 읽기 1 0 DR 쓰기동작 : DR D.D.RAM, C.G.RAM 1 1 DR 읽기동작 : DR D.D.RAM, C.G.RAM = LCD를제어하기위한명령어. ( 이는데이터버스를통해전송됨 )... 이하, 실행시간 (f osc = 250KHz 기준 ) 1 표시클리어 = LCD 화면을클리어 / 커서는홈위치로 (1행1열위치 ) / D.D.RAM의어드레스카운터 =0 됨! 2 커서홈 = 커서는홈위치로 (1행1열위치 ) / D.D.RAM의어드레스카운터 =0 됨!
3 엔트리모드셋 = 커서의이동방향설정 / 디스플레이를이동시킬지여부를설정. ATmega128 인터페이스프로그래밍 <bit> I/D = 문자코드를 D.D.RAM or C.G.RAM 에써넣거나읽을때, 어드레스를 +1,-1 하기위한설정비트. <bit> S = D.D.RAM 에데이터를써넣은후에, 표시전체를좌 / 우로이동시키기위한설정비트. <bit> I/D = 1 : 어드레스를 +1 하고, 커서를우로이동시킴. 0 : 어드레스를 -1 하고, 커서를좌로이동시킴. <bit> S = 0 : 디스플레이를이동하지않음. 1 : (& I/D=1 일때 ) 표시전체가좌로이동함. S=1 이면, 커서위치 = 불변임. (& I/D=0 일때 ) 표시전체가우로이동함. 4 표시 ON/OFF 제어 = 전체표시 ON/OFF / 커서 ON/OFF / 커서위치의문자깜박임설정. 커서 : 5x7 폰트에서커서 =8 째줄 / 5x10 폰트에서커서 =11 째줄임. <bit> D = 1 : LCD 전체가 ON( 글자가표시됨 ) / D=0: OFF! (D.D.RAM 내용 = 그대로임 ) <bit> C = 1 : 커서가나타남 / C = 0 : 사라짐. <bit> B = 1 : 커서가깜박임 / B = 0 : not 5 커서 / 표시이동 = D.D.RAM 내용을변경하지않은상태에서 : 커서의이동 / 표시전체의이동설정용. 커서이동 : 첫라인마지막칸 (40) 에서다음라인으로넘어감. 표시이동 : 첫라인과다음라인이동시에이동함. ( 상하이동 = 불가 ) <bit> S/C R/L = 0 0 : 커서가좌로이동 (AC 는 -1 됨 ) 0 1 : 커서가우로이동 (AC 는 +1 됨 ) 1 0 : 표시와커서가좌로이동 1 1 : 표시와커서가우로이동 6 펑션셋 = 인터페이스길이 / 표시행수 / 문자폰트설정용. <bit> DL = 1 : 8-bit 데이터로설정 0 : 4-bit 데이터로설정 -(DB7-DB4 가사용됨. 전송 = 상위 4 bit 이후하위 4 bit!) <bit> N F = 0 0 : 표시라인 = 1 / 글자폰트 = 5x7 도트 / 듀티비 = 1/8 0 1 : 표시라인 = 1 / 글자폰트 = 5x10 도트 / 듀티비 = 1/11 1 * : 표시라인 = 2 / 글자폰트 = 5x7 도트 / 듀티비 = 1/16 7 C.G.RAM 어드레스설정 = C.G.RAM 의어드레스를설정함. 아래 (11) 과관련!! 이어드레스의설정후에 C.G.RAM 의데이터를읽고쓸수있음. 8 D.D.RAM 어드레스설정 = D.D.RAM 의어드레스를설정함. 아래 (11) 과관련!! 이어드레스의설정후에 D.D.RAM 의데이터를읽고쓸수있음. 9 B/F 어드레스읽기 = B/F(Busy Flag) 와어드레스카운터의내용을읽기. B/F = LCD 내부동작상태확인용. B/F = 1 이면 : LCD 내부동작중임. (LCD = 명령을받아들일수없음의미 ) 0 이면 : LCD 에명령어쓰기허락임. 10 C.G.RAM, D.D.RAM 으로데이터쓰기 = C.G.RAM or D.D.RAM 에 8-bit 데이터를쓴다. < 단 > C.G.RAM or D.D.RAM 의선택 = 이전에어드레스값이설정된 RAM 이선택된다. 엔트리모드 에따라, 어드레스 = +1 or -1 된다. 11 C.G.RAM, D.D.RAM 으로데이터읽기 = C.G.RAM or D.D.RAM 으로부터 8-bit 데이터를읽는다. < 단 > 읽기명령을하기전에, 반드시 C.G.RAM or D.D.RAM 의어드레스설정명령을실행해야함!... 만일, 이어드레스설정명령을하지않으면 : 첫번째데이터는무효가되고, 두번째데이터부터정상적으로읽혀짐!
전원 ON & 전원 Vdd 가 4.5V 이상된후, 15ms 이상지연!!! 펑션셋 : (RS=0, R/W'=0) : D7 D0 = 0 0 1 0 N F 0 0 표시 ON : (RS=0, R/W'=0) : D7 D0 = 0 0 0 0 1 1 C B 표시클리어 : (RS=0, R/W'=0) : D7 D0 = 0 0 0 0 0 0 0 1 엔트리모드 : (RS=0, R/W'=0) : D7 D0 = 0 0 0 0 0 1 I/D S LCD 초기화완료.. 프로그램시, LCD 의 Busy Flag(BF) 를조사하는대신시간지연함수를사용고려! LCD 모듈의 Read/Write 타이밍도 (= 프로그램시이용!!) (E: 1 0 순간 LCD 는문자읽음 )!!!
(LCD 의 8-bit 데이터방식사용!) 기능 : LCD 에다음의문자열을출력한다. (LCD = 16 문자 x2 행 ) ABC-D Hello!! Success! H/W 결선상태 : 8- 비트데이터방식사용! 따라서, LCD 결선 = AVR 포트 2 개 (Port C, D) 필요!! 즉, Control = Port C0,1,2 사용 & Data = Port D0 7 사용 LCD = 16 문자 x2 행 //------------------ <H/W 검사 > 회로대로꾸민후, 전원을넣으면 //------------------ LCD 에검은블럭들이일렬로나타남. < 유의 > 프로그램시, LCD 의 Busy Flag(BF) 를조사하는대신, 시간지연함수를사용함! //===LCD_Display_8bit_Data.c======================= #include <mega128.h> #include <delay.h> //delay_us(), delay_ms() =[us],[ms] #include <stdio.h> //sprintf() for LCD //---define LCD COMMANDS (LCD Display)------- < 비교 > LCD 의 4-bit 데이터방식 (= 간편!!) =[ 부록 4] 참조! <LCD 출력회로 > 8-bit data 방식 #define LCD_FUNCSET 0b00111000 //=0x38 =Function Set (8-bit Data!!, 표시라인 =2, 폰트 =5x7) #define LCD_ENTMODE 0b00000110 //=0x06 =Entry Mode Set ( 커서의이동방향과디스플레이이동여부결정 ) #define LCD_ALLCLR #define LCD_DISPON 0b00000001 //=0x01 =All Clear 0b00001100 //=0x0C =Display ON #define LCD_DISPOFF 0b00001000 //=0x08 =Display OFF #define LCD_HOME #define LCD_LINE2 #define LCD_RSHIFT #define LCD_LSHIFT //---functions-------------------- 0b00000010 //=0x02 =Cursor LCD_HOME 0b11000000 //=0xC0 =2nd Line Move -< 관련 >D.D.RAM addr :1-line=0x00-0x27, 2-line=0x40-0x67. 0b00011100 //=0x1C =Display Right Shift 0b00011000 //=0x18 =Display Left Shift void LCD_initialize(void); // LCD 초기화함수..book p.316 void send_command_to_lcd(unsigned char byte); //LCD 에 Command( 문자 1 개 ) 쓰기함수 (RS=0, R/W=0) // = LCD-Write Timing Chart 구현! void send_1chardata_to_lcd(unsigned char byte); //LCD 에 Data( 문자 1 개 ) 쓰기함수 (RS=1, R/W=0) // = LCD-Write Timing Chart 구현! void send_stringdata_to_lcd(unsigned char str[]); //LCD 에 Data( 문자열 1 개 ) 쓰기함수 (RS=1, R/W=0) //========================================================= main() unsigned char string[] = " Hello!!"; unsigned char stringa[] = "Success"; LCD_initialize(); // LCD 초기화 send_command_to_lcd(lcd_home); //Cursor LCD_HOME send_1chardata_to_lcd('a'); send_1chardata_to_lcd('b'); < 유의 > LCD = 문자 (char) 만 display 한다!!! send_1chardata_to_lcd('-'); send_1chardata_to_lcd('d'); send_command_to_lcd(lcd_home); //1st Line Move send_stringdata_to_lcd(string); send_command_to_lcd(lcd_line2); //2nd Line Move send_stringdata_to_lcd(stringa); }//main()
//===Used Functions (LCD Display)================================= void LCD_initialize(void) // LCD 초기화함수..book p.316 //---AVR-LCD interface init--- DDRC = 0xFF; //C포트 all bit = 출력으로설정..LCD-interface: PC0=RS, PC1=R/W', PC2=E DDRD = 0xFF; //D포트 all bit = 출력으로설정..LCD-interface: PD0-7 = Data0-7 //---LCD init----------------- //...send command... send_command_to_lcd(lcd_funcset); //Function Set send_command_to_lcd(lcd_dispon); //Display ON send_command_to_lcd(lcd_allclr); //All Clear send_command_to_lcd(lcd_entmode); //Entry Mode Set }//LCD_initialize() void send_command_to_lcd(unsigned char byte) //LCD에 Command( 문자 1개 ) 쓰기함수 (RS=0, R/W=0) //..This routine = LCD-Write Timing Chart 구현!!! //..interface: (PC0=RS, PC1=R/W', PC2=E), (PD0-7 = DATA0-7) delay_ms(2); //Busy Flag(BF) check -by 단순히시간지연이용! PORTC = 0b00000000; //set RS=0, R/W=0, E=0..(E=Enable) //RS:0=instraction/1=Data, R/W:0=Write/1=Read, E:1->0순간 LCD는문자읽음. delay_us(1); PORTC = PORTC 0b00000100; //set E=1! -with (RS=0, R/W=0)..(E: 1->0순간 LCD는문자읽음 ) delay_us(1); PORTD = byte; // 문자를 LCD에게보내기 delay_us(1); PORTC = PORTC & 0b11111011; //set E=0! -with (RS=0, R/W=0)..(E: 1->0순간 LCD는문자읽음 ) }//send_command_to_lcd() void send_1chardata_to_lcd(unsigned char byte) //LCD에 Data( 문자 1개 ) 쓰기함수 (RS=1, R/W=0) //..This routine = LCD-Write Timing Chart 구현!!! //..interface: (PC0=RS, PC1=R/W', PC2=E), (PD0-7 = DATA0-7) delay_ms(2); //Busy Flag(BF) check -by 단순히시간지연이용! PORTC = 0b00000001; //set RS=1, R/W=0, E=0..(E=Enable) //RS:0=instraction/1=Data, R/W:0=Write/1=Read, E:1->0순간 LCD는문자읽음. delay_us(1); PORTC = PORTC 0b00000100; //set E=1! -with (RS=1, R/W=0)..(E: 1->0순간 LCD는문자읽음 ) delay_us(1); PORTD = byte; // 문자를 LCD에게보내기 delay_us(1); PORTC = PORTC & 0b11111011; //set E=0! -with (RS=1, R/W=0)..(E: 1->0순간 LCD는문자읽음 ) }//send_1chardata_to_lcd() void send_stringdata_to_lcd(unsigned char str[]) //LCD에 Data( 문자열 1개 ) 쓰기함수 (RS=1, R/W=0) int i; for(i=0; str[i]; i++) send_1chardata_to_lcd(str[i]); }//send_stringdata_to_lcd()
!!! LCD 는문자 (char) 만을입력으로받아 display 한다. ATmega128 인터페이스프로그래밍 따라서, 숫자 (int, float) 를표시하고싶으면 : 이숫자를문자열로만들어표시해야한다!! 방법 : sprintf() 함수를이용하면편리! <ex> int a = 128; float b = 25.674; unsigned char str[100]; sprintf(str, "%d", a); a 값을문자열로만들어 char 배열 str[] 에넣음! sprintf(str, "%f", b); b 값을문자열로만들어 char 배열 str[] 에넣음! < 주의 > (CodeVisionAVR Compiler) : - long은안됨!!..char, int, float만됨! - char,int,float의데이터길이 = 1,2,4 byte ( 엄격!!) - unsigned = 엄격히적용됨!! 즉, char=(-128)~(+127), unsigned char=0~255 int=(-32768)~(+32767), unsigned int=0~.. #include<math.h> //for fabs()!!! int i, N = 3; //N = 소수점이하자리수 (float 표시할때이용됨 ) int idata1, idata2, idata; float fdata; //<!> 아래프로그램에서,---------------------------- unsigned char Buf[50],str1[50],str2[50]; // LCD_Command( ) = send_command_to_lcd( ) 의미! LCD_init(); //LCD 초기화 // LCD_String( ) = send_stringdata_to_lcd( ) 의미! //---LCD 에 int data 출력 --- //--------------------------------------------- idata1 = 567; idata2 = 9876; LCD_Command(LCD_HOME); sprintf(buf, " %d", idata1); LCD_String(Buf); // 문자열출력 sprintf(buf, " %d <===", idata2); LCD_String(Buf); // 문자열출력 //Cursor LCD_HOME //--LCD 에 float data 출력 ---------float = 소수점이하 3 자리까지만유효함!!! (by test) //< 주의 > sprintf(buf, " %f", fdata); = 안됨!!?? (I don't know WHY?) N = 3; //set 소수점이하자리수 (float 표시할때 ), < 주의 > 소수점이하더욱정밀한수 = double 사용필요함!! fdata = -12345.065; //target float data!! //...(1) 소수점윗자리를문자열로만들어 str1[] 에넣기... idata = fdata; // 소수점이하버리기 sprintf(str1, "%d", idata); //...(2) 소수점아랫자리를문자열로만들어 str2[] 에넣기 (= 소수점첫째자리의수가 0 일경우의극복법!)... fdata = fabs(fdata); //delete sign! (= 음수대책용!) idata = fdata; for(i=0; i<n; i++) //N = 소수점이하표시자리수 }//for(i) fdata = fdata - idata; //now, fdata= 소수점이하만인수! fdata = fdata * 10; // 소수점이상 1 자리수만듬 idata = fdata; //1 자리수 only str2[i] = idata + 0x30; //make into ASCII code value! (see ASCII table!) str2[i] = '\0'; //add NULL for string in str2[]!! //...(3) 소수점윗자리, 아랫자리합쳐서완성하여 Buf[] 에넣기... sprintf(buf, "%s.%s", str1, str2); // 실수 (float) 를문자열로완성함. LCD_Command(LCD_LINE2); LCD_String(Buf); // 문자열출력 }//main() //2nd Line Move LCD 첫째줄에정수 (int) 값 2 개를 display 하고, 둘째줄에실수 (float) 값 2 개를 display 하는데, 이때, 각각의값들을 1 씩증가시키면서반복적으로 display 하는프로그램을작성하기.
기능 : LCD 에다음의문자열을출력한다. Hello!! -ATmega! You Success!! <LCD 출력회로 > 4-bit data 방식 H/W 결선상태 : 4-비트데이터방식사용! 따라서, LCD 결선 = AVR 포트 1개 (Port D) 만필요!! //------------------ <H/W 검사 > 회로대로꾸민후, 전원을넣으면 LCD에검은블럭들이일렬로나타남. //------------------ < 유의 > 프로그램시, LCD의 Busy Flag(BF) 를조사하는대신, 시간지연함수를사용함! //===LCD_Display_4bit_Data.c==================== #include <mega128.h> #include <delay.h> //delay_us(), delay_ms() =[us],[ms] #include <stdio.h> //sprintf() for LCD #include <string.h> //strlen() for LCD //---define LCD COMMANDS (LCD Display)------- #define LCD_FUNCSET 0b00101000 //=0x28 =Function Set (4-bit Data!!, 표시라인 =2, 폰트 =5x7) #define LCD_ENTMODE 0b00000110 //=0x06 =Entry Mode Set ( 커서의이동방향과디스플레이이동여부를결정 ) #define LCD_ALLCLR 0b00000001 //=0x01 =All Clear #define LCD_DISPON 0b00001100 //=0x0C =Display ON #define LCD_DISPOFF 0b00001000 //=0x08 =Display OFF #define LCD_HOME 0b00000010 //=0x02 =Cursor LCD_HOME #define LCD_LINE2 0b11000000 //=0xC0 =2nd Line Move -< 관련 >D.D.RAM addr :1-line=0x00-0x27, 2-line=0x40-0x67. #define LCD_RSHIFT 0b00011100 //=0x1C =Display Right Shift #define LCD_LSHIFT 0b00011000 //=0x18 =Display Left Shift //---used Functions (LDC Display)----------- void LCD_init(void); // LCD 초기화함수 void LCD_Command(unsigned char byte); // 인스트럭션 ( 명령어 ) 쓰기함수 void LCD_Data(unsigned char byte); // 문자 1개쓰기함수 void LCD_String(unsigned char str[]); // 문자열출력함수 //========================================================= void main() int i; unsigned char Buf[50]; LCD_init(); //LCD 초기화 //---LCD에문자열출력--- LCD_Command(LCD_HOME); sprintf(buf, "Hello!!"); LCD_String(Buf); // 문자열출력 sprintf(buf, " -ATmega!"); LCD_String(Buf); // 문자열출력 //Cursor LCD_HOME LCD_Command(LCD_LINE2); //2nd Line Move sprintf(buf, "You Success!!"); LCD_String(Buf); // 문자열출력 }//main() //===Used Functions (LCD Display)=================================
void LCD_init(void) // LCD 초기화함수 //---AVR-LCD interface init--- DDRD = 0xFF; //D 포트 all bit = 출력으로설정 PORTD = PORTD & 0xFB; //E=0 : E=Enable pin, 0xFB==0b11111011 ATmega128 인터페이스프로그래밍 //---LCD init (send command)--:<! 주의!>-- 이곳 ( 윈래책의 ) 일정부분 routine = 생략한상태임! ( 없어도되므로!) LCD_Command(LCD_FUNCSET); //Function Set LCD_Command(LCD_DISPON); //Display ON LCD_Command(LCD_ALLCLR); //All Clear LCD_Command(LCD_ENTMODE); //Entry Mode Set }//LCD_init() void LCD_Command(unsigned char byte) // 인스트럭션 ( 명령어 ) 쓰기함수 delay_ms(2); //Busy Flag(BF) check -by 단순히시간지연이용! //--- 인스트럭션상위바이트 --- PORTD = (byte & 0xF0); // 데이터 ( 명령어 ) PORTD = PORTD & 0xFE; //RS = 0 :0=instraction/1=Data : FE = 1111 1110 PORTD = PORTD & 0xFD; //RW = 0 :0=Write/1=Read : FD = 1111 1101 delay_us(1); PORTD = PORTD 0x04; //E = 1 : Enable 신호 : 04 = 0000 0100 delay_us(1); PORTD = PORTD & 0xFB; //E = 0 : Enable 신호 : FB = 1111 1011 //--- 인스트럭션하위바이트 --- PORTD = ((byte << 4) & 0xF0); // 데이터 ( 명령어 ) PORTD = PORTD & 0xFE; //RS = 0 :0=instraction/1=Data PORTD = PORTD & 0xFD; //RW = 0 :0=Write/1=Read delay_us(1); PORTD = PORTD 0x04; //E = 1 : Enable 신호 delay_us(1); PORTD = PORTD & 0xFB; //E = 0 : Enable 신호 }//LCD_Command() void LCD_Data(unsigned char byte) // 문자 1 개쓰기함수 delay_ms(2); //Busy Flag(BF) check -by 단순히시간지연이용! //--- 문자데이터상위바이트 --- PORTD = (byte & 0xF0); // 데이터 ( 문자 ) PORTD = PORTD 0x01; //RS = 1 :0=instraction/1=Data PORTD = PORTD & 0xFD; //RW = 0 :0=Write/1=Read delay_us(1); PORTD = PORTD 0x04; //E = 1 : Enable 신호 delay_us(1); PORTD = PORTD & 0xFB; //E = 0 : Enable 신호 //--- 문자데이터하위바이트 --- PORTD = ((byte << 4) & 0xF0); // 데이터 ( 문자 ) PORTD = PORTD 0x01; //RS = 1 :0=instraction/1=Data PORTD = PORTD & 0xFD; //RW = 0 :0=Write/1=Read delay_us(1); PORTD = PORTD 0x04; //E = 1 : Enable 신호 delay_us(1); PORTD = PORTD & 0xFB; //E = 0 : Enable 신호 }//LCD_Data() void LCD_String(unsigned char str[]) // 문자열출력함수 while(*str) LCD_Data(*str++); //LCD_Data()= 문자 1 개쓰기함수 }//LCD_String()
A/D 변환 = 아날로그신호를디지털신호로변환시켜주는것. < 개념 : A/D 변환구성도및동작해설 > S/H (Sample and Holder) = 변화하는아날로그신호를샘플링하여일정값으로유지해줌. A/D Converter = 아날로그신호를디지털신호로변환시켜줌. Conversion time = Analog 신호를 Digital 신호로변환하는데소요되는시간. A/D Converter IC 구입시유의사항 : - Digital output 의 Bit 수 - Conversion time - Voltage level (Vcc 및 Digital output) 동작처리순서 1 Analog Input을준다 2 8개의입력채널중하나를선택한다 (by 3-bit Address를지정 ) 3 START 신호를준다 4 End Of Conversion 신호의 rising edge를받으면 8-bit Digital Output을받는다.
ATmega128 = 10 비트분해능의 A/D 변환기가 8- 채널있음 : ADC0,ADC1,..,ADC7 (=F Port 공용 ) 입력채널 = multiplexer 에의해 A/D 변환기와연결됨. 변환시간 = 13-260 us 기준전압 = 2.56[V] 내부전압 or 외부전압사용. Sample/Hold 회로내장. 관련 pin : AD 입력핀 = (F 포트 )PF0-PF7 = ACD0 - ADC7! 전원및기준전압관련핀 = AVCC,GND,AREF(=pin 64,63,62) 기준전압 Vref = A/D 변환시사용되는기준전압 (max 전압 ) ADC 입력은 0-Vref[V] 사이값이어야함. 기준전압에대한변환후데이터값 : 0-Vref = 0-0x3F 값에해당. (0x3F = 1023) for 1024 내부 / 외부기준전압선택사용 : - 내부기준전압 = 2.56[V] 제공. H/W 결선 = 공통 : AGND 를 GND 와접속. - 외부기준전압 = 외부회로설치 : 관련 pin= AREF,AGND,AVCC(=62,63,64 번핀 ) 내부기준전압사용시 : AREF 와 AGND 사이를콘덴서 (104) 로접속 & AVCC 를 +5[V] 와접속 외부기준전압사용시 : AREF 와 AGND 사이를콘덴서 (104) 로접속 & AVCC 를 AREF 와접속 & AREF 와 +5[V] 사이를코일 (L=10[uH]) 로접속! ATmega128 의 A/D 변환결과값 = (Analog 입력전압값 / Vref) x 1023! (- 이결과값의 range = 0-1023!) ADC 레지스터 : ADMUX ( 디지털값 ).. 이는 AD 변환기데이터레지스터 (16 비트 ) 에저장됨. : bit (7,6)= 기준전압선택 : (00)= 외부기준전압사용, (11)= 내부기준전압 (2.56V) 사용 bit (5) = 변환결과를 ADCH,ADCL 에저장하는형식 : (0)=ok! bit (4-0)= 입력채널선택 : (00000)=ADC0, (00001)=ADC1,.., (00111)=ADC7 ADCSRA : bit (7)=ADEN(=ADC Enable bit) : (1)=ADC Enable 로설정됨, bit (6)=ADSC(=ADC Start bit) : (1)=AD 변환시작시킴!, bit (5)=ADFR(=Free Running 모드 ) : (1)=Free Running 모드로설정, bit (4)=ADIF(=AD 변환완료 flag) : 변환이완료되면 (1) 로됨! ( 이 bit 에 1 을쓰면, ADIF 는 clear 됨!) bit (3)=ADIE(=AD 인터럽트 Enable) : (1)= 인터럽트인에이블! bit (2-0)=AD 변환기에입력되는시스템클럭에의분주비선택 : (111)=128 (=125KHz!) ADCH,ADCL: =AD 변환결과값저장레지스터.( 결과값 =10 비트 ) <!!>!!: AD 변환종료후반드시하위값부터읽어야함!!! ( 상위값부터읽으면하위에어떤값이들어갈수있기때문!)
기능 : ADC0 pin으로아날로그신호입력하고. 그결과값을 LCD에출력한다. (= 소수점이하두자리표시 ) H/W 결선상태 : AD 입력핀 = (F포트)PF0-PF7 = ACD0 - ADC7! 전원및기준전압관련핀 = AVCC,GND,AREF(=pin 64,63,62) //===A/D.c======================= #include <mega128.h> #include <delay.h> //delay_ms(), delay_us() = [ms],[us] #include <stdio.h> //sprintf() for LCD #include <string.h> //strlen() for LCD #include <math.h> //fabs() for LCD void LCD_init(void); //LCD 초기화함수 void Display_LCD(unsigned char Channel, float fdata); //LCD display ( 소수점 2자리까지 -ex: 3.25) main() unsigned char Channel; int ad_value; //ad_value = AD변환결과값 float fvalue, Vref; //fvalue = 실제전압값 ( 환산값 ) -from ad_value LCD_init(); // LCD 초기화!!! //---포트설정------ DDRF = 0x00; //F 포트 = 입력으로설정.(=ACD 입력단!!) //---do ADC!!------Channel 0를반복적으로ADC 처리및 LCD로출력. Channel = 0; //A/D 채녈 0 설정. while(1) //---ADC 채널선택 & 초기화 -- ADMUX = 0b00000000 Channel; //ADC0 채널선택, 단극성입력, 외부기준전압 (Vref) 으로설정. ADCSRA = 0x87; //=0b10000111 : AD변환정지!, ADC = Enable, 16MHz의 128분주 (=125 KHz) 로설정. delay_ms(5); //delay반드시필요!! -by test!! ( 잘안되면더길게!!!) //---AD 변환수행--- ADCSRA = 0xC7; //=0b11000111 : AD변환시작!, ADC = Enable, AD완료bit=0. while((adcsra & 0x10) == 0) ; //ADIF=1이될때까지기다림. delay_ms(5); //delay반드시필요!! -by test!! ( 잘안되면더길게!!!) ad_value = (int)adcl + ((int)adch << 8); //AD변환결과값읽어오기. //!< 주의 >! ad_value = ((int)adch << 8) + (int)adcl; = 안됨!! -by TEST!! //---실제전압값으로환산-- Vref = 4.80; // H/W보드에서 AREF pin 전압의실제측정값으로해야함!( 유의 ) <=( 통상 Vcc =5[V]!) fvalue = ((float)ad_value / 1023.0) * Vref; //= 실제의아날로그입력전압값!! //---LCD Display-- Display_LCD(Channel, fvalue); //AD변환값을 LCD에표시. }//while() }//main() void Display_LCD(unsigned char Channel, float fdata) //LCD display ( 소수점 2자리까지 -ex: 3.25) int i, N = 2; //N = 소수점이하자리수 (float 표시할때 ) int idata; unsigned char Buf[50],str1[50],str2[50];
//--- //LCD_init(); //LCD 초기화 = 위의 main() 에서수행했음! ATmega128 인터페이스프로그래밍 //--LCD에 float data 출력--------- 소수점이하 3자리까지만유효함!(by test) ////< 주의 > sprintf(buf, " %f", fdata); = 안됨!?! //...(1) 소수점윗자리를문자열로만들어 str1[] 에넣기... idata = fdata; // 소수점이하버리기 sprintf(str1, "%d", idata); //...(2) 소수점아랫자리를문자열로만들어 str2[] 에넣기 (= 소수점첫째자리의수가 0일경우의극복법!)... fdata = fabs(fdata); //delete sign! (= 음수대책용!) idata = fdata; for(i=0; i<n; i++) //N = 소수점이하표시자리수 fdata = fdata - idata; //now, fdata= 소수점이하만인수! fdata = fdata * 10; // 소수점이상 1자리수만듬 idata = fdata; //1자리수 only str2[i] = idata + 0x30; //make into ASCII code value! (see ASCII table!) }//for(i) str2[i] = '\0'; //add NULL for string in str2[]!! sprintf(buf, "(%d)%s.%s ", Channel, str1, str2); // 실수 (float) 를문자열로완성함. LCD_Command(LCD_HOME); //1st Line Move LCD_String(Buf); // 문자열출력 }//Display_LCD() A/D 채녈 0,1,2 로부터 3 개의아날로그전압을입력받아, 이모두를 LCD 에 display 하는프로그램을작성하라. ( 측정하여 display 하는작업을반복할것 )
D/A 변환 = 디지털신호를아날로그신호로변환시켜주는것. <ex> D/A 용 IC = "DAC0800" ( 사다리형 D/A 변환기 ) < 회로분석 >-by 절점해석법..where, 의혼합입력 = 중첩의원리로해결됨!
(a) 경우 : a점 : b점 : c점 : -1-2 -3 2,3 의 를 1 에대입 : (b) 경우 : a점 : b점 : c점 : -1-2 -3 2,3 의 를 1 에대입 :!!!! (c), (d) 경우 : = 같은방법!! 기능 : B포트로출력한 Digital신호에대한 Analog신호 ( 전압 ) 을구한다. H/W 결선상태 : B포트의 8-비트에 D/A 변환회로 (R-2R회로) 가결선되어있음. //===D/A.c======================= #include <mega128.h> #include <delay.h> //delay_ms(), delay_us() = [ms],[us] main() unsigned char data; DDRB = 0xFF; //B 포트의모든핀을출력으로설정 : 0= 입력, 1= 출력 data = 0b00000010; // 디지털출력겂 PORTB = data; }//main() //B 포트로값을출력 위프로그램에서, data 값으로서여러값을주고, 이때포트 B 의각비트에서출력되는전압과 Analog 출력값 ( ) 의전압을전압계로측정하여 아래표를완성하라.
data 0b0000 0000 0b0000 0001 0b0000 0010 0b0000 0011 0b0000 0100 포트 B 의각비트출력전압값 [V] PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 Analog 출력값 [V] 0b0000 1000 0b0001 0000 0b0010 0000 0b0100 0000 0b1000 0000 0b1000 0001 0b1000 0010 0b1111 1110 0b1111 1111 D/A 변환으로 sin 파를만들어라. - 리포트검사 = 오실로스코프로측정하여검사! <hint> -<! 특별검사!> 오실로스코프 & 펑션제너레이터사용능력검사!! for(angle=0; 1; angle=angle+0.01) value = sin(angle); //then, -1 <= value <= +1 PORTB = data; //(ex) data = (value + 1)*255? }
일반적으로, MCU 에서입력을받아들이는방법 = 2 가지. 1 폴링 (polling) 방식 = 사용자가외부입력의변화를알아내기위해, 외부입력의값을계속읽어보는방식. 2 인터럽트 (interrupt) 방식 = MCU 자체가 H/W 적으로외부입력의변화를체크하여, 외부입력의변화시에 만사용자의프로그램이그에대한동작을수행하도록하는방식. 인터럽트가발생하면 MCU 는지금까지실행하던프로그램을일단중단하고, 사용자가미리정해놓은 인터럽트서비스루틴 을실행한다. 이루틴의실행이끝나면다시원래실행하던 프로그램으로돌아가서하던일을계속한다. [ 비교 ]: 폴링 = 모든경우의입력또는값의변화에대응하여처리가가능하지만, 인터럽트 = H/W 적으로지원되는몇개의입력또는값의변화에만대응처리가가능하며, 처리속도는통상인터럽트가더빠르다. 인터럽트소스 = 인터럽트를발생시키는주체. (ex: 외부입력핀, 카운터, Serial 포트등 ) 인터럽트벡터테이블 = 인터럽트발생시이인터럽트를처리하는프로그램 (= 인터럽트서비스루틴 ) 의 초기주소를기록해놓은곳 ( 테이블 ). (= 인터럽트점프테이블 이라고도함 ) 인터럽트서비스루틴 = 인터럽트발생시, 이인터럽트를처리하는프로그램.(= 함수 ). (= 인터럽트핸들러 라고도함 )
: INT0 INT7 = 외부인터럽트요구 0-7 ( 해당외부 pin = 포트 E의 bit 4 7, 포트 D의 bit 0 3) TIMERx.. = 타이머 / 카운터관련인터럽트 10개 < 특이법 > 외부인터럽트 INT0 INT1을 S/W적으로인터럽트를발생시키는법 : ADC = ADC 변환완료 = 이들 pin을출력모드로설정하고, UART0 관련 = RS232(UART0) 수신완료, 외부인터럽트를 enable해놓으면됨!! 전송완료, 데이터레지스터빔 (ref= book p.129 맨위 ) SPI, STC = SPI 직렬전송완료 ANALOG COMP = 아날로그비교기 RESET = 외부리셋, 등.. -여기서, 인터럽트소스명 은해더파일에 (mega128.h) 에정의된소스명사용.(= 고유명사 ) < 예 > 외부인터럽트0 (INT0) 의경우 : interrupt [EXT_INT0] void ext_int0(void) < 예 > 인터럽트소스명 : 외부 int = EXT_INT0 EXT_INT7, 타이머 int = TIM0_COMP, ADC int = ADC_INT 등... 책 p.129-131 EICRA : bit (1,0) = (INT0-INT3) 의트리거방식설정용 : (10) 값 = 하강에지에서인터럽트요구. (11) 값 = 상승에지에서..-//-.. EICRB : bit (1,0) = (INT4-INT7) 의트리거방식설정용 : (10) 값 = 하강에지에서인터럽트요구. (11) 값 = 상승에지에저..-//-.. " 에지트리거 " 의펄스폭 = 50[ns] 이용필요!! EIMSK : bit (7..0) = 각각 INT7..INT0의인에이블비트임 : 각 bit = 1 이면, 해당 INTx = enable시킴! SREG : bit 7 = 전역인터럽트 Enable bit. ( 인터럽트인에이블을위해서는 EIMSK, SREG 필요!) EIFR : bit (7..0) = 각각 INT7..INT0의인터럽트발생여부를나타낸다.(=EIFR= int. flag register!)
기능 : INT4 에연결된푸시버튼을누를때마다, 인터럽트가발생하여, C 포트의 LED 가순차적으로하나이동하여점멸하게함. -( 푸시버튼을누를때마다외부인터럽트핀 INT4(=PE4) 에인터럽트신호 ( 하강에지 ) 가발생함!!) -(INT4-7 = 포트 E 의 PE4-7 과공유임! -ATmega128 pin arrangement 참조 ) H/W 결선상태 : E 포트의 PE4 에푸시버튼 ( 스위치 ) 가부착되어있음! //===interrupt.c======================= #include <mega128.h> // io.h 설정시자동으로칩지정 #include <delay.h> //delay_ms(), delay_us() unsigned char led = 0x01; void main(void) //--- 포트초기화 ---- DDRC = 0xFF; DDRE = 0x00; PORTC = ~led; //C 포트모든핀을출력으로설정 //E 포트모든핀을입력으로설정 (PE4 = INT4) //C 포트 (LED 연결!) 에초기값출력, ~ = eacg bit NOT //--- 외부인터럽트 (INT4) 초기화 ---- EICRB = 0b00000010; //INT4 의트리거방식설정 : 하강에지 에서인터럽트요구. EIMSK = 0b00010000; //INT4 enable! ( 즉, 외부인터럽트 4 = '1' = enable!) SREG = 0x80; // 전역인터럽트 enable! ( 즉, 전역인터럽트인에이블비트셋 ) } while(1) ; // 무한루프 : 외부인터럽트기다리다가, 인터럽트가오면 인터럽트처리함수 를수행함! //---interrupt service routine-------------- interrupt [EXT_INT4] void external_int4(void) // 외부인터럽트 (INT4) 서비스루틴 (= 인터럽트처리함수 ) //---LED 순차점멸--- led <<= 1; if(led == 0x00) led = 0x01; PORTC= ~led; //~ = each bit NOT } p.10 의리포트 [ 문제 2] 를인터럽트를이용하여수행하는프로그램을설계, 시행하라. D/A 출력만들기 : 아래의입력에의해크기와주파수가변하는 sin 파를출력하기. (1) 가변저항에의한 A/D 입력에인가되는전압을변경하면 => sin 파의크기 ( 진폭 ) 가변경된다. (2) 1 푸시버튼 -1 을누를때마다 => sin 파의주파수가조금씩커진다. ( 외부인터럽트사용 ) 2 푸시버튼 -2 을누를때마다 => sin 파의주파수가조금씩작아진다.( 외부인터럽트사용 ) 이시점에서설계과제를내줌!! 내용예 = 모터제어 ( 푸시버튼 4 개의누름에의한모터의정회전 / 역회전 / 가속 / 감속제어 )!
2 개의 8- 비트타이머 / 카운터 = TIMER/COUNTER 0, 2 2 개의 16- 비트타이머 / 카운터 = TIMER/COUNTER 1, 3..TCNTn, OCRn = 레지스터이름. 카운트시사용하는클럭 = 내부클럭 (clk_cpu) 또는외부클럭! (TCNTn= TCNT0,TCNT3), (OCRn= OCR0,OCR3)..(TOP= 카운터의최대값!) (1) Normal 모드 : 타이머 / 카운터레지스터 (TCNTn) 값이증가하여 0xFF 값이되면이값은다시 0X00 이 되고, 이로부터다시카운팅을시작함. ( 이경우, TOP=0xFF) (2) CTC 모드 : 타이머 / 카운터레지스터 (TCNTn) 값이증가하여출력비교레지스터 (OCRn) 값과일치하면 TCNTn 값 =0x00 이되고, 다시카운팅을시작함. ( 이경우, TOP=OCRn)...(CTC = Clear Time on Compare Match) (3) 고속 PWM 모드 : TCNTn 값이 0 에서 0xFF 까지증가하고, 그후다시 0 부터 0xFF 까지증가하는 카운트동작을반복함. ( 용도 : 이는높은주파수의 PWM 발생에유용.) (4) PC PWM 모드 : TCNTn 값이 0x00 에서 0xFF 까지증가한후이 0xFF 에서다시역방향으로 0x00 으로 감소하고, 그후다시이러한카운트동작을반복함. ( 용도 : 이는높은분해능의 PWM 발생에유용.) (1) Normal 모드사용 : 카운터의 overflow 시마다타이머 / 카운터 0 의 overflow- 인터럽트가발생하는프로그램... 이의응용 = 0.5 초마다특정작업하는프로그램만듬. (2) CTC 모드사용 : 타이머 / 카운터 0 의출력비교에의해 (TCNT0 = OCR0) 일때 ( 내부클럭사용시 ) < 방법 > X-TAL 클럭의 1024 분주한클럭을타이머 / 카운터의클럭으로이용함. ( 예 ) X-TAL 클럭이 16MHz 인경우 : => 인터럽트가발생하는프로그램 가장긴 overflow- 인터럽트주기 = (1/16 us)x(1024 분주 )x(256 카운터주기 ) = 16.384 ms! 이경우, overflow- 인터럽트가 31 회걸리면 : 16.384 ms x 31 = 508 ms = 약 0.5 초! TCCR0 : 1 bit (6,3) = 동작모드설정 : (=read/write 가능!) 값 : (0,0) = Normal 모드, TOP=0xFF, OCR0 update 시점 = 설정즉시 (0,1) = CTC 모드, TOP=OCR0, OCR0 update 시점 = 설정즉시 (1,0) = PC PWM 모드, TOP=0xFF, OCR0 update 시점 =TOP (1,1) =fast PWM 모드, TOP=0xFF, OCR0 update 시점 =TOP 2 bit (2,1,0) = 클럭선택 ( 시스템클럭 / 분주비 ) -ex: 값 (1,1,1)= 16MHz/1024 값 : (0,0,0) = 클럭입력차단 (0,0,1) = Clk / 1 (0,1,0) = Clk / 8 : (1,1,1) = Clk / 1024 TCNT0 : bit 7-0 = 타이머 / 카운터 0 레지스터값. (=read/write 가능!) OCR0 : bit 7-0 = 출력비교레지스터값 (=read/write 가능!) 이 OCR0 값은 TCNT0 값과계속적으로비교됨... 이둘의값이일치하면 => 인터럽트가발생하거나, 또는 OC0 핀을통해설정된값이출력됨! TIMSK : bit (1,0) : bit 1 = OCIE0 = 출력비교인터럽트 enable bit (- 추가로, SREG bit 7 =1 필요!) bit 0 = TOIE0 = overflow- 인터럽트 enable bit (- 추가로, SREG bit 7 =1 필요!) SREG : bit 7 = 전역인터럽트 Enable bit. ( 인터럽트인에이블을위해서는 EIMSK, SREG 필요!)
------------------------------------------- 참고 : 인터럽트서비스루틴 ( 인터럽트함수 ) 만드는법 타이머 / 카운터0 모드의경우 -여기서, 인터럽트소스명 은해더파일에 (mega128.h) 에정의된소스명사용. < 예 > 외부인터럽트0 (INT0) 의경우 : interrupt [EXT_INT0] void ext_int0(void) < 예 > 인터럽트소스명 : 외부 int=ext_int0 EXT_INT7, 타이머 int = TIM0_COMP, ADC int = ADC_INT 등... 기능 : 0.5 초마다타이머 / 카운터 0 의인터럽트가발생하여, C 포트의 LED 가깜박이게함. //===Timer_interrupt.c======================= #include <mega128.h> // io.h 설정시자동으로칩지정 #include <delay.h> //delay_ms(), delay_us() unsigned char led = 0x01; int count =0; void main(void) //---포트초기화---- DDRC = 0xFF; //C 포트모든핀을출력으로설정 PORTC = ~led; //C포트(LED 연결!) 에초기값출력. ( ~ = each bit NOT) //---타이머/ 카운터0 의설정및인터럽트초기화----: 관련인터럽트서비스루틴 = timer_comp0()! TIMSK = 0x02; //OCIE0=1 : 출력비교인터럽트 enable. TCCR0 = 0x0F; // 프리스케일 = CK/1024, CTC 모드. OCR0 = 255; // 출력비교레지스터값. --OCR0값은 TCNT0값과계속적으로비교됨. TCNT0 = 0x00; // 타이머 / 카운터0 레지스터초기값.--OCR0와 TCNT0값이일치하면 // => 인터럽트가발생, 또는 OC0 핀을통해설정된값이출력됨! SREG = 0x80; // 전역인터럽트인에이블비트셋. p.131 } while(1) ; // 무한루프 : 외부인터럽트기다리다가오면아래인터럽트함수수행함! //---interrupt service routine-------------- interrupt [TIM0_COMP] void timer_comp0(void) // 타이머 / 카운터 0 " 출력비교 " 서비스루틴. // 타이머 / 카운터 0 " 출력비교 " 하여, (TCNT0 = OCR0) 일때인터럽트발생함! } }//timer_comp0() // 인터럽트발생주기 = (1/16 us)x(1024 분주 )x(256 카운터주기 ) = 16.384 [ms]! // => 따라서, 인터럽트가 31 회걸리면이는약 0.5 초! // ( 즉, 16.384 ms x 31 = 50.7904 ms = 50.8 [ms]!) count++; //counting for 0.5 초검사. if(count == 31) //---LED 순차점멸 --- led <<= 1; if(led == 0x00) led = 0x01; PORTC = ~led; //~ = each bit NOT //--- count = 0; //reset!
PWM은직류모터의전압제어에사용되는방식이다. 직류모터와 PWM 직류모터의전압제어는모터의단자전압을가변시켜모터의속도를제어하는경우로서, 보편적으로손실도적고, 제어의폭이넓어서널리사용되는방법이다. 직류모터에인가하는직류전압을증가시키면모터의속도가증가하고, 직류전압을감소시키면속도는감소한다. ( 그이유는직류모터의속도는모터의역기전력에비례하기때문이다 ) 한편, 전압을조절하는방법으로는, 직류전압의크기를제어하기보다는전압의평균값을제어하는 PWM 방식이가장많이사용된다. 이란진폭변조방식 (Pulse Width Modulation) 의약자로서, 펄스의폭을가변시켜이파형의직류성분을가변시키는방법이다. 주기가 T 이고크기가 인구형파펄스가 High 인시간이 이라고하면, 이파형의평균값은다음과같이나타낼수있다. 여기서주기 T와크기 가일정하다고했을때출력전압의평균값은 시간에비례하게된다. 즉, 사용자가임의로 시간을가변시켜서출력전압의평균값을조절할수있게된다. 이출력전압의평균값이이파형의직류전압의성분에해당한다. 시간을가변시키는것을 제어라고한다. 직류모터의 PWM 제어법은출력전압의평균값을제어하는방식으로직류전압을가변시키는것과동일한효과를나타낸다. -이둘의용법은동일함, 단지레지스터만다름! -TNCTn= TNCT1,TNCT3), (OCRn= OCR1,OCR3)..(TOP= 카운터의최대값! -타이머및관련레지스터 more detail = 앞의 3.8절의 타이머해설 부분볼것! (1) 일반모드 : 타이머 / 카운터레지스터 (TNCTn) 값이증가하여 0xFF 값이되면 0x00부터다시시작함. ( 이경우, TOP=0x00) (2) CTC모드 : 타이머 / 카운터레지스터 (TNCTn) 값이증가하여출력비교레지스터 (OCRn) 값과일치하면 TNCTn값 =0x00이되고, 다시카운팅을시작함. (CTC = Clear Time on Compare Match) ( 이경우, TOP=OCRn) (3) 고속 PWM 모드 : TCNTn값이 0에서 0xFF까지증가하고, 그후다시 0부터 0xFF까지증가하는카운트동작을반복함. ( 용도 : 이는높은주파수의 PWM 발생에유용.) (4) PC PWM 모드 : TCNTn값이 0에서 0xFF까지증가한후이 0xFF에서 0으로감소하하고, 그후다시이러한카운트동작을반복함. ( 용도 : 이는높은분해능의 PWM 발생에유용.) 여기서는, PC PWM 모드를구현함!!
레지스터 : (TCNT1),(TCNT3) = 타이머 / 카운터1,3 레지스터. (TCCR1A,TCCR1B,TCCR1C),(TCCR3A,TCCR3B,TCCR3C) = 제어레지스터 (1,3각각의 A,B,C의 ). (OCR1A,OCR1B,OCR1C),(OCR3A,OCR3B,OCR3C) = 출력비교레지스터 (1,3각각의 A,B,C의 ). PWM 출력핀 = (OC1A,OC1B,OC1C),(OC3A,OC3B,OC3C) = 출력핀 (1,3각각의 A,B,C의 ). 동작 : TCNTn값이 0에서 TOP까지증가하다가다시 0으로감소하는카운트동작을반복함. 이때, 업카운트중에 TCNTn값과 OCRnx의값이일치하면 OCnx 핀을통해 0 이출력되고, 다운카운트중에 TCNTn값과 OCRnx의값이일치하면 OCnx 핀을통해 1 이출력된다. PWM 주기 = TOP값의설정에따라결정됨. PWM의펄스폭 (DUTY) = OCRnx 레지스터의값에따라결정됨. PWM 주파수 f = (f_s) / (2(N)(TOP)) -여기서, f_s= 시스템클럭주파수 [Hz], N= 분주비 =1,8,64,256,1024. 따라서, 주파수조정법 : TOP값이크면 주기 = 길어짐...TOP값 = TCCR1A,C( 제어레지스터 ) 에서설정함. DUTY 조정법 : OCRnx( 출력비교레지스터 ) 값이커지면 DUTY가커짐 ( 즉, 1 길이가길어짐 ) -fo 위의타이머 / 카운터1 의경우 ( 타이머 / 카운터1 및 3 내용 = 동일함!) 참고 : 파형발생모드설정 = TCCR1A의 bit(1,0) 과 TCCR1B의 bit(4,3) 의조합으로설정됨. TCCR1A : bit (1,0) = 파형발생모드설정용 : (11) 값 = PC PWM 10비트, TOP=0x03FF. bit (7,6)(5,4)(3,2) =A,B,C각각의동작모드설정용 : each (10) 값 = OCnx출력클리어. TCCR1B : bit (2,1,0) = 클럭소스선택설정용 : (101) 값 = CLK/1024. bit (4,3) = 파형발생모드설정용 : (00) 값 = PC PWM 10비트, TOP=0x03FF. TCCR1C : PWM모드에서는무효. TCNT1 : 타미머 / 카운터값 (=16비트데이터 ) OCR1A,OCR1B,OCR1C : A,B,C의출력비교값 (=16비트데이터 : H,L) 우리의경우, 파형의주기 T = 1/f =(2(N)(TOP))/(f_s) =(2x1024(TOP)x1024( 분주 )) x (1/16)[us] = 131[ms]!! ATmega C program routine
기능 : " 타이머 / 카운터 1" 을이용한 PWM 출력 (=PC PWM, 모드 3) - 목표 : OC1B pin(=pb6) 으로 PWM_B 신호출력. OC1C pin(=pb7) 으로 PWM_C 신호출력. H/W 정보 : OC1B, OC1C pin = PWM 출력 pin 임. ( 이두 pin 은 Port B 의 bit 6,7 pin 과겸용임 ) 실험시, 이두 pin 을오실로스코프에연결하여출력파형을확인할것! //===pwm.c======================= #include <mega128.h> unsigned int TOP = 0x03FF; //=Max 기준값 : 아래에서 TCCR1A 초기화시 TOP = 0x03FF 로설정되었음! unsigned int PWM_B = 0x100; //=OCR1B( 출력비교레지스터 ) 값 : 이값 = 아래의 TOP 값보다작아야함! unsigned int PWM_C = 0x030F; //=OCR1C( 출력비교레지스터 ) 값 = 이값 = 아래의 TOP 값보다작아야함! main() char tmpdata1, tmpdata2; //===IO Port 설정 =============== DDRB = 0xFF; //=0b11111111; //PWM출력핀 2개 = OC1B, OC1C (=PB6, PB7) 로설정. //---' 타이머 / 카운터1' 의 B,c 초기화------ //TCCR1A = 0b00001011; //10비트 PC PCM, TOP=0x03FF(=10비트 all 1) 로지정. TCCR1A = 0b00101011; //10비트 PC PCM, TOP=0x03FF(=10비트 all 1), OC1B & OC1C출력클리어로지정. TCCR1B = 0b00000101; //prescaler= CK/1024 (= 클러소스지정 ) TCCR1C = 0x0; // 타이머 / 카운터1 인터럽트불용지정. TCNT1 = 0x0000; // 타이머 / 카운터1 레지스터초기값 = 0으로지정 (=16비트데이터임 ) //...B OCR1BH = (PWM_B & 0xFF00) >> 8;; //OCR1B의상위값 (H) 지정. (=2비트분량 ) OCR1BL = PWM_B & 0x00FF; //OCR1B의하위값 (L) 지정. (=8비트분량 ) = 총 10비트분량. //...C OCR1CH = (PWM_C & 0xFF00) >> 8;; //OCR1C의상위값 (H) 지정. (=2비트분량 ) OCR1CL = PWM_C & 0x00FF; //OCR1C의하위값 (L) 지정. (=8비트분량 ) = 총 10비트분량. //<!> 주 :--------------------------- // 만일, 제어시, 상황에따라 PWM DUTY를바꾸려면 // => 아래부분에서, 조건에따라이 OCR1CH,OCR1CL값만을바꾸어주면됨! //--------------------------------- //---tmp TEST : B포트그냥출력 (not PWM) : B포트의 bit 4,5 tmpdata1 = 0b00010000; //bit 4 tmpdata2 = 0b00100000; //bit 5 PORTB = tmpdata1 tmpdata2; }//main()
= 직렬전송 (serial communication) 을위한규격. 1 사용전압 : logic '1' = -3 ~ -15V...(negative logic 채용 ) 따라서, 전압레벨변환 IC( MAX232 ) 사용필요! logic '0' = +3 ~ +15V 편리한전압이용 ( 통상 ±12V) 2 최대전송 line 길이 = 50 ft (=15 m). 3 전송속도 (bps) : 110, 300, 600. 1200, 2400, 4800, 9600, 19200[bps] 4 전송 Data 의 Format : bps=bits per second. 송신부는한개의데이터에약속된방식으로몇개의 bit 을추가로붙여 (=frame 을만들어 ) 전송하고, 수신부에서는 frame 한개를받으면추가된 bit 를제거하여데이터를뽑아낸다. ~ 이를위해사용되는추가 bit 들 : ( 이들은한개의순수 data 마다에추가됨 ) - start bit : data 의시작을알리는비트 - stop bit : data 의끝을알리는비트 - parity bit : 전송 error 검사용비트 - 종류 = even parity, odd parity < 에러의종류 > 1 overrun error = 이전 data 의해독이종료되지않은시점에서다음의 data 가들어와서처리불능이되는것. 2 framing error = 수신기가 noise 등을검지해서이를 start bit 로해석하여수신을개시하는일이있다. 이경우 stop bit 의해독 timing 으로 stop bit 이외의부분을읽어올바르게 data 를해독하지못하는것.
ATmega128 : USART 2개를내장. (PIN = TXD0,RXD0, TXD1,RXD1 <- p.60) - 동기모드 / 비동기모드, 전이중통신가능. - 3개의인터럽트소스 : 송신완료, 수신완료, 송신데이터레지스터빔 (empty). 송신부 = 송신버퍼, 쉬프트레지스터, 패리티발생기등으로구성 수신부 = 수신버퍼, 쉬프트레지스터, 패리티검사기등으로구성. 에러자동검사 = 패리티에러, 프레임에러, 데이터오버런에러. : 데이터레지스터 : UDRn (= 송신 / 수신겸용 ) n=0,1 (USART 번호!) 제어레지스터 (A,B,C) : UCSRnA, UCSRnB, UCSRnC. 보레이트레지스터 (H/L) : UBRRnH, UBRRnL.... 이하, n=0,1 : 즉, UDRn => UDR0,UDR1, UCSR0A, UBRR0H..etc UDRn : USARTn I/O Data Register ( 데이터레지스터 ) : 8-bit (= 책p.247) = 송신데이터버퍼 & 수신데이터버퍼겸용이름. 이름은동일하지만, 내부 (H/W) 적으로분리되어있음! 1. UDRn 레지스터에데이터를쓰면 => 송신데이터버퍼 TXBn에값이써진다. UDRn 레지스터를읽으면 => 수신데이터버퍼 RXBn에들어있는내용이읽혀진다. UDRE = Data Register Empty 2. 송신데이터버퍼 (UDRn) 에값을쓸수있는때 = UCSRnA 레지스터의 UDRE 비트가 1 일때 (only). (0 일때데이터를쓰면무시됨 ) => 송신이가능하고또한송신시프트레지스터가비어있으면, 송신버퍼에쓰여진데이터는송신시프트레지스터를통해 TXD0 핀으로출력됨. UCSRnA : USARTn Control and Status Register A ( 제어및상태레지스터 A) : 8-bit (= 책p.247) bit (7) = RXCn(=Receive Complete = 수신완료플레그비트 ) 값 1 : 수신버퍼 (UDRn) 에읽지않은데이터가들어있으면셋됨. ( 비어있으면 0 됨 ) 인터럽트관련 : 이비트는 " 수신완료인터럽트 " 를발생시킴. bit (6) = TXCn(=Transmit Complete = 송신완료플레그비트 ) 값 1 : 문자프레임이 TxD 핀으로송신이완료되어, 송신버퍼 (UDRn) 및송신시프트레지스터가비어있으면셋됨. 인터럽트관련 : 이비트는 " 송신완료인터럽트 " 를발생시킴. ( 송신완료인터럽트가발생되면 -> 이비트는자동으로클리어됨 ) bit (5) = UDREn(=Data Register Empty = 송신데이터레지스터준비완료플래그비트 ) 값 1 : 송신버퍼 (UDRn) 가비어있어서새데이터를받을준비가되면셋됨. 인터럽트관련 : 이비트는 " 송신데이터레지스터준비완료인터럽트 " 를발생시킴. bit (4,3,2) = Error 관련플레그비트들. -모두: 수신버퍼 (UDRn) 가읽혀질때까지유효함. UCSRnA 레지스터에값을쓰면클리어됨. - bit (4) =FEn(=Frame Error) - bit (3) =DORn(=Data OverRun Error) - bit (2) =PEn(=Parity Error) bit (1) =U2Xn(=Double Tx Speed = 송신속도 2배설정비트 ). 값 1 = 전송속도가 2배로됨. bit (0) =MPCMn(=Multi-processor Comm. mode = 멀티프로세서통신모드 ) : = omit! UCSRnB : USARTn Control and Status Register B ( 제어및상태레지스터 B) : 8-bit (= 책p.249) bit (7) =RxCIEn(=Rx Complete Interrupt Enable = " 수신완료인터럽트 " 인에이블비트 )..SREG 레지스터의 비트와이비트가 1 인상태에서, 수신이완료되면 ( 즉, UCSRnA 레지스터의 bit(7) 이 1이되면 ) => " 수신완료인터럽트 " 가발생된다. bit (6) =TxCIEn(=Tx Complete Interrupt Enable = " 송신완료인터럽트 " 인에이블비트 )..SREG 레지스터의 비트와이비트가 1 인상태에서, 송신이완료되면 ( 즉, UCSRnA 레지스터의 bit(6) 이 1이되면 ) => " 송신완료인터럽트 " 가발생된다.
bit (5) =UDRIEn(=Data Register Empty Interrupt Enable =" 송신버퍼준비완료인터럽트 " 인에이블비트 )..SREG 레지스터의 I 비트와이비트가 1 인상태에서, 송신버퍼가비면 ( 즉, UCSRnA 레지스터의 bit(5) 가 1이되면 ) => " 송신버퍼준비완료인터럽트 " 가발생된다. bit (4) =RxENn(=Receiver Enable = 수신기인에이블 ) 값 1 = 수신가능상태로만들고, H/W적으로 RxDn 핀이 ( 범용 I/O가아닌 ) 수신단자로동작하게됨. bit (3) =TxENn(=Transmitter Enable = 송신기인에이블 ) 값 1 = 송신가능상태로만들고, H/W적으로 TxDn 핀이 ( 범용 I/O가아닌 ) 송신단자로동작하게됨. bit (2) =UCSZn2(=Character Size = 전송데이터길이선택비트 ) -이비트는 UCSRnC 레지스터의 bit (2,1) 과함께사용됨! bit (1) =RxB8n(=Receive Data Bit 8 = 수신데이터비트 8) = 9비트전송모드관련 (omit!) bit (0) =TxB8n(=Transmit Data Bit 8 = 송신데이터비트 8) = 9비트전송모드관련 (omit!) UCSRnC : USARTn Control and Status Register C ( 제어및상태레지스터 C) : 8-bit (= 책p.251) bit (7) = 불용! bit (6) =UMSELn(=Mode Select = 모드설정비트 ) : 값 0 = 비동기모드, 1 = 동기모드. bit (5.4)=UPMn(=Parity Mode = 패리티모드설정비트 ) : 값 (0,0)= 불용, (1,0)= 짝수패리티, (1,1)= 홀수패리티. bit (3) =USBSn(=Stop Bit Select = 스톱비트선택비트 ) : 값 0 =1비트, 1 =2비트 bit (2,1)=UCSZn1,UCSZn0(=Character Size = 전송데이터길이선택비트 ) : -이비트는 USCRnB 레지스터의비트 (2)(=UCSZn2) 와함께사용됨! < 즉 > (UCSZn2,UCSZn1,UCSZn0) : 값 (0,1,1)=8비트, (0,1,0)=7비트,..,(0,0,0)=5비트. -기타 = 책 p.252 [ 표10-2] 참조. bit (0) =UCPOLn(=Clock Polarity = 클럭극성선택비트 ) -이비트는동기모드에서만사용 ( 상승에지, 하강에지선택용 ). (omit!) UBRRnH,UBRRnL : USARTn Baud Rate Register ( 보레이트레지스터 ) : each 8-bit (= 책p.253) = 총16비트중 12비트만사용됨.(H= 상위바이트, L= 하위바이트 ) < 주의 > 값쓰기 = 상위바이트 (H) 에먼저값을쓴후, 하위바이트 (L) 에써야함!! -책 p.253 [ 표10-4] = 전송속도및본 UBRRn용설정값을구하는공식 -책 p.254 [ 표10-5] = 16MHz 시스템에서, bps와 UBRRn 설정값의관계표!! < 설정값관계 >: (bps-ubrr) : (2400-416),(4800-207),(9600-103), (14.4K-68),(19.2K-51),(28.8K-34),(38.4K-25),..,(1M-0) [ 방법 1] CodeVisionAVR에내장된터미널창사용 : -by 툴바의 PC모양아이콘클릭! [ 방법 2] Windows OS 제공 " 하이퍼터미널 " 사용 : o모니터좌측하단의 < 시작 > => 모든프로그램 => 보조프로그램 => 통신 => 하이퍼터미널선택 -> TAPI오류 메시지박스가나타남 (= 무시 ) -> [ 확인 ] 버튼 -> 연결이름기입 메시지박스나타남 -> 임의이름기입 & [ 확인 ] 버튼 -> 또 TAPI오류 메시지박스가나타남 (= 무시 ) -> [ 확인 ] 버튼 -> 연결에사용할모뎀 설정용메시지박스나타남 -> 원하는 COM 포트선택 & [ 확인 ] 버튼 -> 포트설정 메시지박스나타남 -> 통신포트 (RS232) 초기화설정 : 즉,(bps,data,parity,stop bit 설정 )& 흐름제어 = 없음 으로설정! -> [ 확인 ] 버튼 ==> 그러면하이퍼터미널완성!! 이제외부에서이 PC의통신포트 (RS232) 로데이터가들어오면 이하이퍼터미널창에그데이터 (ASCII코드) 가표시되고, 이 PC의키보드를두드리면 해댱키데이터가이 PC의통신포트 (RS232) 를통해전송됨!! = [ 부록 5] 참조!!!
기능 : RS-232 포트로 PC 와직렬데이터송수신 ( 일반 & 인터럽트사용 ) H/W 결선 : ATmega128 과 PC 사이에 RS-232 serial cable 연결. //===Serial_COMM.c======================= #include <mega128.h> #include <delay.h> //delay_ms() RS-232 serial cable 제작법 (ATmega128 용 ) = 책 p.375. //---Job Functions ( 본프로그램의기능 : 3 종 )---------------------source= book p.259-262 void RS232_Tx(); //ATmega128 의 RS-232 포트 0 를통해문자열을송신. void RS232_TxRx(); //PC 에서키를치면 ATmega128 는이를수신하고이를다시 PC 에송신함. void RS232_TxRX_Interrupt(); //PC 에서키를치면 ATmega128 는이를수신하고이를다시 PC 에송신함. // ( 단, 인터럽트사용!) //---used functions void Tx_OneByte(char data); //1 byte 송신함수 : 송신가능상태가되기를기다린후, 준비가되면송신함.(RS-232) char Rx_OneByte(); //--- main() //1 byte 수신함수 : 데이터가수신되기를기다린후, 수신되면받아서리턴함.(RS-232) RS232_Tx(); //ATmega128 의 RS-232 포트 0 를통해문자열을송신. // RS232_TxRx(); //PC 에서키를치면 ATmega128 는이를수신하고이를다시 PC 에송신함. // RS232_TxRX_Interrupt();//PC 에서키를치면 ATmega128 는이를수신하고이를다시 PC 에송신함.( 인터럽트사용!) }//main() //--------------------------- void Tx_OneByte(char data) //1 byte 송신함수 : 송신가능상태가되기를기다린후, 준비가되면송신함.(RS-232) } while(!(ucsr0a & 0b00100000)) ; //(USART-0) Tx Data Register Empty? ( 즉, UDRE0 =1?) UDR0 = data; //(USART-0) Tx Data Register 에데이터입력 (= 전송!) char Rx_OneByte() //1 byte 수신함수 : 데이터가수신되기를기다린후, 수신되면받아서리턴함.(RS-232) } char data; while(!(ucsr0a & 0b10000000)) ; //(USART-0) Rx Complete? ( 즉, RxC0 =1?) = 수신완료되기를기다림 data = UDR0; //(USART-0) Rx Data Register 에수신되어있는데이터를가져옴. return(data); //===RS232_Tx(): USART0 송신프로그램 [ATmega128의 USART-0(RS232 포트 0) 사용 ]============ // JOB : 직렬통신으로, ATmega128에서 PC로, 문자열 "This is USART control program" 을전송하기. // -Spec: BAUD=9600, DataBit=8, StopBit=1, Parity=None. // H/W 연결상태 : ATmega128과 PC사이에 RS-232 serial cable 연결. //... // <PC측에서확인법 >= CodeVisionAVR에내장된터미널창사용! (by 툴바의 PC모양아이콘클릭!) // 또는, Windows OS 제공 " 하이퍼터미널 " 사용. //------------------------------------------------------------------------------- void RS232_Tx() //ATmega128의 RS-232 포트0를통해문자열을송신. char string[] = "This is USART control program!!!=="; // 전송할문자열 char *pstr; //===USART-0 초기화 ============ UCSR0A = 0x0; //(USART-0) 송수신관련 all Flag Bits = clear! UCSR0B = 0b00001000; //(USART-0) 송신 enable(txen0=1), 모든송수신인터럽트 =disable