Sida 1 av 3

Snabb hjälp med AVR önskas!

Postat: 14 september 2006, 15:14:36
av Johan.o
Hej, har problem med AVR, i mikrodator-kurs.
Inte ens läraren kan hjälpa mig med detta (!)

iaf så vill inte datorn inte komma ur mina subrutiner.
Detta är alltså ett enkelt blinka lysdioder på portB (alla utgångar har LED )
klockas med intern 1Mhz, använder STK500, och AVRstudio.
programmet funkar fram tills jag ska in i första subrutinen..
sedan händer det inget mer.. Lite fundersam om jag lagt in subrutinerna på rätt ställe?

Tacksam för hjälp..

Kod: Markera allt





.include "m16def.inc"	

.def 	count	= r18
.def 	temp	= r17 





.org 0
	jmp		main		; Gå till huvudprogrammet

wait_1ms:
	ldi		count,0xc8	; 200dec
loop_1ms:
	dec		count
	cpi		count,0
	brne	loop_1ms
	ret		

wait_1s:
	ldi		count,0xc8	; 200 dec
loop_1s:
	rcall	wait_1ms
	dec		count
	cpi		count,0
	brne	loop_1s
	ret	

main:
	ldi		temp, HIGH(RAMEND)	; Beräkna övre del av SP
	out		SPH, temp			; och lagra i SPH
	ldi 	temp, low(RAMEND)	; därefter lägre del av SP
	out		SPL, temp			; och lagra i SPL

	ldi		temp, 0xff		 
	out		DDRB, temp		; Sätter PortB = alla utgångar 
	ldi		r28, 0
	out		DDRA, r28		; Sätter PortA = Alla ingångar
	ldi		temp, 0x00
	out		PORTB, r28		; Nollställ	


loop:
	
	ldi		temp, 0x0f
	out		PORTB, temp	
	rcall	wait_1s
	ldi		temp, 0xff
	out		PORTB, temp
	rcall	wait_1s	
	jmp 	loop



Postat: 14 september 2006, 15:18:07
av sodjan
Kolla hur du använder "count".
Det är inte speciellt konstigt att det inte fungerar...

Postat: 14 september 2006, 15:29:14
av Johan.o
Tack sodjan :)
Ibland blir bara allt fel :oops:

Postat: 14 september 2006, 15:33:05
av sodjan
OK. Då såg alltså vad det var, eller hur ?

Det som var mest förvånande i ditt inlägg var :
> "Inte ens läraren kan hjälpa mig med detta (!)"...

Postat: 14 september 2006, 15:36:13
av Johan.o
Nä, han visste inte hur man fick igång så subrutiner funkade..
Utan var mest van vid att använda en c-kompilator där allt sånt sköts i ett "färdigt skal"

Eftersom jag fortfarande trodde att det var stacken subrutin-anropen som var fel så...

Nåväl jag bytte count -> count2 i ena subrutinen..

Postat: 14 september 2006, 15:41:40
av sodjan
Vilka sopa... (läreren) !!
Hur f-n kan han leda en AVR kurs !!??
Jag har aldrig skrivit en rad kod till AVR, men det tog 10 sek att se felet...

För övrigt är din åtgärd helt rätt.

En C-komp hade antagligen hanterat "count" com "local" (beroende på hur man skriver koden)...
D.v.s att det hade blivit två olika instanser av "count".

EDIT:
Har eran utvecklingsmiljö ingen simulator ?
Typ MPSIM i MPLAB (för PIC) ?

Postat: 14 september 2006, 15:56:50
av björn
Får verkligen hålla med Sodjan angående en lärare som inte hittar det felet (för det var väl inte som han tyckte att du skulle hitta det själv?).

AVRStudio har simulering.

Postat: 14 september 2006, 17:05:20
av Johan.o
Först så bad jag om hjälp, då jag inte fick min subrutin att funka
(wait_1s) som även innuti anropar wait_1ms. Gick igenom den men vi hittade inte felet.

Då hade jag inte förstått att man var tvungen att använda rcall och
initiera stacken, villket inte han heller viste.

Så att det största felet då, var att felaktiga 'call' användes samt att
vid 'ret' så hämtades felaktig återvänds-adress från stacken.

Sedan så löste jag det på egen hand, men antog att det fortfarande
var problem med att gå in/ur subrutiner..

Men jo, jag tycker också han verkar ha lite dålig koll på AVR..
Det ska ju inte vara okänt hur man använder sig av subrutiner för honom.

Sedan får jag nog påstå att det var lite sopigt av mig själv att göra ett sådant fel.
Jag har ändå programmerat (PIC) assembler i många år, och bör inte gå bet på något sådant enkelt.

Postat: 14 september 2006, 19:15:30
av exile
Lite sopit av läraren....

