Kan inte konstatera felet, AVR ASM [En del kod]

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Eddie
Inlägg: 47
Blev medlem: 20 oktober 2005, 16:07:53

Kan inte konstatera felet, AVR ASM [En del kod]

Inlägg av Eddie »

Har skrivit min första kod och gjort min första uppkoppling men något är galet :roll:
Jag har en Atmega8 med en LM35 in på ADC0 och 2 knappar på INT0 och INT1, två 7 segments displayer kopplade via BCD->7seg dekodrar på PORTB och slutligen en LED på PD5 och ett relä via trissa på PD4.

Vad ska den göra då?
LM35 lämnar en temperatur via ADC som omvandlas till BCD och spottas ut på PortB. En termometer alltså (Som nybörjare var det väldigt upphetsande att få den biten att fungera :D ).

Vidare så lade jag till ett register med ett inställbart värde som kunde ökas och minskas med hjälp av interrupt-knapparna. När jag ökar eller minskar värdet så spottas det värdet i BCD ut på PortB, en LED tänds och indikerar att jag är i inställningsläget och efter 5 sekunders inaktivitet på knapparna så växlar den tillbaka till att visa temperaturen igen.

Lade sedan till Comparefunktion som drar reläet på PD4 om det inställda värdet är högre än temperaturen och släpper om det är lägre.

Vid det här laget ansåg jag att jag hade en termostat (Ännu lyckligare :D )
men sedan började problemen.

Problemet är att om jag trycker på någon av knapparna snabbt upprepade gånger så visas det alla möjliga siffror på "displayen" och till slut så hittar den inte tillbaka till temperaturen och visar istället det inställda värdet hela tiden.

Ögonen blöder och jag har säkert bara orsakat skada och oreda i koden i mina försök att få rätt på problemet.

Någon som kan se något uppenbart? (ber om ursäkt för rörig kod och oortodoxa tillvägagångssätt i vissa försök till lösningar)
Alla optimeringstips och kommentarer är mycket välkomna.
Ska väl nämna att det är AvrStudio jag skriver i.

Kod: Markera allt

.include "m8def.inc"  
 
.def Siffra4 = R3 
.def Siffra5 = R4 
.def Temp = R16   
.def rBin1H = R17 
.def rBin1L = R18 
.def rBin2H = R19 
.def rBin2L = R20    
.def Program = R21 
.def IntFlag = R22
          

.org 0x0000
             
   rjmp  RESET
   
.org INT0addr
   
   rjmp Minus          
   
.org INT1addr

   rjmp Plus
   
	
RESET:   ;*****STARTSETUP*****

   SBRC IntFlag,7
   rjmp main   
   ldi Temp,LOW(RAMEND) ; Initiera Stackpointer
   out SPL,Temp 		
   ldi Temp,HIGH(RAMEND)
   out SPH,Temp
   ldi Program, 20			
   ldi Temp, $ff		
   out DDRB,Temp		
   sbi DDRD, 4
   sbi DDRD, 5
   sbi PortD, 2
   sbi PortD, 3   
   ldi TEMP,(1<<INT0)+(1<<INT1) ; int masks 0 och 1 
   out GICR,TEMP
   ldi TEMP, $0F
   out MCUCR, TEMP
   sei   	
   
            
   
Main:    ;*****HUVUDPROGRAM*****   
   cbr IntFlag,7
   sei 
   rcall ADCInit	
   ldi   Temp, $0   
   rcall ADCsel
   rcall ADCTrig
   lsr rBin1H
   ror rBin1L
   lsr rBin1H
   ror rBin1L
   cp rbin1L, Program
   brge Off
   brlo On
Cont:
   rcall Bin2ToBcd5
   rcall klar
   rjmp  Main

On: sbi PortD, 4
   rjmp Cont

Off: cbi PortD, 4
   rjmp Cont
   
ADCInit:  ;*****ADC Start*****
        	                   
   ldi Temp, $A3	          
   out ADCSRA, Temp           
   ret

ADCsel:
   out ADMUX, Temp	   
   ret
;
ADCTrig:
   SBI ADCSRA, 6                 
   rcall DEL600mus
   IN   rBin1L, ADCL              
   IN   rBin1H, ADCH              
   
ADCCLR:
   SBI ADCSR, 4                 
   IN   Temp,ADCSR            		                             
   SBIC ADCSR, 4                
   RJMP ADCCLR                   
   RET
         
     
Bin2ToBcd5: ;*****TALOMVANDLING*****
	
   push rBin1H  
   push rBin1L
   ldi Temp,HIGH(10000) 
   mov rBin2H,Temp
   ldi Temp,LOW(10000)
   mov rBin2L,Temp
   rcall Bin2ToDigit 
   ldi Temp,HIGH(1000) 
   mov rBin2H,Temp
   ldi Temp,LOW(1000)
   mov rBin2L,Temp
   rcall Bin2ToDigit 
   ldi Temp,HIGH(100) 
   mov rBin2H,Temp
   ldi Temp,LOW(100)
   mov rBin2L,Temp
   rcall Bin2ToDigit 
   ldi Temp,HIGH(10) 
   mov rBin2H,Temp
   ldi Temp,LOW(10)
   mov rBin2L,Temp
   rcall Bin2ToDigit 
   st z,rBin1L 
   sbiw ZL,4 
   pop rBin1L 
   pop rBin1H
   rcall klar
   ret 

