nomod51 nosymbols spring 2013


$NOMOD51
$NOSYMBOLS
;*****************************************************************************
; Spring 2013 Project
;
; FILE NAME : Project.ASM
; DATE : 3/30/2013
; TARGET MCU : C8051F340
; DESCRIPTION : Starter Code for the Spring 2013 Digital II Project.
; It initializes the cross bar, I/O and ADC0.
; The keypad and LCD code is included.
; The ACALL to Measure_Temp returns a 10-bit right justified
; value in the DPTR representing the internal temperature in
; Degree Celcius. The internal Voltage Reference is utilized
; so that the temperature can be determined from the following
; equation:
;
; Vtemp = ((2.86mV/C) * C) + 776mV
; C= ((DPTR * (2.44/1024) -776mV)/2.86mV
;
; Not all 1024 values are required so a small table can be
; used with an offset to determine values from 0 to 99 degrees
; F. Use a lookup table as it is far easier than trying to
; implement the formula in code, convert to degrees F and then
; convert to LCD format encoding.
;
; NOTE: All the provided started code below is written using lower case
; instructions. Your source code should be written using upper case
; instructions so that I can help debug your code easier.
;
;
;
;*****************************************************************************
$NOLIST ; stops listing of the include file
$INCLUDE (C8051F340.inc)
$LIST ; restarts listing
;*****************************************************************************
; EQUATES TABLE
;*****************************************************************************


ENABLE equ P1.4 ; Enable signal to LCD
RW equ P1.2 ; R/W signal to LCD.
RS equ P1.3 ; RS signal to LCD
LCD equ P0 ; Output port to LCD.

keyport equ P2 ; Keypad port connected here
row1 equ P2.0 ; Row 1 (pin 8)
row2 equ P2.1 ; Row 2 (pin 1)
row3 equ P2.2 ; Row 3 (pin 2)
row4 equ P2.3 ; Row 4 (pin 4)

col1 equ P2.4 ; Column 1 (pin 3)
col2 equ P2.5 ; Column 2 (pin 5)
col3 equ P2.6 ; Column 3 (pin 6)
col4 equ P2.7 ; Column 4 (pin 7)

Switch equ P1.1 ; Door Close Switch 0 = door closed
; 1 = door open

Ambient DATA 40H ; AMBIENT temp (degrees F) RAM address
TIME_HOUR DATA 41H ; Time of Day - hour RAM address
TIME_MINUTE DATA 42H ; Time of Day - minute RAM address
TIME_SECOND DATA 43H ; Time of Day - second RAM address

;*****************************************************************************
; RESET AND INTERRUPT VECTOR TABLE
;*****************************************************************************

org 0000H ; Code starts at reset vector address
ljmp Main

org 002BH ; Vector address for Timer 2 ISR
jmp T2ISR ; As the ISR is large need to relocate
; and jump to it


;*****************************************************************************
; MAIN PROGRAM CODE
;*****************************************************************************

org 0030H ; Main starts above the vector addresses
Main:
anl PCA0MD, #0BFH ; Disables watchdog timer

; Enable the Port I/O & Crossbar
mov P0MDOUT, #0FFH ; Make P0 output push-pull
mov P1MDIN, #0DFH ; P1.5 set to Analog I/O
mov P1MDOUT, #0FCH ; Make P1.2, P1.3, P1.4, P1.6,and P1.7
; output push-pull
mov P1SKIP, #20H ; Skips P1.5 in crossbar
mov P2MDOUT, #0FH ; Make P2 low nibble output push-pull
mov P1MDIN, #0FFH ; Make port pins input mode digital
mov XBR1, #40H ; Enable Crossbar
mov RSTSRC, #04H ; Missing clock detector is enabled
mov SP, #5FH ; Puts stack in high RAM
call Timer2_Init ; Calls Timer2 initalization routine
call ADC0_Init ; Calls the ADC initalization routine
setb AD0EN ; Enables AD0



; YOUR DISPLAY AND LED TEST CODE GOES HERE!!

mov R3, #0 ; Clears LCD position counter
call init_LCD ; LCD Initialization proceedure
call clear_LCD ; Clear LCD Display

; YOUR OPERATION CODE START HERE!!

;****************************************************************************
; To get the current temp use the following line of code:
;
; call Measure_Temp ; Returns the temperature in the DPTR
; ; Now DPTR has the 10-bit right
; ; justified value for temperature
;*****************************************************************************

; For this program, the keys are numbered as:

; +----+----+----+----+
; | 1 | 2 | 3 | A | row1
; +----+----+----+----+
; | 4 | 5 | 6 | B | row2
; +----+----|----+----+
; | 7 | 8 | 9 | C | row3
; +----+----+----+----+
; | * | 0 | # | D | row4
; +----+----+----+----+
; col1 col2 col3 col4

; The pressed key number will be stored in
; R0. Therefore, R0 is initially cleared.
; Each key is scanned, and if it is not
; pressed R0 is incremented. In that way,
; when the pressed key is found, R0 will
; contain the key''s number.

; The general purpose flag, F0, is used
; by the column-scan subroutine to indicate
; whether or not a pressed key was found
; in that column.
; If, after returning from colScan, F0 is
; set, this means the key was found.

start: mov R0, #0 ; clear R0 - the first key is key0

; scan row1
setb row4 ; set row4
clr row1 ; clear row1
call colScan ; call column-scan subroutine
jb F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found
; | and its number is in R0)

