include - chowk.khu.ac.krchowk.khu.ac.kr/lecture/avr/report/up2012_2_2번과제_유…  · web...

Post on 06-Feb-2018

227 Views

Category:

Documents

9 Downloads

Preview:

Click to see full reader

TRANSCRIPT

임베디드 시스템 설계

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

top related