Bin2ToDigit:
   clr Temp 
Bin2ToDigita:
   cp rBin1H,rBin2H 
   brcs Bin2ToDigitc 
   brne Bin2ToDigitb 
   cp rBin1L,rBin2L 
   brcs Bin2ToDigitc 
Bin2ToDigitb:
   sub rBin1L,rBin2L 
   sbc rBin1H,rBin2H 
   inc Temp 
   rjmp Bin2ToDigita 
Bin2ToDigitc:
   st z+,Temp 
   ret 

klar: ;******SKICKA UT PÅ DISPLAY******
   mov rBin1H, Siffra4
   mov rBin1L, Siffra5
   bst rBin1H,0
   bld rBin1L,4
   bst rBin1H,1
   bld rBin1L,5
   bst rBin1H,2
   bld rBin1L,6
   bst rBin1H,3
   bld rBin1L,7
   out PORTB, rBin1L
   ret

;*****DELAYRUTINER*****

DEL600mus:
   LDI XH, HIGH(798)
   LDI XL, LOW (798)
COUNT4:
   SBIW XL, 1
   BRNE COUNT4
   RET 

DEL49ms:
   LDI XH, HIGH(65535)
   LDI XL, LOW (65535)
COUNT3:
   SBIW XL, 1
   BRNE COUNT3
   RET 

Del05s:
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   rcall DEL49ms
   ret

;*****INTERUPTS*****

Plus:
   sbr IntFlag,7
   inc Program
   rjmp Visaprog
		

Minus:
   sbr IntFlag,7
   dec Program
   rjmp Visaprog
		

Visaprog:
   clr rBin1L
   clr rBin1H
   clr rBin2L
   clr rBin2H
   mov rBin1L, Program
   rcall Bin2ToBcd5
   rcall klar
   sbi PortD, 5
   rcall DEL49ms
   rcall Del05s
   cbi PortD, 5
   reti


Edit: Tog bort sei och cli
Senast redigerad av Eddie 23 februari 2006, 14:37:37, redigerad totalt 1 gång.
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Först och främst så är det ganska olämpligt att koppla knappar direkt på INT0 och INT1 då de uppkommer kontakt studs pga de mekaniska knapparna detta gör att det kommer flera pulser efter varandra vilket resultera i flera interrupt...

Nästa fel du gör är att enbla interupten inne i interrupt-rutinen vilket gör att om nog många interrupt inträffar kommer hel stacken att ätas up vilket ger enhel del olika kufiska fel...
med andra ord använd inte cli och sei i interrupt-rutinen.
Jag förstår hur du tänker typ "jag vill inte att några andra interupt ska kunna av bryta det här interrupt"
Men hårdvaran tar hand om att clera den globala interrupt flagan...
och när du färdig med interrupt-rutinen så hoppar du tillbaka med hjälp av reti som sätter den globala interrupt flagan..

Så använd inte cli och sei i interrupt dock kan det finnas tillfällen där man vill att andra interupt ska kunna av bryta det interupt som körs... men det är sällan...

Så hoppas att du förstog mina kråkfötter :)
Eddie
Inlägg: 47
Blev medlem: 20 oktober 2005, 16:07:53

Inlägg av Eddie »

Ok, tack. Det tog bort problemet iom att jag inte kan öka värdet snabbt, men det skapar ett annat problem eftersom jag måste vänta ut 5s fördröjningen innan jag kan öka värdet ytterliggare en gång.
Vill kunna öka värdet relativt snabbt men ändå ha kvar fördröjningen så att värdet visas under en liten stund. Hoppas ni förstår vad jag menar :?
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Men herregud.....du har ju delayen i din ISR....

Den ska såklart styras i din main!

Följande ska ske:
Starta en timer-interrupt, jag brukar att använda 10Hz till keyboard-grejor.
För varje Timer-interrupt ska du göra följande: (pseudo C kod)

Kod: Markera allt

if(Delay_Counter > 0) Delay_Counter = Delay_Counter - 1;
If(Plus)
  {
  Delay_Counter = 50; // 5 sek delay
  if((Previous_Plus < 1) && Plus)
    {
    Talet_Som_Ska_Ställas = Talet_Som_Ska_Ställas+1;
    }
  Previous_Plus = Plus;
  if((Previous_Minus < 1) && Minus)
    {
    Talet_Som_Ska_Ställas = Talet_Som_Ska_Ställas-1;
    }
  Previous_Minus = Minus;
  }

main:
  while(1)
    {
    if(Delay_Counter > 0)
      {
      // Visa det ställbara talet
      }
    else
      {
      // Visa det mätte värde
      }
    }

Allt detta kan sedan kompletteras med key-auto-repeat osv men detta är grunden.
Skriv svar