jag ser att du använder cpi x,0 efter dec vilket är helt onödigt efter som dec ändra Z-flagan när registret blir noll...

Sedan behöver du inte använda rcall utan kan använda call, skilnade mellan rcall och call är att rcall endast kan hoppa +/-2k instruktioner medans call kan hoppa +/-2048k instruktioner där imot tar rcall endast 2byte medans call tar 4byte och längre tid att köras...

Sedan vill jag slå ett slag för använda 16bitar eller mer, som kan göras väldigt enkelt med AVR exemple

Kod: Markera allt

.include "m16def.inc"

.def    counth	= r19	//
.def    countl	= r18	//16bitar
.def    temp	= r16 

jmp reset

wait:
	.equ	conts = 500	//vänte tiden
	ldi		counth,high(conts)
	ldi		countl,low(conts)	//count = 500;
w_loop:						//do{
	subi	countl,low(1)			//
	sbci	counth,high(1)			//	count--;
	brne	w_loop				//} while (count)
	ret

reset:
	ldi		temp, HIGH(RAMEND)
	out		SPH, temp
	ldi		temp, low(RAMEND)
	out		SPL, temp
	
	ldi		temp, 0xff
	out		DDRB, temp
loop:
	rcall	wait
	in		temp, PORTB
	com		temp
	out		PORTB, temp
	rjmp	loop
^^

Postat: 11 oktober 2006, 14:46:13
av Johan.o
Fortsatta problem i den mikrodatorkurs jag läser, programmerar atmel MEGA 16, nu skrivs koden i C.

Jag har problem med att i en interrupt-rutin så ändrar jag värdet på en variabel "value" som är definerad i början av programmet.

Probelmet är att jag försöker ändra på value i interuupten men det förblir ofärändrat, hur löser jag det?
Läraren har som vanligt ingen aning.

använder några filer som serverats på silverfat för att interrupt ska fungera,
interrupt.h och signal.h , programmerar i winAVR.
såhär ser mitt program ut:

Kod: Markera allt


#include <io_atmega16.h>
#include <stdio.h>
#include <avr/delay.h>
#include <delay_loop.h>
#include <lcd4.h>
#include <signal.h>
#include <interrupt.h>


// --- Globala objekt ---

lcd4 		theDisplay;
delay_loop 	theDelay;


int  value=0;

//--- Main ---

int main(void)
{

	char s[20];

	
	
	//--- Intitiering av portar ---
	
	
	DDRA  = 0xFF;				// Alla utgångar
	DDRB  = 0xFF;				// Alla utgångar	
	DDRC  = 0xFB;				// PD2 ingång, resten utgångar
	MCUCR = 0x03;				// Positiv flank på INT0 genererar interrupt
	GICR  = 0x40;				// INT0 enable
	
	//--- Initiering av objects ---
	lcd4_init(&theDisplay,&PORTC, &DDRC, 4000,50);
	
	delay_loop_init(&theDelay, 5000, DELAY_LOOP_8MHZ );
	
	
	
	
		SREG = 0x80;					// Global aktiveing av interrupt
		
	while(1)
	  { 
	   sprintf(s, "Pulser=%x st", value);
		
   
       lcd4_cup_row1(&theDisplay);
	   lcd4_write_string(&theDisplay, s);
	   
	   delay_loop_delay(&theDelay);
	  }

    SIGNAL(SIG_INTERRUPT0)
    {
	  value++;
    }

	return 0;
}

edit: Ändrade kod enligt Icecaps förslag

Postat: 11 oktober 2006, 15:09:15
av Icecap
"Value" är definierat i "main" vilket gör att den inte kan ses av interruptrutinen. "Value" är alltså en lokal variabel som ägs (och "ses") enbart av main. Flytt deklarationen till "grunden" alltså strax in under "// --- Globala objekt ---"

Edit: sopig lärare!

Postat: 11 oktober 2006, 15:36:46
av Johan.o
Funkar ändå inte, trots att jag flyttar det, ändrade i bifogad kod så du ser vart jag la den nu..
Japp totalsopig, man får inte lära sig något så jag vet inte riktigt vad jag gör.

Postat: 11 oktober 2006, 15:43:17
av Icecap
Testa att definiera den som:
volatile int value;

Det är inte standart att man assigner ett värde i deklarationen, det är inte alla kompilers som klarar det.

Postat: 11 oktober 2006, 15:44:20
av calmar
Jag vet inte hur interrupt i winAVR fungerar, men det kan vara värt att prova att ändra deklarationen till

Kod: Markera allt

volatile int value = 0;
.

Postat: 11 oktober 2006, 15:45:24
av Johan.o
Funkar ej heller med volatile int value; :(