Need some help with a program; in assembly language modify this program for an a
ID: 3683401 • Letter: N
Question
Need some help with a program; in assembly language modify this program for an alarm clock, to a digital clock. Use the LCD to display the time. Please add comments to modified part.
;
; NOTE - DIP Switches must be up (open)
; Switch SW2 -- toggles alarm arming (indicated by right decimal point LED), also
; stops the alarm (without disarming) if it is sounding. Also used to view alarm
; time and (when held down) will allow setting the alarm time.
; Switch SW3 -- Depress and hold while setting the time.
; Switch SW4 -- In combination with SW2 sets the alarm hour and with SW3 set the time hour
; Switch SW5 -- In combination with SW2 sets the alarm minute and with SW3 sets the alarm hour
; Setting the time minutes or hours will also reset the internal seconds counter to zero. The
; buttons are debounced and the hour/minute setting have auto-repeat every half second.
; The Left decimal point LED indicates "pm". The center decimal point LEDs flash once per second.
; The right decimal point LED indicates the alarm is armed.
AMPM equ 0 ; Comment out for a 24 hour clock (no AM/PM indication)
#include registers.inc ; include register equates and memory map
;
MULTI_MODE equ $10
SINGLE_MODE equ 0
SCAN_MODE equ $20
NO_SCAN_MODE equ 0
CHANNEL_NUM: equ 7 ; reading input from AN07
ALARM_SW equ %1000 ; Alarm switch (0 if depressed)
TIME_SW equ %100 ; Time set switch (0 if depressed)
HOUR_SW equ %10 ; Hour switch (0 if depressed)
MINUTE_SW equ %1 ; Minute Switch (0 if depressed)
TB1MS: equ 24000 ; 1ms time base of 24,000 instruction cycles
; ; 24,000 x 1/24MHz = 1ms at 24 MHz bus speed
org DATASTART
;
select: rmb 1 ; current digit being displayed
disptn: rmb 4 ; Normal display digits
dispdp: rmb 4 ; decimal point display digits
normalpm: equ dispdp
flashsec equ dispdp+1
flashsec2 equ dispdp+2
alarmon equ dispdp+3
dispta: rmb 4 ; alarm display digits
dispadp: rmb 4 ; decimal point display for alarm
alarmpm: equ dispadp
alarmon2: equ dispadp+3
milisecs rmb 2 ; Millisecond counter (reset every second)
seconds rmb 1 ; Seconds counter, reset every minute
debounce rmb 1 ; time for debounce
lastbuttons rmb 1 ; last button values
repeat rmb 2 ; repeat time
brtness: rmb 1
isoff: rmb 1
buzzing: rmb 1
;
; Segment conversion table:
;
; Binary number: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
; Converted to 7-segment char: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
;
; Binary number: $10,$11,$12,$13,$14,$15,$16,$17
; Converted to 7-segment char: G H h J L n o o
;
; Binary number: $18,$19,$1A,$1B,$1C,$1D,$1E,$1F,$20
; Converted to 7-segment char: P r t U u y _ -- Blank
;
org PRSTART
;
jmp start
segm_ptrn: ; segment pattern
fcb $3f,$06,$5b,$4f,$66,$6d,$7d,$07 ; 0-7
; 0, 1, 2, 3, 4, 5, 6, 7
fcb $7f,$6f,$77,$7c,$39,$5e,$79,$71 ; 8-$0f
; 8, 9, A, b, C, d, E, F
fcb $3d,$76,$74,$1e,$38,$54,$63,$5c ; 10-17
; G, H, h, J L n o o
fcb $73,$50,$78,$3e,$1c,$6e,$08,$40 ; 18-1f
; P, r, t, U, u Y - -
fcb $00,$01,$48,$41,$09,$49 ; 20-23
; blk, -, =, =, =, =
;
;
; this routine will read adc input on the pin AN07 and store the result at adr07h
;
;
adc_conv:
adda #SINGLE_MODE+NO_SCAN_MODE
;
; if you want to read multi-channel input, change above statement to
; adda #MULTI_MODE+NO_SCAN_MODE
;
staa ATD0CTL5
not_ready:
brclr ATD0STAT $80 not_ready
rts
start:
lds #DATAEND
#ifdef INITIALIZEVECTORS
movw #timer5,UserTimerCh5 ; initialize the int vector
movw #timer6,UserTimerCh6 ; initialize the int vector
movw #timer7,UserTimerCh7 ; initialize the int vector
#endif
ldaa #$ff ; turn off 7-segment display
staa PTP ; portp = 11111111
;
staa DDRB ; portb = output
staa DDRP ; portp = output
clr DDRH ; porth = input
ldaa #$80
staa TSCR ; enable timer
ldaa #$E0
staa TIOS ; select t5, t6, t7 as an output compares
staa TMSK1
bset tctl1,#$4 ; t5 in toggle mode
bset tctl1,#$8 ; turn off alarm sound
bset ATD0CTL2 $80 ; enable adc operation
bset ATD0CTL3 $40 ; 8 conversion needed for an07
clr isoff
clr select
movb #$ff,brtness
ldaa #$20
ldx #disptn ; flashing 8s on display
staa 1,x+ ; reset to flashing 8s
staa 1,x+
staa 1,x+
staa 1,x+
clr 1,x+ ; clear the status decimal points
clr 1,x+
clr 1,x+
clr 1,x+
ldx #dispta
movb #1,1,x+ ; 12:00 is setting for alarm
movb #2,1,x+
ldaa #11 ; 0 in alarm minutes and decimal points, milliseconds, seconds
l1: clr 1,x+
dbne a,l1
movw #$8080,dispadp+1 ; show static colon in alarm time
clr buzzing
cli
;
begin: ldaa #CHANNEL_NUM ; set channel number before calling
jsr adc_conv
movb ADR07H,brtness
jmp begin
timer5:
; speaker
bclr TFLG1,#~$20 ; clear flag
ldd #TB1MS*2
addd TC5
std TC5
rti
timer6:
; Timer 6 keeps display refreshed
bclr TFLG1,#~$40 ; clear flag
com isoff
beq noton
ldd #TB1MS ; reload the count for 1 ms time base
addd TC6
std TC6
cli ; allow other interrupts to occur
ldab select
incb
andb #3
stab select
tfr b,x ; select value in X
ldaa PTP ; only alter port p bits we are using
anda #$f0
oraa dspmap,x
staa PTP
brclr PTH,ALARM_SW,dispalarm ; display alarm time?
leax disptn,x
bra dispnorm
dispalarm: leax dispta,x
dispnorm:
ldaa 0,x
ldy #segm_ptrn
ldaa a,y ; get converted value
oraa 4,x ; set dp if required
staa PORTB
rti
noton: clr PORTB
ldaa brtness
ldab #$ff
addd TC6
std TC6
rti
timer7:
; Timer 7 runs handles the user interface and updates the time
bclr TFLG1,#~$80
ldd #TB1MS
addd TC7
std TC7
cli ; allow other interrupts to occur
ldx milisecs
inx ; increment miliseconds
stx milisecs
cpx #500
beq halfsec
cpx #1000 ; on the second
bne noflash ; no -- handle buttons
secactivity:
movw #0,milisecs
inc seconds
ldaa seconds
cmpa #60 ; Update minute display
bne halfsec ; no -- do half second activity
clr seconds
ldx #disptn
jsr incrementM ; increment minute
bne tcheck ; returns having set CCR on minutes
jsr incrementH ; increment hours
tcheck: jsr alarmcheck ; check alarm every minute after correcting time
halfsec: ldx #disptn
ldaa flashsec-disptn,x ; do flashing
eora #$80
staa flashsec-disptn,x
staa flashsec2-disptn,x
ldaa disptn ; check to see if blank or 8
cmpa #$20
beq flash
cmpa #$08
bne noflash
flash: ldab #4 ; flash the display
flashl: ldaa 0,x
eora #$28
staa 1,x+
dbne b,flashl
; handle buttons
noflash: ldaa PTH ; get port h (button) value
cmpa lastbuttons ; changed value?
beq nochange
staa lastbuttons ; new buttons
movb #10,debounce ; Do something after 10 counts
movw #-1,repeat ; Signify first entry
rti
nochange: ldab debounce ; are we debouncing
beq nobounce ; zero if not
decb
stab debounce ; wait for debouncing period to be over
rti
nobounce: anda #$0f ; only look at bottom switches
cmpa #15-TIME_SW-MINUTE_SW ; Minute time?
bne notmintime
ldx repeat
cpx #0
ble processmintime
dex
stx repeat
rti
processmintime:
movw #500,repeat ; delay until repeat
ldx #disptn
jsr powoncheck
clr seconds
movw #0,milisecs
jsr incrementM
rti
notmintime:
cmpa #15-TIME_SW-HOUR_SW ; Hour time?
bne nothourtime
ldx repeat
cpx #0
ble processhourtime
dex
stx repeat
rti
processhourtime:
movw #500,repeat ; delay until repeat
ldx #disptn
jsr powoncheck
clr seconds
movw #0,milisecs
jsr incrementH
rti
nothourtime:
cmpa #15-ALARM_SW-MINUTE_SW ; Minute alarm?
bne notminalarm
ldx repeat
cpx #0
ble processminalarm
dex
stx repeat
rti
processminalarm:
movw #500,repeat ; delay until repeat
ldx #dispta
jsr incrementM
rti
notminalarm:
cmpa #15-ALARM_SW-HOUR_SW ; Hour alarm?
bne nothouralarm
ldx repeat
cpx #0
ble processhouralarm
dex
stx repeat
rti
processhouralarm:
movw #500,repeat ; delay until repeat
ldx #dispta
jsr incrementH
rti
nothouralarm:
cmpa #15-ALARM_SW ; just the alarm button
bne nobutton
ldx repeat ; don't allow repeats
bge nobutton
movw #0,repeat ; only one performance
tst buzzing ; is it buzzing?
bne killbuzz
ldaa alarmon ; else toggle alarm
eora #$80
staa alarmon
staa alarmon2
rti
killbuzz:
jsr alarmoff
nobutton:
rti
alarmcheck:
tst alarmon
beq alarmoff ; if alarm is turned off, make sure sound is off
ldy #dispta
ldaa 1,x+
cmpa 1,y+
bne alarmoff
ldaa 1,x+
cmpa 1,y+
bne alarmoff
ldaa 1,x+
cmpa 1,y+
bne alarmoff
#ifdef AMPM
ldaa 1,x+
cmpa 1,y+
bne alarmoff
#endif
ldaa 0,x
cmpa 0,y
bne alarmoff
alarmsound:
bclr TCTL1,#$8 ; turn on alarm sound
inc buzzing
rts
alarmoff:
bset TCTL1,#$8 ; turn off alarm sound
clr buzzing
rts
powoncheck: ; Resets time if flashing 8's
ldaa 0,x
cmpa #8
beq pon2
cmpa #$20
bne pon3
pon2:
#ifdef AMPM
movw #1,0,x
#else
movw #0,0,x
#endif
movw #0,2,x
pon3: rts
incrementM: ; Increment the minute value
; X has address of buffer for time display or alarm display
ldd 2,x ; get minute value into A:B
incb
cmpb #10
bne doneinc
clrb
inca
cmpa #6
bne doneinc
clra
doneinc: std 2,x ; condition code will be Z=1 if hour to be incremented
rts
incrementH: ; increment the hour value
; X has address of buffer for time display or alarm display
ldd 0,x
incb
cmpb #10
bne chk24
clrb
inca
chk24:
#ifdef AMPM
cpd #$0102 ; 12 - toggle AMPM
bne not12
psha
ldaa 4,x ; get AMPM indicator
eora #$80 ; toggle it
staa 4,x
pula
bra doneinch
not12: cpd #$0103 ; 13 -- make it 1
bne doneinch
ldd #$1
#else
cpd #$0204
bne doneinch
ldd #0
#endif
doneinch: std 0,x
rts
dspmap: db $0e,$0d,$0b,$07
#ifdef STATICVECTORS
org UserTimerCh5
dw timer5
org UserTimerCh6
dw timer6
org UserTimerCh7
dw timer7
#endif
end
Explanation / Answer
//**************************************************************//
//System Clock :2MHz
//Software :AVR Studio 4
//LCD Interfacing :8-Bit
//TWI Frequency :100KHz
//**************************************************************//
#include<avr/io.h>
/*Includes io.h header file where all the Input/Output Registers and its Bits are defined for all AVR microcontrollers*/
#define F_CPU 2000000
/*Defines a macro for the delay.h header file. F_CPU is the microcontroller frequency value for the delay.h header file. Default value of F_CPU in delay.h header file is 1000000(1MHz)*/
#include<util/delay.h>
/*Includes delay.h header file which defines two functions, _delay_ms (millisecond delay) and _delay_us (microsecond delay)*/
#define LCD_DATA_PORT PORTB
/*Defines a macro for the lcd.h header File. LCD_DATA_PORT is the microcontroller PORT Register to which the data pins of the LCD are connected. Default PORT Register for data pins in lcd.h header file is PORTA*/
#define LCD_CONT_PORT PORTD
/*Defines a macro for the lcd.h header File. LCD_CONT_PORT is the microcontroller PORT Register to which the control pins of the LCD are connected. Default PORT Register for control pins in lcd.h header file is PORTB*/
#define LCD_RS PD0
/*Defines a macro for the lcd.h header file. LCD_RS is the microcontroller Port pin to which the RS pin of the LCD is connected. Default Port pin for RS pin in lcd.h header file is PB0*/
#define LCD_RW PD1
/*Defines a macro for the lcd.h header file. LCD_RW is the microcontroller Port pin to which the RW pin of the LCD is connected. Default Port pin for RW pin in lcd.h header file is PB1*/
#define LCD_EN PD2
/*Defines a macro for the lcd.h header file. LCD_EN is the microcontroller Port pin to which the EN pin of the LCD is connected. Default Port pin for EN pin in lcd.h header file is PB2*/
#include<avr/lcd.h>
/*Includes lcd.h header file which defines different functions for all Alphanumeric LCD(8-Bit Interfacing Method). LCD header file version is 1.1*/
#include<avr/ds1307.h>
/*Includes ds1307.h header file which defines different functions for DS1307 Real Time Clock. DS1307 header file version is 1.1*/
int main(void)
{
DDRB=0xff;
/*All the 8 pins of PortB are declared output (data pins of LCD are connected)*/
DDRD=0x07;
/*PD0, PD1 and PD2 pins of PortD are declared output (control pins of LCD are connected)*/
unsigned char hour=0,sec=0,min=0,am_pm=0,day=0,date=0,month=0,year=0;
/*Variable declaration*/
twi_init();
/*TWI initialisaiton*/
lcd_init();
/*LCD initialisaiton*/
lcd_string_write(“ABLab Solutions”);
/*String display in 1st row of LCD*/
lcd_command_write(0xc0);
/*Cursor moves to 2nd row 1st column of LCD*/
lcd_string_write(“www.ablab.in”);
/*String display in 2nd row of LCD*/
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
/*Display stays for 2 second*/
lcd_command_write(0x01);
/*Clear screen*/
/*DS1307 write section starts here*/
ds1307_second_write(0);
/*Writting second value in DS1307*/
ds1307_minute_write(0);
/*Writting minute value in DS1307*/
ds1307_hour_write(11,1,0);
/*Writing hour value in 12 hour format with PM in DS1307*/
ds1307_day_write(3);
/*Writting day(Wednesday) value in DS1307*/
ds1307_date_write(1);
/*Writting date value in DS1307*/
ds1307_month_write(1);
/*Writting month value in DS1307*/
ds1307_year_write(14);
/*Writting year value in DS1307*/
/*DS1307 write section ends here*/
/*Start of infinite loop*/
while(1)
{
sec=ds1307_read_second();
/*Reading second value from DS1307*/
min=ds1307_read_minute();
/*Reading minute value from DS1307*/
hour=ds1307_read_hour();
/*Reading hour value from DS1307*/
day=ds1307_read_day();
/*Reading day value from DS1307*/
date=ds1307_read_date();
/*Reading date value from DS1307*/
month=ds1307_read_month();
/*Reading month value from DS1307*/
year=ds1307_read_year();
/*Reading year value from DS1307*/
/*Checking AM/PM status*/
if((hour & 0x20) == 0x20)
{
am_pm=1;
/*Hour time is PM*/
}
else
{
am_pm=0;
/*Hour time is AM*/
}
lcd_command_write(0x80);
/*Cursor moves to 1st row 1st column of LCD*/
hour=convert_bcd_to_decimal((hour & 0x1f));
/*Converting BCD number to Decimal value*/
lcd_number_write(hour ,10);
/*Hour value display in 1st row of LCD*/
lcd_data_write(‘:’);
/*Character(:) display in 1st row of LCD*/
min=convert_bcd_to_decimal(min);
/*Converting BCD number to Decimal value*/
lcd_number_write(min,10);
/*Minute value display in 1st row of LCD*/
lcd_data_write(‘:’);
/*Character(:) display in 1st row of LCD*/
sec=convert_bcd_to_decimal(sec);
/*Converting BCD number to Decimal value*/
lcd_number_write(sec,10);
/*Second value display in 1st row of LCD*/
lcd_data_write(‘ ‘);
/*Character display in 1st row of LCD*/
/*Checking AM/PM status to display in LCD*/
if(am_pm == 1)
{
lcd_string_write(“PM “);
/*String display in 2nd row of LCD*/
}
else
{
lcd_string_write(“AM “);
/*String display in 2nd row of LCD*/
}
lcd_command_write(0xc0);
/*Cursor moves to 2nd row 1st column of LCD*/
date=convert_bcd_to_decimal(date);
/*Converting BCD number to Decimal value*/
lcd_number_write(date,10);
/*Date value display in 2nd row of LCD*/
lcd_data_write(‘:’);
/*Character(:) display in 2nd row of LCD*/
month=convert_bcd_to_decimal(month);
/*Converting BCD number to Decimal value*/
lcd_number_write(month,10);
/*Month value display in 2nd row of LCD*/
lcd_data_write(‘:’);
/*Character(:) display in 2nd row of LCD*/
year=convert_bcd_to_decimal(year);
/*Converting BCD number to Decimal value*/
lcd_number_write(year,10);
/*Year value display in 2nd row of LCD*/
lcd_data_write(‘ ‘);
/*Character display in 1st row of LCD*/
/*Switch statement to display day in LCD*/
switch(day)
{
case 1:
lcd_string_write(“MON “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 2:
lcd_string_write(“TUE “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 3:
lcd_string_write(“WED “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 4:
lcd_string_write(“THU “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 5:
lcd_string_write(“FRI “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 6:
lcd_string_write(“SAT “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
case 7:
lcd_string_write(“SUN “);
/*String display in 2nd row of LCD*/
break;
/*Break statement*/
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.