; scan row2
setb row1 ; set row1
clr row2 ; clear row2
call colScan ; call column-scan subroutine
jb F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found
; | and its number is in R0)

; scan row3
setb row2 ; set row2
clr row3 ; clear row3
call colScan ; call column-scan subroutine
jb F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found
; | and its number is in R0)

; scan row4
setb row3 ; set row3
clr row4 ; clear row4
call colScan ; call column-scan subroutine
jb F0, finish ; | if F0 is set, jump to end of program
; | (because the pressed key was found
; | and its number is in R0)

jmp start ; | go back to scan row 1
; | (this is why row4 is set at the
; | start of the program - when the
; | program jumps back to start, row4
; | has just been scanned)

finish: mov DPTR, #Table ; Initialize Data Pointer
mov A, R0 ; Move keynumber to acc
movc A, @A + DPTR ; Get key character

call display
clr F0 ; clear flag
jmp start ; Continue looking for next key



;*****************************************************************************
; SUBROUTINES
;*****************************************************************************

; YOUR KEYPAD, DISPLAY AND TEST SUBROUTINES SHOULD GO HERE!!




;*****************************************************************************
;*****************************************************************************
;
; Timer2_ISR:
;
; Every 0.2 seconds this ISR will be called.
; You will need to add code to take action during this IRS.
;
;*****************************************************************************

T2ISR:

; ADD YOUR TIMER2 ISR CODE HERE!!!!

clr TF2H ; Clears Timer 2 flag because unlike
; timers 0 & 1 the hardware does not
; clear timer 2 flag automatically
; during an ISR
reti ; Return to "where ever" from interrupt

;*****************************************************************************
;*****************************************************************************
;
; Init_Timer2
;
; This subroutine initializes Timer 2 to generate an interupt every 0.2
; seconds.
;
;*****************************************************************************

Timer2_Init:
mov TMR2RLL, #LOW (-25000) ; Load low byte reload value
mov TMR2RLH, #HIGH(-25000) ; Loads high byte reload value
mov TMR2L, #LOW (-25000) ; Loads initial byte value
mov TMR2H, #HIGH(-25000) ; Loads initial byte value
mov TMR2CN, #00000100B ; Configures Timer2
; 00000100B
; 1> Sets T2 to run
mov IE, #10100000B ; Enables interrupts
; 10100000B
; 1> Enable Global interrupt
; 1> Enable Timer2 interrupt
ret ; Return from CALL

;*****************************************************************************
;*****************************************************************************
;
; colScan subroutine
;
; The subroutine scans columns. It is called during each scan row event.
; If a key in the current row being scaned has been pressed, the subroutine
; will determine which column. when a key if found to be pressed, the
; subroutine waits until the key has been released before continuing. This
; method debounces the input keys.
;
; GLOBAL REGESTERS USED: R0
; GLOBAL BITS USED: F0(PSW.5)
; INPUT: col1(P1.4), col2(P1.5), col3(P1.6), col4(P1.7)
; OUTPUT: R0, F0
;
;******************************************************************************

