Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I\'m writing an Assembly code to blink the LED on an AVR ATMEGA328P microcontrol

ID: 2291283 • Letter: I

Question

I'm writing an Assembly code to blink the LED on an AVR ATMEGA328P microcontroller by creating a time delay by programming the Timer0 in the chip. I'm having a problem where the LED remains turned on and will not blink. After doing some testing, I found that the program was never exiting the L1 loop in the macro I wrote for the time delay, suggesting that the TOV0 flag was never being set. What is it that I have coded wrong to result in this? Above is the code I have written for the time delay macro. The rest of the code where the LED bit is actually being set is not shown as I have already discovered the issue is in the time delay macro. Any help is appreciated, thanks in advance.

MACRO DELAY LDI R16, 0x00 OUT TCNTe, R16; Set initial count value to e LDI R16, 0x05 OUT TCCRe, R16; Set timer to normal mode, and 1024 prescaler LI: IN R20, TIFR SBRS R20, TOVe; Skip next instruction if TOVO is set RJMP L1 LDI R16, 0x00 OUT TCCRO, R16; Stop timer LDI R16, (1??Tove) OUT TIFR, R16; Clear Tove flag ENDMACRO

Explanation / Answer

/*

* Atmega2560asmtest.asm

*

* Created: 6/1/2015 3:46:37 PM

* Author: DarkSector

*/

.EQU F_CPU = 16000000

.ORG 0

LDI R16, LOW(RAMEND)

OUT SPL, R16

LDI R16, HIGH(RAMEND)

OUT SPH, R16

;MAIN LABEL

MAIN:  

LDI R16, 0xFF  

OUT DDRB, R16 ;PORTB IS OUTPUT

BACK:  

COM R16 ;COMPLEMENT THE VALUE IN R16  

OUT PORTB, R16 ;PUSH THE VALUE IN R16 TO PORTB  

CALL DELAY  

RJMP BACK ;KEEP DOING THIS INFINITELY

DELAY:  

LDI R17, 100  

LOOP3: LDI R18, 255  

LOOP2: LDI R19, 255  

LOOP1: DEC R19  

BRNE LOOP1 ;KEEP DECREASING R19  

DEC R18  

BRNE LOOP2 ;FOR EVERY DECREASE OF R18 REDO THE PREVIOUS LOOP  

DEC R17  

BRNE LOOP3 ;FOR EVERY DECREASE OF R17 REPEAT PREVIOUS LOOP  

RET ;RETURN TO PREVIOUS PC ADDRESS  

/*

* atmega2560_test.c

*

* Created: 6/1/2015 3:23:10 PM

* Author: DarkSector

*/

#define F_CPU 16000000UL

#include <avr/io.h>

#include <util/delay.h>

int main(void)  

{

DDRB |= 0xFF;

while(1)

{

PORTB = 0xFF;

_delay_ms(500);

PORTB = 0x00;

_delay_ms(500);

}

}

in c program

.include "m8def.inc"

.dseg

.def temp = r16

.def delay1 = r17

.def delay2 = r18

.def delayv = r19

.equ led = 4 ; PORTD bit number to blink LED on

.cseg

.org $000

rjmp main

delay:

clr delay1

clr delay2

ldi delayv, 100

delay_loop:

dec delay2

brne delay_loop

dec delay1

brne delay_loop

dec delayv

brne delay_loop

ret ; go back to where we came from

main:

ldi temp,low(RAMEND)

out SPL,temp

ldi temp,high(RAMEND)

out SPH,temp

sbi DDRD, led ; connect PORTD pin 4 to LED

loop:

cbi PORTD, led ; turn PD4 high

rcall delay ; delay for an short bit

sbi PORTD, led ; turn PD4 low

rcall delay ; delay again for a short bit

rjmp loop ; recurse back to the head of loop

This should work fine, if not try this delay routine which is tested:

;*************Delay(1sec) Module***********************

delay_1sec:

push delay1

push delay2

push delayv

ldi temp,$ff

mov delay1,temp

ldi temp,$13

mov delay2,temp

ldi temp,$06

mov delayv,temp

de:

dec delay1

brne de

dec delay2

brne de

dec delayv

brne de

pop delay1

pop delay2

pop delayv

ret