Archiv verlassen und diese Seite im Standarddesign anzeigen : "if"-Operation wie umschreiben?
Bei Assembler gibt es ja leider keinen "if"-Befehl, aber es gibt doch sicher einen geschickten Weg dies zum gehen.
Ich möchte folgende Schaltung bauen: Ein Pic16f88 mit einer Photodiode und 6 LEDs drann. Je nachdem welche Spannung an der Photodiode ausgelesen wird, sollen die LEDs leuten. Also bei wenig Spannung nur 1 LED, bei mehr Spannung 2 LEDs ... und beim maximalen Spannungswert halt alle.
Mit dem AD-Wandler kann ich ja die Spannung in das ADRESH und ADRESL Register schreiben, also habe ich den Wert schonmal als eine digitale Zahl vorliegen. Da mich die beiden ersten Stellen nicht interessieren ( Photospannung geht maximal so auf 0,6V rauf und 5V ist die Referenzspannung), lese ich also nur das ADRESL-Register aus und möchte, sobald dieser Wert größer als ein bestimmter Wert ist, eine LED einschalten. Wenn ein zweiter Referenzwert erreicht wird, dann halt eine weitere LED und so weiter.
Wie führe ich am geschicktesten so eine Vergleichsoperation aus?
beim kleinsten referenzwert anfangen und vom wert abziehen. dann prüfen ob der wert die null unterschritten hat (gibts gleubich nen bit für) und wenn nich den betrag bis zum nächsten referenzwert abziehen.
beispiel: wert ist 7, schritte sind 1,2,5,6,8,10
7-1 = 6 = positiv, also led 1 an
6-1 = 5 = positiv, also led2 an
5-3 = 2 = positiv, also led3 an
2-1 = 1 = positiv, also led 4 an
1-2 = -1 = negativ, also led 5 nich an und nich mehr weiter prüfen
Danke für den Algorythmus. :)
Werde ihn gleich mal testen, sobald ich dieses Bit gefunden habe. Meine auch schonmal davon gehört zu haben, weiß aber leider nicht mehr wo. Vielleicht kann ja jemand noch das Bit benennen, das umschaltet, sobald der Wert kleiner 0 ist? 8-[
edit: Es ist das Bit 0 des Status Registers.
Ich habe jetzt mal ein Programm erstellt, dass den Algorythmus verwendet, allerdings scheint er noch nicht richtig zu funktionieren, bzw. ich habe etwas falsch verstanden.
Ich habe die Photodiode jetzt an RA0/AN0 hängen. LEDs sitzen in chronlogischer Reihenfolge an RA2, RA3, RB1, RB2, RB4 und RB 5.
Ich habe jetzt das Problem, dass LED1 konstant leuchtet, egal wie groß die Photospannung ist. Ich denke, dass ich irgendwie die Schleife falsch programmiert habe. Kann mal jemand bitte über den Code drüber schauen:
#include P16f88.INC
;*****Set up the Constants****
STATUS equ 03h ;Address of the STATUS register
TRISA equ 85h ;Address of the tristate register for port A
PORTA equ 05h ;Address of Port A
TRISB equ 86h
PORTB equ 06h
OSCCON equ 8Fh
COUNT1 equ 20h ;First counter for our delay loops
COUNT2 equ 21h ;Second counter for our delay loops
SPEICHER equ 22h
;****Set up the port****
call Delay
bsf STATUS,RP0 ;Switch to Bank 1
movlw 11h ;Set the Port A pins
movwf TRISA
movlw 01h ;Set the Port B pins
movwf TRISB
movlw 2Eh ;Taktfrequenz setzen
movwf OSCCON
bcf STATUS,RP0 ;Switch back to Bank 0
movlw 00h ;
movwf PORTA
movlw 00h
movwf PORTB
; ADC einschalten
BSF ADCON0, 0 ; ADON=1
; ADC-Eingang AN0 auswählen
BCF ADCON0, 5 ; ADCHS2=0
BCF ADCON0, 4 ; ADCHS1=0
BCF ADCON0, 3 ; ADCHS0=0
; ADC speed für 1 MHz einstellen
BSF ADCON0, 7 ; ADCS1=1
BCF ADCON0, 6 ; ADCS0=0
; Daten rechtsbündig
BSF STATUS,RP0 ; Bank1
BSF ADCON1, 7 ; ADFM=1
BCF STATUS,RP0 ; Bank0
;_________________________________________________ __________________________
;****Turn the 1st LED on****
Start
call Delay
clrwdt
clrf PORTA
clrf PORTB
bcf STATUS,0 ; Status,0 auf null setzten
;Eingangsspannung wandeln
BSF ADCON0, 2 ; ADC starten
loop
BTFSC ADCON0, 2 ; ist der ADC fertig?
GOTO loop ; nein, weiter warten
; Wert nach W schreiben
BSF STATUS,RP0 ; Bank1
movfw ADRESL ; untere 8 Bit auslesen
BCF STATUS,RP0 ; Bank0
; Erste Überprüfung
SUBWF 15h,0 ;von w 15 abziehen und wieder in w schreiben
movwf SPEICHER ;wieder in den Speicher schreiben
movlw 04h ; LED 1 an
movwf PORTA
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Zweite Überprüfung
movlw SPEICHER
SUBWF 17h,0 ;von w 17 abziehen und wieder in w schreiben
movwf SPEICHER
movlw 08h ; LED 2 an
movwf PORTA
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Dritte Überprüfung
movlw SPEICHER
SUBWF 16h,0 ;von w 16 abziehen und wieder in w schreiben
movwf SPEICHER
movlw 02h ; LED 3 an
movwf PORTB
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Vierte Überprüfung
movlw SPEICHER
SUBWF 16h,0 ;von w 16 abziehen und wieder in w schreiben
movwf SPEICHER
movlw 04h ; LED 4 an
movwf PORTB
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Fünfte Überprüfung
movlw SPEICHER
SUBWF 15h,0 ;von w 15 abziehen und wieder in w schreiben
movwf SPEICHER
movlw 10h ; LED5 an
movwf PORTB
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Sechste Überprüfung
movlw SPEICHER
SUBWF 16h,0 ;von w 16 abziehen und wieder in w schreiben
movwf SPEICHER
movlw 20h ; LED 5 an
movwf PORTB
BTFSs STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
goto Start ;go back to Start and turn LEDs on again
;****Here is our Subroutine
Delay
movlw 230
movwf COUNT1 ;Load count1 with init value
movlw 10
movwf COUNT2 ;Load count2 with init value
Loop1 decfsz COUNT1,f ;This second loop keeps the LEDs
goto Loop1 ;turned off long enough for us to
decfsz COUNT2,f ;see it turned off
goto Loop1 ;
return
;****End of the program****
end ;Needed by some compilers, and also
;just in case we miss the goto instruction.
end ;Needed by some compilers, and also
;just in case we miss the goto instruction.
Ich habe jetzt einmal den Teil mit der If-Schleife etwas umgeschrieben und die Befehle für den AD-Wandler erst mal ausgeschlossen, um hier eine Fehlerquelle auszuschließen. Stattdessen setze ich einen manuellen Wert, der überprüft werden soll. Jetzt leuchet immer die 2. LED, obwohl eigentlich noch die 4. leuchten sollte.
Ich muss irgendwo einen Denkfehler haben, den ich einfach nicht finde. Kann mir jemand weiterhelfen?
Start
call Delay
clrwdt
clrf PORTA
clrf PORTB
bsf STATUS,0 ; Status,0 auf eins setzten
movlw 50h ; einen Testwert setzten, so dass die 4. und 2. LED leuchten sollte
movwf SPEICHER
; Erste Überprüfung
movlw SPEICHER
SUBLW 15h ;von 15 w abziehen und wieder in w schreiben, wenn Speicher kleiner als 15 ist, wird das C-Flag gelöscht
movlw 04h ; LED 1 an
movwf PORTA
BTFSC STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Zweite Überprüfung
movlw SPEICHER
SUBLW 2Bh ;von w 17 abziehen und wieder in w schreiben
movlw 08h ; LED 2 an
movwf PORTA
BTFSC STATUS,0 ;wenn STATUS,0=0 , dann übersprigen
goto Start
; Dritte Überprüfung
movlw SPEICHER
SUBLW 41h ;von w 16 abziehen und wieder in w schreiben
movlw 02h ; LED 3 an
movwf PORTB
BTFSC STATUS,0 ;wenn STATUS,0=0 , dann übersprigen
goto Start
; Vierte Überprüfung
movlw SPEICHER
SUBLW 57h ;von w 16 abziehen und wieder in w schreiben
movlw 04h ; LED 4 an
movwf PORTB
BTFSC STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Fünfte Überprüfung
movlw SPEICHER
SUBLW 6Ch ;von w 15 abziehen und wieder in w schreiben
movlw 10h ; LED5 an
movwf PORTB
BTFSC STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
; Sechste Überprüfung
movlw SPEICHER
SUBLW 82h ;von w 16 abziehen und wieder in w schreiben
movlw 20h ; LED 5 an
movwf PORTB
BTFSC STATUS,0 ;wenn STATUS,0=1 , dann übersprigen
goto Start
goto Start
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.