colScan:
jb col1, nextcol ; check if col1 key is pressed
jnb col1, $ ; If yes, then wait for key release
jmp gotkey ; Have key, return
nextcol: inc R0 ; Increment keyvalue
jb col2, nextcol2 ; check if col2 key is pressed
jnb col2, $ ; If yes, then wait for key release
jmp gotkey ; Have key, return
nextcol2: inc R0 ; Increment keyvalue
jb col3, nextcol3 ; check if col3 key is pressed
jnb col3, $ ; If yes, then wait for key release
jmp gotkey ; Have key, return
nextcol3: inc R0 ; Increment keyvalue
jb col4, nokey ; check if col4 key is pressed
jnb col4, $ ; If yes, then wait for key release
jmp gotkey ; Have key, return
nokey: inc R0 ; Increment keyvalue
ret ; finished scan, no key pressed

gotKey: setb F0 ; key found - set F0
ret ; and return from subroutine


;*****************************************************************************
;*****************************************************************************
;
; init_LCD subroutine
;
; The subroutine is used initialize the LCD during startup.
;
; LOCAL REGISTERS USED: None
; INPUT:
; OUTPUT: LCD (P0), ENABLE (P1.4)
;
;*****************************************************************************

init_LCD:
clr RS ; Register Select ( 0 = Command )
clr RW ; Read/Write ( 1 = Read ; 0 = Write )
clr ENABLE ; High to Low Transition Stores the data
call delay ; Waits for LCD to stabilize
call reset_LCD ; Sends reset bytes to LCD
; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #38H ; 1 0 0 0 0 0 1 1 1 0 0 0 Function Set Word
;
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call busy ; Check Busy Flag
; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #08H ; 1 0 0 0 0 0 0 0 1 0 0 0 Display Off word
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call Busy ; Check Busy Flag
; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #0FH ; 1 0 0 0 0 0 0 0 1 1 1 1 Display On word
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call Busy ; Check Busy Flag
; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #06H ; 1 0 0 0 0 0 0 0 0 1 1 0 Entry Mode word
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call Busy ; Check Busy Flag
; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #02H ; 1 0 0 0 0 0 0 0 0 0 1 0 Display Home word
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call Busy ; Check Busy Flag
ret

;*****************************************************************************
;*****************************************************************************
;
; clear_LCD subroutine
;
; Clears the LCD.
; Used one 8-bit data move to send the Clear Display Instruction command
; (01H) to the LCD.
;
; The subroutine is used during initialization and when the display is full
; to clear the display before it wraps back to DDRAM address 00.
;
; INPUT: none
; OUTPUT: Port 0 (LCD) and P1.4 (ENABLE)
;
;*****************************************************************************

clear_LCD: ; E X R R D D D D D D D D
; | | S W 7 6 5 4 3 2 1 0
; | | | | | | | | | | | |
mov LCD, #01H ; 1 0 0 0 0 0 0 0 0 0 0 1 Clear Display
call Busy ; Check Busy Flag
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
ret

;*****************************************************************************
;*****************************************************************************
;
; display subroutine
;
; Moves the control or ASCII byte in the accumulator into the LCD 8-bits at
; a time.
;
; LOCAL REGISTERS USED: R3
; INPUT: byte in the Accumulator
; OUTPUT: One byte to the LCD.
;
;*****************************************************************************

display: ; The data to be sent is in A
setb RS ; Register Select ( 1 = Data )
mov LCD, A ; Sends data to LCD
setb ENABLE ; Latches the data
call delay ; Waits
clr ENABLE ; Then resets the latch

inc R3 ; R3 is used to keep track of LCD DDRAM
; After an ASCII char is sent, R3 is
; incremented
cjne R3, #8, next2 ; If R3=8 then the second line is used
call secondline
next2: cjne R3, #16, next3 ; If R3=16 then the LCD will need to
; start over
mov R3, #0 ; R3 is cleared
call clear_LCD ; This clears the LCD and resets the
; DDRAM to 0
next3: ret

;*****************************************************************************
;*****************************************************************************
;
; secondline subroutine
;
; This subroutine is called when the first line of the LCD is full and the
; second line of the LCD is about to be used. It initializes sets the
; DDRAM in the LCD to address 40H, the first address on the second line.
; This subroutine calls the init subroutine which uses the ACC, and DPTR
; so these registers must be saved (push) on the stack and later restored
; (pop) before returning.
;
; INPUT: none
; OUTPUT: none
; ACTION: Saves ACC and DPTR, loads DPTR with location of control word
; to set DDRAM address to 40H. Calls init to send control word.
; Restores ADD and DPTR to previous values.
;
;*****************************************************************************

secondline:
push ACC ; Saves ACC to stack
push DPH ; Saves
push DPL ; DPTR to stack
clr RS
mov LCD, #0C0H ; Moves Second Line word
setb ENABLE ; Latched the first byte
call delay ; Waits
clr ENABLE ; Then resets latch
call Delay
setb RS
pop DPL ; Restores
pop DPH ; DPTR
pop ACC ; Restores ACC
ret

;*****************************************************************************
;*****************************************************************************
;
; delay subroutine
;
; This subroutine is a simple delay loop that is used to provide timing for
; the LCD interface.
;
; LOCAL REGISTERS USED: R5, R6
; INPUT: none
; OUTPUT: none
; ACTION: Provides time delay for the LCD interface.
;
;*****************************************************************************

delay:
mov R6, #00h
Loop0: mov R5, #00h
djnz R5, $
; djnz R6, Loop0
ret

;*****************************************************************************
;*****************************************************************************
;
; reset_LCD
;
; Initialization by instruction
; This subroutine sends a Function Set byte (30H) to the LCD three times so that the
; LCD will reset correctly and communicate with the 8051.
;
; INPUT: none
; OUTPUT: LCD (P0), ENABLE (P1.4)
;
;*****************************************************************************

reset_LCD:
call delay
mov LCD, #30H ; Writes Function Set
setb ENABLE ; Latches Instruction
call delay ; Waits
clr ENABLE ; Then resets latch
call Busy ; Check Busy Flag delay
mov LCD, #30H ; Writes Function Set
setb ENABLE ; Latches Instruction
call delay ; Waits
clr ENABLE ; Then resets the latch
call Busy ; Check Busy Flagdelay
mov LCD, #30H ; Writes Function Set
setb ENABLE ; Latches Instruction
call delay ; Waits
clr Enable ; Then resets the latch
call Busy ; Check Busy Flag
ret

;******************************************************************************
;******************************************************************************
;
; Busy
;
; This Subroutine check the Busy Flag (DB7) to ensure the LCD is not busy
;
; INPUT P0.7
;******************************************************************************

Busy:
clr RS
setb RW
jb P0.7, $
clr RW
ret

;*****************************************************************************
;*****************************************************************************
;
; ADC0_Init
;
;
; Configure ADC0 to use ADBUSY as conversion source, and to sense internal
; Temp Sensor. Vref is used as the converson reference.
; Disables ADC end of conversion interrupt. Leaves ADC disabled.
;
;*****************************************************************************

ADC0_Init:
mov ADC0CN, #80H ; conversion initiated on every
; write of "1" to AD0BUSY
mov AMX0P, #00011110B ; select Internal Temp Sensor
mov AMX0N, #00011111B ; select ground (single-ended mode)
mov ADC0CF, #00001000B ; 00001000B
; 1>sets ADC conversion clk (750kHz)
; 0> ADC0H:ADC0L is right justified
;
mov REF0CN, #00000111B ; 00000111B
; 0> Vref used as voltage ref
; 1> internal temp sensor on
; 1> internal bias gen on
; 1> internal reference
; buffer enabled
anl EIE1, #0F7H ; disable ADC0 conversion
; complete interrupt
ret

;*****************************************************************************
;*****************************************************************************
;
; Measure_Temp
;
;
; Measures temperature through ADC. Puts Vtemp result in DPTR.
; Vtemp = ((2.86mV/C) * C) + 776mV => C= ((DPTR * (2.44/1024) -776mV)/2.86mV
;
; Returns 10-bit temp in DPTR
;
;*****************************************************************************

Measure_Temp:

clr AD0INT ; clears conversion completion flag
setb AD0BUSY ; initiates AD0 conversion
jnb AD0INT,$ ; waits for conversion to complete
mov DPL,ADC0L ; stores temperature (word) in
mov DPH,ADC0H ; DPTR
ret

;*****************************************************************************
; CONSTANTS
;*****************************************************************************
;
;
; YOUR DISPLAY CONVERSION "TABLE" CONSTANTS SHOULD GO HERE!!

; Use MOVC A, @A+DPTR to get here.
Table: DB ''????????????????''



;*****************************************************************************

; End of file.

END

Request for Solution File

Ask an Expert for Answer!!
Assembly Language: nomod51 nosymbols spring 2013
Reference No:- TGS0265606

Expected delivery within 24 Hours