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 ENDMACROExplanation / 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