include - chowk.khu.ac.krchowk.khu.ac.kr/lecture/AVR/report/up2012_2_2번과제_유… · Web...
Transcript of include - chowk.khu.ac.krchowk.khu.ac.kr/lecture/AVR/report/up2012_2_2번과제_유… · Web...
임베디드 시스템 설계
2006200209 유한솔
2006200209 유한솔
2012 년도 2 학기 - 임베디드 시스템 설계
2 번 과제(Report) : Digital Clock 를 구현 하라.
Keypad 를 입력 장치로 LCD 를 출력 장치로 사용 하여, 시간, 분, 초 시간을 표시
하고, 현재 시간 설정이 가능 기능을 구현하라.
1. 문제의 설명
1) Sec 주기 신호를 만드는데 Timer 0(외부 Crystal(32K) 과 T/C Oscillator 를 이용) 또는
Timer 1 Interrupt 를 사용 할 것
2) 참고자료(GCC_asm_utilts.zip) 에 있는 함수를 이용 할 수 있다.
3) 제출기한(Due date) : 2012 년 11 월 11 일(일요일) 까지
4) 작성 방법(Documentation Tool) : MS Word 를 사용하여 작성 한다. 내용은 과제 설명과
프로그램, 결과가 출력된 사진을 포함 할 것.
5) 레포트 제목(파일 이름) 작성 방법 : "1 번과제"_"본인 이름"을 포함하여 작성 할 것. 예:1
번과제_김갑돌.docx
6) 제출 방법(Up Load Site) : FTP 서버(Server) 163.180.144.55 에 접속(Connect) 하여
Up Load 할 것.
2. 문제의 파악
가. 문제파악
디지털시계를 제작하기 위해서 기본적으로 시간을 표현할 LCD 와 시간을 입력받을 Keypad
가 필요하다. 또한 문제에서 요구되는 것과 같이 외부 Crystal 을 이용하여 1 초를 만들
것이므로 그것에 대한 추가 회로도 필요하다. 소프트웨어를 설계하기 이전에 앞서 필요한
하드웨어를 점검하고 필요한 회로를 추가로 제작하여 부착할 수 있도록 한다.
임베디드 시스템 설계
2006200209 유한솔
나. 사용할 기능의 설정
기본적으로 시간을 표시할 수 있어야 하며, 사용자의 요구에 따라 시간을 맞출 수 있는
기능이 있어야 한다. 때문에 시간을 표시하는 도중 임의의 키패드 버튼을 조작하여 시간을
set 할 수 있도록 제작하여야 한다. 또한 시간은 24 시간을 기준으로 동작하되, 24 시가
되었을 경우 0 으로 초기화가 되어야 한다.
3. 문제의 해결
가. 외부 Crystal(32K) 과 T/C Oscillator 를 이용한 회로의 설계
우선적으로 Sec 주기 신호를 만들기 위하여 외부 Crystal(32K)와 T/C Oscillator 를
사용하여야 한다. TOSC1, TOSC2 는 <자료실> 내의 “KHU-EE-AVR Board
Connector(2011 년)”을 참조하여 찾을 수 있으며, J2 의 10 번과 11 번이므로, 즉 PG3,
PG4 에 연결하면 된다. <강의노트> 내에 있는 예제파일을 참조하면 LED 를 이용하여 외부
Crystal 을 이용한 회로의 작동 가부를 쉽게 파악할 수 있다. 사용된 회로도는 다음과 같다.
임베디드 시스템 설계
2006200209 유한솔
<< 외부 Crystal(32K) 과 T/C Oscillator 를 이용한 회로>>
나. 소프트웨어의 설계
1) 사용할 함수의 지정
시계를 동작시키기 위해서는 LCD, Keypad 를 포함한 하드웨어 작동을 위한 함수와,
타이머와 BCD 출력 등을 갖는 기타 유틸리티 함수가 필요하다. 제공된
“GCC_asm_utilts.zip”함수를 기반으로 사용하였으며, Main 함수는 본 프로그램과 가장
유사하다고 판단되는 “2 Line LCD 에 문자를 출력 하는 예(Timer 2 Over Flow Interrupt
를 이용)”을 기초로 제작하였다.
"cho_asm_io_def.h""GCC_asm_delay_timer2.h""GCC_asm_uart.h""GCC_asm_sci_util.h""GCC_asm_in_out_util.h""GCC_asm_lcd_hd44_4bit_timer2.h""GCC_asm_get_keypad_cmd.h""GCC_asm_digital_clock_util.h“
“GCC_asm_utilts.zip” 함수에 포함되지 않은 함수는 다른 예제파일을 참조하여 추가할 수
있도록 하였다.
임베디드 시스템 설계
2006200209 유한솔
2) 함수의 기능
각 함수에서 대표적으로 사용되는 기능은 다음과 같다.
"GCC_asm_delay_timer2.h" :delay_1mSec,delay_100uSec, delay_10uSec
"GCC_asm_digital_clock_util.h“ :timer0_init, TIMER0_OVF_vect, time_display, set_time,sec_count, min_count, hour_count, display_flag, time_update_flag
"GCC_asm_get_keypad_cmd.h" :keypad_init, keyscan, get_key, get_key_cmd
"GCC_asm_in_out_util.h" :bin2BCD16, BCD_print, DEC_print, binary_HEX_print, InUSBCD, InUSBCD
"GCC_asm_sci_util.h"OutString,InUSDec,InUSDecN_Digit
"GCC_asm_uart.h"UART_Init, UART_Transmit, UART_Receive, UART_getchar, UART_putchar, ASM_getchar, ASM_putchar
각 함수의 header 파일을 참조하여 각 함수에서 갖는 기능을 분석하고 필요에 따라 그것을
사용할 수 있도록 하였다.
3) 프로그램의 작성
기초적인 메인함수를 작성하고 각종 필요 함수를 추가시킨 후 Complile 한 결과 각종
함수에서 요구되는 define 이 정의되지 않아 오류가 발생하는 것을 볼 수 있었다. 때문에
Error Message 를 확인하고 각기 해당하는 값을 입력하였다.
Error Message 를 참조하여 추가된 값은 다음과 같다.
임베디드 시스템 설계
2006200209 유한솔
.global sec_count,min_count,hour_count,display_flag,time_update_flagsec_count: .byte 00min_count: .byte 00hour_count: .byte 00display_flag: .byte 0xfftime_update_flag: .byte 0xff
각 값은 전역변수와 같이 각기 다른 함수에서 참조하여 사용할 수 있으며, sec, min, hour 는
각기 시, 분, 초를 count 하는 부분이고, display_flag 와 time_update_flag 는 각각 화면의
출력여부와 시간을 업데이트 하는 것에 대한 flag 의 역할을 수행한다.
flag 는 0 과 1 을 통하여 어떠한 기능의 분기점과 같이 사용된다. 때문에 0x00 과 0xff 로 0
과 1 을 표시하게 될 것이며, 사용의 편리성과 가독성을 높이기 위하여 각기 false 와 true 로
define 하도록 하였다.
#define TRUE 0xff#define FALSE 0x00
임베디드 시스템 설계
2006200209 유한솔
4. 동작 알고리즘
임베디드 시스템 설계
2006200209 유한솔
가. Flag 의 이해
본 프로그램에 사용되는 Flag 는 Display 와 Time update 의 2 가지 종류가 있다.
Display Flag 는 LCD 에 값을 출력(Time display 함수)할 것인지 하지 않을 것인지 정하는
Flag 이다. 만일 Display Flag 가 0 일 경우 화면은 정지한 것처럼 보인다.
Time_update Flag 는 Time0 의 Overflow interrupt 의 완료를 알려주는 flag 이다.
연산도중에 값이 출력되는 것을 막을 수 있다. Time update flag 가 1 인 경우 연산이
완료된 것을 알려주며, 화면이 출력된 이후에는 다시 0 으로 바꾸어 Loop 에서 화면이
출력되는 것을 막는다.
나. Main 동작
Main 동작의 처음은 Display Flag 를 0 으로 하여 화면 출력을 정지시키는 것부터 시작한다.
time display 화면 출력을 하지 않은 상태로 timer 와 각종 장치를 초기화 시키고 interrupt
를 enable 하도록 한다. 또한 사용자에게 set time 기능을 시킬 수 있는 keypad 의 입력키
‘*’를 표시할 수 있는 명령 또한 수행하게 되어있다. 상기 언급한 내용을 모두 수행하고 나면
display flag 를 true 로 바꾼 후 loop 동작을 수행하도록 한다.
다. Loop 동작
Loop 동작은 Main 이 시행된 이후 무한 반복되는 동작이다. 총 3 번의 분기문이 존재한다.
검토되는 분기문은 다음 3 개가 있다.
1) 사용자가 ‘*’키를 입력하였는가.
2) Display Flag 가 True 인가 False 인가.
3) Time_update Flag 가 True 인가 False 인가.
만일, 사용자가 ‘*’을 입력하였다면 Set_time 동작을 수행한다. 그렇지 아니한 경우 2), 3)을
확인하여 Flag 가 모두 True 일 때 화면을 출력하도록 한다. 만일 그러하지 아니하다면 다시
Loop 를 반복하여 확인하게 된다.
라. Interrupt 동작
임베디드 시스템 설계
2006200209 유한솔
위 그림과 같이 Main 과 Loop 동작을 수행하는 도중 interrupt 가 발생할 경우 해당
interrupt routine 을 수행하고 이후 이전으로 복귀하는 형태를 취하게 된다. 본
디지털시계는 Timer0 overflow 인터럽트를 사용한다. “GCC_asm_digital_clock_util”에
포함된 내용을 살펴보면, timer0_init 에서 1 초를 생성한다. 즉 1 초마다 인터럽트가
발생하게 되며 매 인터럽트가 발생할 때 마다 Timer0_OVF_vect 의 내용을 수행하게 된다.
인터럽트에서 수행되는 명령은 매 인터럽트 발생 시 그 값을 1 씩 더해가며 60 초가 되었을
때 1 분을, 60 분이 되었을 때 1 시간을, 24 시간이 되었을 때 reset 이 되는 형태를 취한다.
초, 분, 시의 순서로 파악하여 연산을 하기 때문에 연산과정에서 시간이 출력되는 것을 막기
위하여 연산이 끝남을 표시하는 time_update flag 가 필요하다. 동작되는 알고리즘을
도표로 나타내면 아래와 같다.
마. Set time 동작
사용자가 ‘*’을 눌렀을 때 동작하는 것으로, 시간을 맞추는 동안 화면에 시간이 출력되는 것을
막기 위해 display flag 를 통해 현재시간 출력을 정지시킨다. 그러면서 사용자가 시간을
입력하고 나면 입력된 시간부터 다시 전체 명령이 다시 시작되는 구조로 되어있다. “
CLOCK_DISPLAY_POSITION_ROW”과 “CLOCK_DISPLAY_POSITION_COL”에서는 현재
시간이 표시될 시작지점을 지정하게 되어있다. header 에서 define 된 부분을 수정하면
임베디드 시스템 설계
2006200209 유한솔
시작지점을 임으로 변경할 수 있으나, 그 시작지점을 잘못 지정할 경우 값이 LCD 의 출력
가용범위를 넘어서 출력되지 않을 수도 있음에 유의한다. 시간 설정을 시작할 때는 display
flag 를 false 로 지정하여 시간 설정을 수행하고 그것이 끝나면 flag 를 다시 true 로
전환하여 현재시간을 출력한다.
바. 주요 source 설명
LOOP:
rcall get_key_cmd //keypad 의 값을 받는다.
cpi RG_ARG0_L, '*' //값이 ’*’인지 비교한다.
brne loop1 //값이 ‘*’이 아니면 loop1 로 간다.
rcall set_time //값이 ‘*’이면 set_time(시간설정)으로 간다.loop1:
lds AC0, display_flag //AC0 에 display flag 값을 load 한다.
cpi AC0, FALSE //AC0 와 False 값을 비교한다.
breq loop2 //AC0(display flag)==False 이면 loop2 로 간다.
lds AC0, time_update_flag //AC0 에 time update flag 값을 load 한다.
cpi AC0, FALSE //AC0 와 False 값을 비교한다.
breq loop2 //AC0(time update flag)==false 이면 loop2 로
간다.
//이 경우는 display flag 와 timeupdate flag 가 모두 1 인 경우가 된다.
rcall time_display //현재 시간을 출력한다.
ldi AC0, FALSE //AC0 에 False 를 load 한다.
sts time_update_flag, AC0 //time update flag 를 false 로 만든다.loop2:
rjmp LOOP //Loop 로 돌아간다. 무한루프가 된다.
임베디드 시스템 설계
2006200209 유한솔
5. 결과
디지털 시계의 초기동작 화면 10 초가 흐른 뒤 *을 누른 화면
시간 설정을 하는 화면 시간 설정 후 동작하는 화면
임베디드 시스템 설계
2006200209 유한솔
6. 토의
가. 23:59:59 에서 00:00:00 으로 넘어가는 부분, 혹은 각 단위보다 큰 수가 입력될 경우
23:59:59 이후 문제없이 00:00:00 으로 넘어가는 것을 확인할 수 있으며, 입력된 값이 각기
24, 60, 60 이 초과할 경우 해당 시 분 초에 연산이 이루어 질 때 값이 변화하는 것을 알 수
있다. 예를 들어 11:99:30 을 입력할 경우 분 연산이 이루어지는 30 초 뒤에 99 가 0 으로 11
이 12 로 바뀌게 될 것이다.
임베디드 시스템 설계
2006200209 유한솔
나. LCD 문제
디지털시계를 제작하는 동안 값이 정상적으로 표시되지 않는 경우가 있었다. 원인을 찾지
못하여 많은 시간이 소요되었는데, LCD 를 교체하였더니 정상적으로 작동하였다.
지금까지도 그 원인에 대해서는 정확하게 알지 못하고 있지만, 다음 수업 시간에 교수님의
조언을 얻어 문제를 해결해 보고자 한다.
임베디드 시스템 설계
2006200209 유한솔
7. 사용된 전체 source# ifndef atmega128
#define atmega128# endif#define FOSC 16000000// Clock Speed
#include <avr/io.h> // Definition file for ATmega128#include "cho_asm_io_def.h" // I/O Port Definition for ATmega128#include "GCC_asm_delay_timer2.h"#include "GCC_asm_uart.h"#include "GCC_asm_sci_util.h"#include "GCC_asm_in_out_util.h"#include "GCC_asm_lcd_hd44_4bit_timer2.h"#include "GCC_asm_get_keypad_cmd.h"#include "GCC_asm_digital_clock_util.h"
// SRAM Definitions#define _SFR_OFFSET 0 // Needed to subtract 0x20 from I/O addresses
// [Add all hardware information here]
// Program Constants
// Program Variables Definitions#define RG_TEMP r0 // Temporary Register#define RG_ZERO r1 // Zero#define AC0 r16 // Temporary Byte Rg 0#define AC1 r17 // Temporary Byte Rg 1#define AC2 r18 // Temporary Byte Rg 2#define AC3 r19 // Temporary Byte Rg 3#define AC4 r20 // Temporary Byte Rg 2#define AC5 r21 // Temporary Byte Rg 2#define ACW0_L r2 // Temporary Word Rg 0 Low#define ACW0_H r3 // Temporary Word Rg 0 High#define ACW1_L r4 // Temporary Word Rg 1 Low#define ACW1_H r5 // Temporary Word Rg 1 High#define ACW2_L r6 // Temporary Word Rg 2 Low#define ACW2_H r7 // Temporary Word Rg 2 High#define ACW3_L r8 // Temporary Word Rg 3 Low#define ACW3_H r9 // Temporary Word Rg 3 High#define RG_ARG0_H r25 // Function Argument Word Rg 0 High#define RG_ARG0_L r24 // Function Argument Word Rg 0 Low#define RG_ARG1_H r23 // Function Argument Word Rg 1 High#define RG_ARG1_L r22 // Function Argument Word Rg 1 Low#define RG_ARG2_H r21 // Function Argument Word Rg 2 High#define RG_ARG2_L r20 // Function Argument Word Rg 2 Low
#define CR 0x0d#define LF 0x0a#define TRUE 0xff#define FALSE 0x00
// MACRO 함수 정의.macro CR_LF_OUT
push RG_ARG0_Lldi RG_ARG0_L, CRcall ASM_putcharldi RG_ARG0_L, LFrcall ASM_putcharpop RG_ARG0_L
.endm
.section .data
.ORG 0x0000 // Compiler 가 OffSet 0x0100 을 더하기 때문에 실제 번지는 0x0100 이 된다..global sec_count,min_count,hour_count,display_flag,time_update_flag
sec_count: .byte 00 min_count: .byte 00 hour_count: .byte 00 display_flag: .byte 0xfftime_update_flag: .byte 0xff
mesg1: .asciz "Set key : *"
//cWord: .word 0x0000 // Allocata word(s) of storage with initialized values//cLongWord: .long 0x00000000 // Allocata 32-bit long word(s) of storage with initialized values
.global main
.global ASM_getchar,ASM_putchar
.section .text
ASM_getchar:
임베디드 시스템 설계
2006200209 유한솔
rcall get_keyret
ASM_putchar:rcall LCD_OutCharret
// My Main Entry into programmain:
clr RG_ZERO
; Time display flag <- FALSEldi AC0, FALSEsts display_flag, AC0
rcall timer0_init
// Init USART// Set Baud Rate : 19200( UBRR <- 51)clr RG_ARG0_Hldi RG_ARG0_L, 51rcall UART_Initrcall keypad_initsei ; Global Interrupt
Enablercall LCD_init
ldi RG_ARG0_L, 2ldi RG_ARG1_L, 1rcall LCD_SetCsr
ldi RG_ARG0_L, lo8(mesg1)ldi RG_ARG0_H, hi8(mesg1)rcall OutString
; Time display flag <- TRUEldi AC0, TRUEsts display_flag, AC0
LOOP:rcall get_key_cmdcpi RG_ARG0_L, '*'brne loop1rcall set_time
loop1:lds AC0, display_flagcpi AC0, FALSEbreq loop2
lds AC0, time_update_flagcpi AC0, FALSEbreq loop2
rcall time_display
ldi AC0, FALSEsts time_update_flag, AC0
loop2:rjmp LOOP ; Loop Indefinitly
.end