-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 20

Thema: Atmega16 springt zu $0000, Reset?

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.05.2005
    Ort
    Chemnitz
    Alter
    28
    Beiträge
    104

    Atmega16 springt zu $0000, Reset?

    Anzeige

    Hallo Leute,

    ich hab ein eigenartiges Problem: Mein Atmega16 beginnt nach 66 sekuendiger fehlerfreier Programmausfuehrung ploetzlich wieder bei der Adresse $0000 mit dem Programm. Ich glaube allerdings nicht, dass es sich um einen Reset handelt, weil ich den Reset-Pin richtig angeschlossen hab, keinen Watchdog verwende, dieses JTAG-interface ausgeschalten habe und die Betreibsspannung nicht schwankt. Außerdem werden die Register nicht mit ihren Anfangswerten initialisiert, sondern behalten ihre derzeitigen Werte bei. Woran koennte das liegen? Ich waer echt dankbar, wenn mir jemand helfen kann, weil ich langsam am verzweifeln bin.

    Danke im Voraus.

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.08.2005
    Ort
    49.80248 8.59252
    Alter
    33
    Beiträge
    172
    Macht er das immer nach genau 66sek?
    Koentest du uns das Programm geben?

  3. #3
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Kann sein, daß das nix damit zu tun hat. Aber wenn ich den ISP angeschlossen lasse, kriegt der Chip gelegentlich einen auf die Glocke vom Brennerprogramm.
    Für störungsfrei (von der Seite) muß ich abstecken
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.05.2005
    Ort
    Chemnitz
    Alter
    28
    Beiträge
    104
    Das ging aber schnell! Danke.

    Ja der macht das aller 66 Sekunden. Es ist egal, ob das ISP angeschlossen ist oder nicht, der Fehler tritt trotzdem auf.

    Das Programm ist allerdings ein ganzes Stueck lang, weil ich ein LCD angeschlossen hab:
    Code:
    .nolist
    .include "m16def.inc"
    .list
    
    .def data = r0
    .def flag = r10
    .def temp = r16
    .def tim1 = r17
    .def tim2 = r18
    .def addr = r20
    .def tmp1 = r19
    .def blinkr = r21
    .def cnt  = r22
    .def bin  = r23
    .def lowb = r24
    .def highb = r25
    
    .equ RS	  = 4			;alle von PortC
    .equ RW	  = 5	 
    .equ E    = 6
    
    .equ Minus = 0
    
    .cseg
    initial:	
    			cbi PortD, 7				;Hintergrundbeleuchtung ausschalten
    
    			ldi temp, low(ramend)
    			out SPL, temp
    			ldi temp, high(ramend)
    			out SPH, temp				;Stackpointer initialisiert
    
    			ldi temp, 0b10000000 		;MSB setzen (JTD)
    			out MCUCSR, temp				
    			out MCUCSR, temp			;2x -> kein JTAG
    
    			;I/O-Ports definieren 
    
    			ldi temp, 0b11000000
    			out DDRD, temp				;Port D: Pin7,6->A, Rest->E							
    			ldi temp, 0b00000001
        		out DDRB, temp				;Port B: Pin1->Ausgang, Rest->Eingang							
    			ldi temp, 0xFF
    			out DDRC, temp				;Port C -> Ausgang			
    
    			;A/D-Wandler initialisieren
    			sbi ADCSR, 7				;anschalten
    			in temp, ADCSR
    			sbr temp, 0b00100111		;Vorteiler=128; ADC an, Autotrigger
    			out ADCSR, temp			    ;uebernehmen
    			ldi temp, 0b11000001        ;V(ref) = 2,56V; kanal1
    			out ADMUX, temp
    			sbi ADCSR, 6				;und los
    
    LCDinit:	cli
    			call wait500ms
    			call wait500ms
    			ldi temp, 0b11
    			out PortC, temp
    			call enable								;erstesmal uebernehmen
    			call wait5ms
    			call enable								;2.mal uebernehmen
    			call wait5ms
    			call enable								;3.mal uebernehmen
    			call wait5ms
    			ldi temp, 0b00000010					;4-bit Modus einstellen
    			call SendCom
    			ldi temp, 0b00101000					;Zeilenzahl und Matrix setzen
    			call SendCom
    			ldi temp, 0b00001000					;Display abschalten
    			call SendCom
    			ldi temp, 0b00000001					;Display loeschen
    			call SendCom
    			ldi temp, 0b00000110					;Eingabemodus setzen
    			call SendCom
    			ldi temp, 0b00001100					;Display einschalten
    			call SendCom							; ohne Cursor und ohne blinken
    			sei
    
    			ldi ZL, low(text1)
    			ldi ZH, high(text1)
    			call SendTxt
    			ldi temp, 0b11000011
    			call SendCom
    			ldi ZL, low(GradC)
    			ldi ZH, high(GradC)
    			call SendTxt
    			ldi temp, 0b11001110
    			call SendCom
    			ldi ZL, low(GradC)
    			ldi ZH, high(GradC)
    			call SendTxt
    			sbi PortD, 7				;Hintergrundbeleuchtung einschalten
    
    endlos:		call wait5ms
    			in lowb, ADCL							;Lowbyte der Umwandlung einlesen
    			in highb, ADCH							;Highbyte einlesen
    			push lowb
    			push highb								;fuer spaeter
    			ldi temp, 0b11000000			
    			call SendCom
    			call umrech	
    			ldi temp, 0b0							;		
    			call chngchnl							;2.Kanal (Kanal1) auswaehlen			
    			call wait5ms							;Zeit fuer neue Umwandlungen lassen
    			in lowb, ADCL							;Lowbyte der Umwandlung einlesen
    			in highb, ADCH							;Highbyte einlesen
    			ldi temp, 0b11001011
    			call SendCom
    			call umrech			
                ldi temp, 0b1
    			call chngchnl
    			cbi PortB, 0
    			sbrc flag, Minus						;IP+2 bei gesetztem "Minus"-flag
    			sbi PortB, 0
    			jmp endlos								;von vorn
    			
    
    
    ;---Prozeduren fuer die verschiedenen Zeitspannen---
    wait5ms:	cli
    			push temp
    			ldi temp, 78
    			out OCR0, temp			    ;OutputCompareRegister=10000
    			ldi temp, 0b101
    			out TCCR0, temp	     		;8bit-Timer mit Vorteiler=8 starten
    warten:		in  temp, TIFR
    			sbrs temp, 1				;Flag testen (TCNT0=OCR0)
    			jmp warten
    			sbr temp, 0b10
    			out TIFR, temp				;Flag zuruecksetzen
    			eor temp, temp				;temp=0
    			out TCCR0, temp
    			out TCNT0, temp	    		;=0
    			pop temp
    			sei
    			ret
    wait500ms:	cli
    			push tmp1
    			ldi tmp1, 100
    wait500msa:	call wait5ms
    			dec tmp1
    			brne wait500msa
    			pop tmp1
    			sei
    			ret							;100 mal 5ms
    
    ;___________einen "Enable"-Impuls starten (Display uebernimmt Daten)_____________________
    enable:		sbi PortC, E				;Enable-Pin -> H
    			call wait5ms				;5000ns spaeter
    			cbi PortC, E				;Enable-Pin -> L
    			ret
    ;___________Einen String ans Display senden_____________________________________________
    SendTxt:	push temp
    			push cnt
    			cli
    			clr cnt
    			lsl ZL
    			rol ZH						;Z-Pointer mal 2
    SendTxta:	lpm							;Byte von Adresse (Z) im Flash laden
    			mov temp, data				;in data (r0) landete das byte			
    			cpi temp, 0
    			breq SendTxtb
    			call SendDat	 			;an LCD senden
    			adiw ZH:ZL, 1				;Z-Pointer incrementieren
    			inc cnt		
    			jmp SendTxta
    SendTxtb:	ldi temp, 0x20
    			call SendDat
    			inc cnt
    			cpi cnt, 16
    			brlo SendTxtb
    			ldi temp, 0b10000000
    			call SendCom
    			sei
    			pop cnt
    			pop temp
    			ret
    ;___________Prozedur zum Senden von Befehlen ans Display (4bit-Modus)___________________
    SendCom:	cli
    			push tmp1
    			push temp
    			mov tmp1, temp
    			swap temp					;hoeherwertiges Nibble->niederwertiges
    			andi temp, 0x0F     		;hoeherwertiges->loeschen (auf 0 setzen)
    			out PortC, temp
    			call enable					;Uebernehemen
    			andi tmp1, 0x0F
    			out PortC, tmp1
    			call enable
    			call wait5ms
    			pop temp
    			pop tmp1
    			sei
    			ret
    ;___________Prozedur zum senden von Zeichen an das Display (4bit-Modus)_________________
    SendDat:	cli
    			push tmp1
    			push temp
    			mov tmp1, temp
    			swap temp					;hoeherwertiges Nibble->niederwertiges
    			andi temp, 0x0F     		;hoeherwertiges->loeschen (auf 0 setzen)
    			out PortC, temp
    			sbi PortC, RS
    			call enable					;Uebernehemen
    			andi tmp1, 0x0F
    			out PortC, tmp1
    			sbi PortC, RS
    			call enable
    			call wait5ms
    			pop temp
    			pop tmp1
    			sei
    			ret		 
    ;---Prozedur zum Umrechnen des 10bit A/D-ergebnisses in eine Temperatur---
    umrech:     push lowb
    			push highb					;fuer spaeter
    			ldi temp, 88				;mit 88 multiplizieren
    			ldi tmp1, 0
    			mul lowb, temp				;multiplizieren
    			mov tim1, r0
    			mov tim2, r1
    			mul highb, temp
    			add r0, tim2				;hoeheres mit niedrigem addieren
    			adc r1, tmp1				;falls Ueberlauf
    			mov lowb, r0
    			mov highb, r1
    			subi lowb, 0x18
    			mov bin, lowb
    			pop highb
    			pop lowb					;wiederherstellen
    			;cpi highb, 0x03
    			;brne umrech_e				;wenn nicht gleich -> umrech_e
    			cpi lowb, 0x2F
    			brlo umrech_k				;wenn kleiner 0°C springen
    			mov temp, flag
    			cbr temp, 0b1
    			mov flag, temp				;"Minusflag" loeschen
    			jmp umrech_e				;sonst beenden
    umrech_k:   ldi tmp1, 0xFF
    			sub tmp1, bin
    			inc tmp1					;minusgrade ausrechnen
    			mov bin, tmp1
    			mov temp, flag
    			sbr temp, 0b1
    			mov flag, temp				;"Minusflag" setzen 
    umrech_e:	ldi tmp1, '0'			;Ascii von 0
    			ldi cnt, 0				;counter = 0
    			ldi tim1, 3				;HilfCouNTer = 3
    			ldi XL, 0x60
    			ldi XH, 0				;Adresse von 1. Speicherstelle im SRAM setzen
    umrech_c:	cpi bin, 10				;Rest mit 10 vergleichen
    			brlo umrech_a			;wenn kleiner Schleife verlassen
    			subi bin, 10			;10 abziehen
    			inc cnt					;incrementieren		
    			jmp umrech_c
    umrech_a:	add bin, tmp1			;-> Ascii-Code
    			st  X+, bin				;Bin (Ascii-Code) in SRAM ($60) speichern und X-Pointer incrementieren
    			mov bin, cnt			;Ergebnis der Division nach, bin
    			clr cnt
    			dec tim1
    			breq umrech_b			;wenn 3mal durchgelaufen, dann beenden
    			jmp umrech_c
    umrech_b:	;sbiw XL, 1				;3. Ascii-Code laden (entspricht "Hunderter") 
    			ld temp,-X
    			ldi temp, '+'			;positive Temperatur anzeigen
    			sbrc flag, 0
    			ldi temp, '-'			;negative Temperatur anzeigen
    			call SendDat
    			ld temp,-X				;2. Ascii-Code laden (entspricht "Zehner") 
    			call SendDat
    			ld temp,-X				;1. Ascii-Code laden (entspricht "Einer") 
    			call SendDat
    			ret
    
    chngchnl:   cli ADCSR, 5			;anhalten
    			in tmp1, ADMUX
    			andi tmp1, 0b11100000   ;unterste 5 bit loeschen
    			or tmp1, temp			;entsprechende bits setzen	
    			out ADMUX, tmp1
    			sbi ADCSR, 5
    			sbi ADCSR, 6			;wieder starten 
    			ret
    
    ;---Strings zum Ausgeben auf dem Display (0-terminiert)---
    text1:  .db "aktuelle Messung",0
    kanal0:	.db "0:",0
    kanal1: .db "1:", 0
    GradC:  .db 0b11011111,"C",0
    Ich vermute der Fehler liegt in dem Unterprogramm "umrech", welches den Wert vom ADC in eine Temperatur umrechnet und am Display ausgibt.

    Es waer wirklich nett, wenn ihr euch den Quelltext mal anschaut, wenn nicht kann ich das aber auch verstehen, weil der ja nicht grad kurz ist (Da ich absolut keine idee hab, wo der Fehler liegt, konnte ich nicht nur einen Ausschnitt zeigen).

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    ich hab mir zwar Dein Programm angeguckt, konnte aber auch keinen großen Fehler
    finden, nur ein paar Anregungen.

    Du benutzt keine Interrupts, wozu dann cli und sei ?
    Bei den enable Puls brauchst Du keine 5 ms warten, ein paar nops reichen vollkommen.
    So wie Du den XZeiger belegst ist es schon was komisch, so geht es sicherlich auch,
    aber eleganter wäre z.B.

    .equ puffer = 0x060

    und dann mit
    ldi XH,HIGH(puffer)
    ldi XL,LOW(puffer)

    Aber das ist eher kosmetischer Natur

    A ja,
    in Deiner endlos schleife machst Du zwei pushs :

    push lowb
    push highb

    und wo werden sie wieder weggeholt?
    Leider habe ich mir das nicht genau angeguckt, vielleicht hollst Du sie irgendwo in einer
    anderen routine wieder weg, die ersten rcalls tun das aber nicht.

    Nicht daß Du dir den Stack zumüllst.......

    Gruß Sebastian

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    04.04.2005
    Ort
    Hamburg <-> Bremen
    Alter
    37
    Beiträge
    112
    Hallo,

    kenne mich mit asm jetzt nicht so aus, aber ich hab mal gehört das die Atmels beim auslösen eines interupts der nicht vergebenwurde std.mäßig wieder nach 0000 springen.
    Is aber nur so ne vermutung...

    Scheint falsch zu sein... Siehe nächsten Beitrag !!!!!

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    std.mäßig wieder nach 0000 springen
    Das würde ich nicht sagen, sie Springen ganau zu der Adresse, die den entspechendem
    Interrupt zugewiesen ist.
    Hier ein Auszug aus m16def.inc :
    ; ***** INTERRUPT VECTORS ************************************************
    .equ INT0addr = 0x0002 ; External Interrupt Request 0
    .equ INT1addr = 0x0004 ; External Interrupt Request 1
    .equ OC2addr = 0x0006 ; Timer/Counter2 Compare Match
    .equ OVF2addr = 0x0008 ; Timer/Counter2 Overflow
    .equ ICP1addr = 0x000a ; Timer/Counter1 Capture Event
    .equ OC1Aaddr = 0x000c ; Timer/Counter1 Compare Match A
    .equ OC1Baddr = 0x000e ; Timer/Counter1 Compare Match B
    .equ OVF1addr = 0x0010 ; Timer/Counter1 Overflow
    .equ OVF0addr = 0x0012 ; Timer/Counter0 Overflow
    .equ SPIaddr = 0x0014 ; Serial Transfer Complete
    .equ URXCaddr = 0x0016 ; USART, Rx Complete
    .equ UDREaddr = 0x0018 ; USART Data Register Empty
    .equ UTXCaddr = 0x001a ; USART, Tx Complete
    .equ ADCCaddr = 0x001c ; ADC Conversion Complete
    .equ ERDYaddr = 0x001e ; EEPROM Ready
    .equ ACIaddr = 0x0020 ; Analog Comparator
    .equ TWIaddr = 0x0022 ; 2-wire Serial Interface
    .equ INT2addr = 0x0024 ; External Interrupt Request 2
    .equ OC0addr = 0x0026 ; Timer/Counter0 Compare Match
    .equ SPMRaddr = 0x0028 ; Store Program Memory Ready

    .equ INT_VECTORS_SIZE = 42 ; size in words

  8. #8
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Beim vorliegenden Code steht nach "CSEG" sofort das Programm und keinen ISR-Vectoren. D.h. WENN ein Interupt tatsächlich ausgelöst würde, fängt der rechner dann irgendwo im Programm vorne an.
    Das sollte also wirklich nicht vorkommen. Laß das SEI also lieber weg, wenn du es eh nicht brauchst
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.05.2005
    Ort
    Chemnitz
    Alter
    28
    Beiträge
    104
    Ok. Die sei's cli's sind noch Ueberbleibsel vom vorhergehendem Programm. Ich bin grad dabei, meine Hardware richig zu testen und ein bisschen rumzuspielen und hab die vergessen weg zumachen, danke fuer den Hinweis.

    Mit den Push's hast du recht. . Ich hab die wirklich nicht wieder runtergeholt und der hat sich vielleicht bis zu dem Registerbereich runtergefressen und hat dort Chaos gemacht! Gerade in der Endlosschleife hab ich viel veraendert und da sin die ausversehen stehen geblieben.

    Ich werd's gleich mal aendern und euch sofort Bescheid sagen, wenn's geht.

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.05.2005
    Ort
    Chemnitz
    Alter
    28
    Beiträge
    104
    Es geht!!! Es lag an den push's. Die sei's und so haben keine Fehler verursacht. Danke an alle, die sich mit meinem Problem befasst haben. =D>

    Das mit den 5ms beim enable-impuls ist wirklich sehr ueberdimensioniert und hab das auch schon mit ein paar nop's probiert, da geht's aber nicht, warum auch immer. Dieser enable-impuls muss ja nur 450ns lang anliegen und die Daten 195ns vorher stabil sein (steht so im Datenblat vom HD44780). Hatte aber noch keine Erfahrung mit LCD's und hab das daher erstmal so gelassen.

    Vielleicht kann mir ja jemand sagen, warum das bei mir nicht geht? Koennte es sein, dass der LCD-Controller "nur" HD44780-kompatibel ist?

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •