Hallo ich beschäftige mich seit 2 Wochen mit Pic’s. Ich habe den Pic16f876. Ich habe folgendes prob. Ich möchte in ein vorhandenes Programm einige Ausgänge integriert. Das original Programm habe ich von http://www.sprut.de/electronic/pic/projekte/thermo/thermo.htm So und ich habe es folgendermaßen abgewandelt. #define Offset D'250' ; Offset des PTC #define Toff1 D'30' #define Toff2 D'30' #define Ton1 D'38' #define Ton2 D'38' Das sind die werte bei den der Lüfter an bzw aus gehen soll. Lüfter ein/aus-schalten Luft1 ; prüfen ob Temp<Toff MOVFW Toff1 subwf f0, w ; w:=f-33 = temp-Toff btfss STATUS, C bcf PORTC, 5 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton1 subwf f0, w ; w:=f-38 = temp-Ton btfsc STATUS, C bsf PORTC, 5 ; Lüfter an return Luft2 ; prüfen ob Temp<Toff MOVFW Toff2 subwf f0, w ; w:=f-w = temp-Toff btfss STATUS, C bcf PORTC, 4 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton2 subwf f0, w ; w:=f-w = temp-Ton btfsc STATUS, C bsf PORTC, 4 ; Lüfter an return Die Unterprogramme werden im Hauptprogramm auf gerufen. Ich weiß niocht was ich falsch gemacht habe kann mir jemand helfen? Danke im voraus Bodo K.
Wenn du uns noch sagst, was genau nicht geht oder falsch gemacht wird könnten wir mitdenken. Torsten
Hi ist ja super so schnell. Also ich habe zwei Ausgänge eingefügt Port C4 und C5. Diese sollen bei 38 Crad angehen und bei 30 Crad Ausgehen. Dafür habe ich folgendes gemacht. #define Toff1 D'30' #define Toff2 D'30' #define Ton1 D'38' #define Ton2 D'38' Für meine aus- einschalt Temperaturen. ; Lüfter ein/aus- schalten Luft1 ; prüfen ob Temp<Toff MOVFW Toff1 subwf Digit, w ; w:=f-33 = temp-Toff btfss STATUS, C bcf PORTC, 5 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton1 subwf Digit, w ; w:=f-38 = temp-Ton btfsc STATUS, C bsf PORTC, 5 ; Lüfter an return Luft2 ; prüfen ob Temp<Toff MOVFW Toff2 subwf Digit, w ; w:=f-w = temp-Toff btfss STATUS, C bcf PORTC, 4 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton2 subwf Digit, w ; w:=f-w = temp-Ton btfsc STATUS, C bsf PORTC, 4 ; Lüfter an return Für die Lüfter. Ich hoffe diese angaben reichen Dir. Danke im voraus BodoK.
Ich glaube das habe ich. Init movlw B'11111111' movwf PORTB movwf PORTC ; LED aus bsf STATUS, RP0 ; Bank 1 movlw Ini_opt ; pull-up on movwf OPTION_REG movlw B'00000000' ; PortB & C alle outputs movwf TRISB movwf TRISC bcf STATUS, RP0 ; Bank 0 movlw B'11111111' movwf PORTB movwf PORTC ; LED aus
So hier ist das ganze Programm. list p=16f876 ;************************************************************** ;* Pinbelegung ;* ---------------------------------- ;* PORTA: 0 < PTC-Spannung ;* 1 - ;* 2 - ;* 3 - ;* 4 - ;* 5 - ;* 6 - ;* 7 - ;* ;* PORTB: 0 Segment A AAAAA AAAAA AAAAA ;* 1 Segment F F B F B F B ;* 2 Segment E F B F B F B ;* 3 Segment D GGGGG GGGGG GGGGG ;* 4 Segment H E C E C E C ;* 5 Segment C E C E C E C ;* 6 Segment G DDDDD HH DDDDD HH DDDDD HH ;* 7 Segment B ;* ;* PORTC: 0 LED------------------------------------------------A ;* 1 LED--------------------------------A ;* 2 LED----------------A ;* 3 - ;* 4 - ;* 5 - ;* 6 - (> TX: RS-232-Ausgang zum Treiber) ;* 7 - (< RX: RS-232-Eingang vom Treiber) ;* ;************************************************************** ; ;sprut (zero) Bredendiek 06/2003 ; ; Termometer mit 16F876 und KTY81-110 ; ; Prozessor 16F876 / 16F673 ; ; Prozessor-Takt 4 MHz ; ; PTC-Spannung: ; Temp. Spannung ADC ; -20°C 1,0106 V 206 ; 0°C 1,1593 V 237 ; +20°C 1,3125 V 268 ; +40°C 1,4678 V 300 ; +100°C 1,9290 V 395 ; ; ; ;************************************************************** ; Includedatei für den 16F876 einbinden #include <P16f876.INC> ERRORLEVEL -302 ;SUPPRESS BANK SELECTION MESSAGES ; Configuration festlegen: ; Power on Timer, kein Watchdog, HS-Oscillator, kein Brown out, kein LV-programming __CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF & _LVP_OFF ;************************************************************** ; Variablen festlegen w_copy Equ 0x20 ; nur für INT s_copy Equ 0x21 ; nur für INT p_copy EQU 0x22 ; nur für INT Flags EQU 0x23 NrMessung EQU 0x24 ; zählt die 64 Temperaturmessungen Fehler equ 0x25 ; Fehlerregister für Mathematik count equ 0x26 ; universeller zähler loops equ 0x27 ; timer für wait loops2 equ 0x28 ; timer für wait ; Dezimalstellen Digit EQU 0x29 Ziffer1 EQU 0x2A Ziffer2 EQU 0x2B Ziffer3 EQU 0x2C HdH EQU 0x2D ;3 Hunderter HdZ EQU 0x2E ;2 Zehner HdE EQU 0x2F ;1 Einer HdX EQU 0x30 ; Puffer für eine Dezimalstelle ;16 Bit Rechenregister f0 equ 0x31 ; f1 equ 0x32 ; ;16 Bit Rechenregister xw0 equ 0x33 ; xw1 equ 0x34 ; ;16 Bit Rechenregister g0 equ 0x35 ; g1 equ 0x36 ; ; Konstanten festlegen #define Leading0 Flags,7 #define Negativ Flags,6 ; 1: Temperatur ist negativ ; der Wert offset dient zur Kalibrierung des Termometers ; der Standardwert ist 150 dezimal ; zeigt das Termometer eine um x° zu hohe Temperatur an, dann ; muss offset um x erhöht werden ; ; Beispiel: ; mit einem offset von 150 zeigt das Termometer eine um 4 °C ; zu hohe Temperatur an, dann ist offset auf 154 zu ändern. #define Offset D'250' ; Offset des PTC #define Toff1 D'130' #define Toff2 D'130' #define Ton1 D'138' #define Ton2 D'138' Ini_con Equ B'00000000' ; TMR0 -> Interupt disable Ini_opt Equ B'10000011' ; Timer0 int 16:1 ;************************************************************** org 0 goto Init ;************************************************************** ; die Interuptserviceroutine org 4 intvec movwf w_copy ; w retten swapf STATUS, w ; STATUS retten clrf STATUS movwf s_copy ; movf PCLATH, W movwf p_copy clrf PCLATH ; Bank 0 ; Intrupt servic routine Int_serv bsf PORTC, 2 ; Ziffer1 aus bsf PORTC, 1 ; Ziffer2 aus bsf PORTC, 0 ; Ziffer3 aus decf Digit,f ; Ziffernzähler verringern ;Digit=2: anzeigen Ziffer 3 1er ;Digit=1: anzeigen Ziffer 2 10er ;Digit=0: anzeigen Ziffer 1 100er btfsc STATUS, Z goto Int_0 ; Z-Flag=1 ergo Digit=0 decf Digit, w btfsc STATUS, Z goto Int_1 ; Digit=1 goto Int_2 ; Digit=2 Int_0 movfw Ziffer1 ; Wert der 1. Ziffer (100er) call Segmente movwf PORTB ; Segmente einschalten bcf PORTC, 2 ; 1. Ziffer einschalten movlw 3 movwf Digit goto Int_end Int_1 movfw Ziffer2 ; Wert der 2. Ziffer (10er) call Segmente movwf PORTB ; Segmente einschalten bcf PORTC, 1 ; 2. Ziffer einschalten goto Int_end Int_2 movfw Ziffer3 ; Wert der 3. Ziffer (1er) call Segmente movwf PORTB ; Segmente einschalten bcf PORTC, 0 ; 3. Ziffer einschalten goto Int_end Int_end movf p_copy, W movwf PCLATH swapf s_copy, w ; STATUS zurück movwf STATUS swapf w_copy, f ; w zurück mit flags swapf w_copy, w bcf INTCON, T0IF ; Interupt-Flag löschen retfie ;************************************************************** ; 7-Segment-Tabelle ;* PORTB: 0 Segment A AAAAA ;* 1 Segment F F B ;* 2 Segment E F B ;* 3 Segment D GGGGG ;* 4 Segment H E C ;* 5 Segment C E C ;* 6 Segment G DDDDD HH ;* 7 Segment B ; Segmente addwf PCL, f ; 76543210 ; BGCHDEFA retlw B'01010000' ; 0 retlw B'01011111' ; 1 retlw B'00110010' ; 2 retlw B'00010110' ; 3 retlw B'00011101' ; 4 retlw B'10010100' ; 5 retlw B'10010000' ; 6 retlw B'01011110' ; 7 retlw B'00010000' ; 8 retlw B'00010100' ; 9 retlw B'11111111' ; dunkel retlw B'10111111' ; - ;************************************************************** ;************************************************************** ; Das Programm beginnt mit der Initialisierung Init movlw B'11111111' movwf PORTB movwf PORTC ; LED aus bsf STATUS, RP0 ; Bank 1 movlw Ini_opt ; pull-up on movwf OPTION_REG movlw B'00000000' ; PortB & C alle outputs movwf TRISB movwf TRISC bcf STATUS, RP0 ; Bank 0 movlw B'11111111' movwf PORTB movwf PORTC ; LED aus movlw Ini_con ; Interupt disable movwf INTCON movlw 3 movwf Digit movlw D'1' movwf Ziffer1 movlw D'2' movwf Ziffer2 movlw D'3' movwf Ziffer3 ; Anzeige '321' ; ADC initialisieren ; 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,25 ... 5 MHz einstellen BCF ADCON0, 7 ; ADCS1=0 BSF ADCON0, 6 ; ADCS0=1 ; Daten rechtsbündig BSF STATUS,RP0 ; Bank1 clrf ADCON1 BSF ADCON1, 7 ; ADFM=1 BCF STATUS,RP0 ; Bank0 ; 244 Hz-Timer0-Interupt einstellen bsf STATUS, RP0 ; auf Bank 1 umschalten movlw B'10000011' ; internen Takt zählen, Vorteiler zum Timer0, 16:1 ; T0CS=0, PSA=0, PS=100, xx0x0100 movwf OPTION_REG movlw D'0' ; (1MHz : 16 ): 256= 244Hz bcf STATUS, RP0 ; auf Bank 0 zurückschalten movwf TMR0 bcf INTCON, T0IF bsf INTCON, T0IE ; Timer0 interupt erlauben bsf INTCON, GIE ; Interupt erlauben ; 1. Temperaturregister (16-Bit) auf 82 setzen (32+50) ; 2. 64 mal ADC abfragen, ADC-Wert jeweils zum Temperaturregister addieren (16 Bit Addition) ; 3. Temperaturregister durch 101 dividieren (16 Bit Division) ; 4. Vom Temperaturregister 150 subtrahieren (16 Bit Subtraktion) ; 5. Temperaturregister in BCD umrechen (3-stellig), Vorzeichen beachten mainloop ; Startwert für korrektes Runden clrf f1 movlw D'82' movwf f0 ; 64 Messungen movlw D'64' movwf NrMessung Messung call UMessen1 ; AN0 nach xw1,xw0 call Add16 ; 16-bit add: f = f + xw decfsz NrMessung, f goto Messung ; Division durch 101 movlw 0x00 ; 101 = 00 65 h movwf xw1 movlw 0x65 movwf xw0 call Div16 ; Division f:= f / xw ; 150°C Offset entfernen bcf Negativ ; angenommen: positive Temperatur clrf xw1 movlw Offset movwf xw0 call Sub16 ; 16 bit f:=f-xw calc=xw cnt=f; neg=C btfss STATUS, C goto Positiv bsf Negativ movfw f0 movwf xw0 movfw f1 movwf xw1 clrf f1 clrf f0 call Sub16 ; 16 bit f:=f-xw calc=xw cnt=f; neg=C Positiv call Hex2Dez8 ; Umrechnung in BCD call wait75ms call Luft1 call Luft2 goto mainloop ;************************************************************** ; Spannung wandeln nach xw1, xw0 UMessen1 clrf count aqui ; 0,3 ms ADC Aqusitionszeit nach Eingangswahl DECFSZ count, f goto aqui BSF ADCON0, 2 ; ADC starten loop BTFSC ADCON0, 2 ; ist der ADC fertig? GOTO loop ; nein, weiter warten movfw ADRESH ; obere 2 Bit auslesen movwf xw1 ; obere 2-Bit nach xw1 bsf STATUS,RP0 ; Bank1 movfw ADRESL ; untere 8 Bit auslesen bcf STATUS,RP0 ; Bank0 movwf xw0 ; untere 8-Bit nach xw0 clrf count ; Warten, damit der ADC sich erholen kann warten DECFSZ count, f goto warten return ;************************************************************** ;Warteroutinen verschiedener Länge **************************** ; 75 ms warten wait75ms movlw D'75' ; 75ms movwf loops goto WAIT ;************************************************************** ;Zeitverzögerung um loops * 1 ms ; 4 MHz externer Takt bedeutet 1 MHz interner Takt ; also dauert 1 ms genau 1000 Befehle ; 100 Schleifen a 10 Befehle sind 1000 Befehle = 1 ms WAIT top movlw .100 ; timing adjustment variable (1ms) movwf loops2 top2 nop ; sit and wait nop nop nop nop nop nop decfsz loops2, F ; inner loops complete? goto top2 ; no, go again ; decfsz loops, F ; outer loops complete? goto top ; no, go again retlw 0 ; yes, return from subWAIT ;************************************************************** ;+++Mathematik-Routinen *************************************** ;************************************************************** ; 16 Bit Subtraktion, bei Überlauf (neg. Ergebnis) ist C gesetzt Sub16 ; 16 bit f:=f-xw calc=xw cnt=f clrf Fehler ; extraflags löschen movf xw0, w ; f0=f0-xw0 subwf f0, f btfsc STATUS,C goto Sub16A movlw 0x01 ; borgen von f1 subwf f1, f btfss STATUS,C bsf Fehler, C ; unterlauf Sub16A movf xw1,w ; f1=f1-xw1 subwf f1 , f btfss STATUS, C bsf Fehler, C ; Unterlauf bcf STATUS, C btfsc Fehler, C bsf STATUS, C return ;************************************************************** ;16 bit Adition, C-Flag bei Überlauf gesetzt Add16 ; 16-bit add: f = f + xw movf xw0,W ; low byte addwf f0,F ; low byte add movf xw1,W ; next byte btfsc STATUS,C ; skip to simple add if C was reset incfsz xw1,W ; add C if it was set addwf f1,F ; high byte add if NZ return ; finished ;************************************************************** ;primitive 16 bit Division f:= f / xw Div16 clrf g0 decf g0, f clrf g1 decf g1, f Div16Loop incf g0, f btfsc STATUS, Z incf g1, f call Sub16 ; btfss STATUS, C ;Überlauf goto Div16Loop ;Stelle 1 mehr movfw g0 movwf f0 movfw g1 movwf f1 return ;************************************************************** ; 8 Bit Wert w auf LED 3-stellig dezimal anzeigen ; 100 = 0064 h ; 10 = 000A h ; 1 = 0001 h Hex2Dez8 ; 8-bit (f1, f0) in 3-stellen BCD bsf Leading0 movlw 0x00 ; 100 = 00 64 h movwf xw1 movlw 0x64 movwf xw0 call Hex2Dez1 ; 100er movfw HdX btfsc Negativ movlw D'11' ;'-' movwf HdH movwf Ziffer1 movlw 0x00 ; 10 = 00 0A h movwf xw1 movlw 0x0A movwf xw0 call Hex2Dez1 ; 10er movfw HdX movwf HdZ movwf Ziffer2 movfw f0 movwf HdE movwf Ziffer3 return Hex2Dez1 clrf HdX decf HdX, f HdLoop incf HdX, f call Sub16 ; btfss STATUS, C ;Überlauf goto HdLoop ;Stelle 1 mehr call Add16 ; falls führende 0 dann Wert=D'10' movfw HdX btfss STATUS, Z bcf Leading0 btfss Leading0 return movlw D'10' movwf HdX return ;************************************************************** ; Lüfter ein/aus-schalten Luft1 ; prüfen ob Temp<Toff MOVFW Toff1 subwf Digit, w ; w:=f-33 = temp-Toff btfss STATUS, C bcf PORTC, 5 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton1 subwf Digit, w ; w:=f-38 = temp-Ton btfsc STATUS, C bsf PORTC, 5 ; Lüfter an return Luft2 ; prüfen ob Temp<Toff MOVFW Toff2 subwf Digit, w ; w:=f-w = temp-Toff btfss STATUS, C bcf PORTC, 4 ; Lüfter aus ; prüfen ob Temp>Ton MOVFW Ton2 subwf Digit, w ; w:=f-w = temp-Ton btfsc STATUS, C bsf PORTC, 4 ; Lüfter an return end
Forumsregel: - Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang Hast Du den Code mal im Simulator single-gesteppt?
Ich weiß nicht was Du für einen Simulator meinst. Wo gibt es so was?
Bodo wrote:
> Ich weiß nicht was Du für einen Simulator meinst. Wo gibt es so was?
Unter den Annahme, dass Du Microchips MPLAB verwendest:
Debugger -> Select Tool -> MPLAB SIM
Ja ich habe MPLAB aber mit meine englisch ist es nicht so gut bestellt. Komme damit nicht zurecht. Kennst du vieleicht eine Sim aud deutsch oder gibt es eine Anleitung in deutsch für MPLAB? Danke
Schau mal auf der Seite http://www.fernando-heitor.de unter Downloads-Dokumente nach. Da gibt es ein Tutorial zu MPLAB auf deutsch, vielleicht hilft es dir ;)
Hallo Ich finde meinen Denkfehler nicht vielleicht hat ja einer von euch Profis mir helfen. Zumindest einen Tipp ich möchte es ja auch lernen, damit ich nicht immer fragen muss. Geht mir ja auch auf die nerven. Ich bin über jede Anregung dankbar. MFG Bodo K.
Bodo wrote: > Ich finde meinen Denkfehler nicht vielleicht hat ja einer von euch > Profis mir helfen. Ob jemand Profi ist, hat damit nichts zu tun. Du bräuchtest jemanden, der PIC-Asssembler kann und da siehts hier im Forum ziemlich mau aus. Hier sind hauptsächlich AVR-ler unterwegs. Und Postingregel 2 beachten: "Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang" Peter
Bodo wrote: > Hallo > > Ich finde meinen Denkfehler nicht vielleicht hat ja einer von euch > Profis mir helfen. Zumindest einen Tipp ich möchte es ja auch lernen, > damit ich nicht immer fragen muss. Geht mir ja auch auf die nerven. Wie weit bist Du mit dem Simulator? Und schau mal nach was MOVFW und MOVLW bewirken resp. was der Unterschied ist.
Der Denkfehler ist ganz einfach, du verwendest die Variable Digit, welche das aktuelle Display fuer das Multiplexing der 7-seg Anzeigen enthaelt (Werte 0-2) und nicht die Temperatur. !!! Chris
Hi das ist mir auch schon aufgefallen. Das da mein Fehler ist habe das in f0 geändert.(Ich glaube das das die aktuelle errechnete Temp ist) bin mir aber nicht sicher das der wert beim Sprung noch da ist.
Ja, der Wert ist in f0 sowie f1, ein 16bit Wert. du solltest Sub16 benutzen, und vorher den Schwellwert in xw0 sowie xw1 laden. Wenn das Carry gesetzt ist, ist der Wert unterschritten, andersweitig ist die Temperatur hoeher oder gleich. ************************************************************** ; 16 Bit Subtraktion, bei Überlauf (neg. Ergebnis) ist C gesetzt Sub16 ; 16 bit f:=f-xw calc=xw cnt=f clrf Fehler ; extraflags löschen movf xw0, w ; f0=f0-xw0 subwf f0, f btfsc STATUS,C goto Sub16A movlw 0x01 ; borgen von f1 subwf f1, f btfss STATUS,C bsf Fehler, C ; unterlauf Sub16A movf xw1,w ; f1=f1-xw1 subwf f1 , f btfss STATUS, C bsf Fehler, C ; Unterlauf bcf STATUS, C btfsc Fehler, C bsf STATUS, C return
Hallo Zur Verständnis. Wenn der Wert des einschalt punkt überschritten ist wird ein Flag gesetzt auf 1. Aber wie frage ich den Flags ab? Ich glaube das das die Zeile ist mit btfss STATUS, C. Aber muss ich nicht noch irgendwo definieren welcher Flags für was ist? Wie binde ich das in mein Programm ein? Das mit dem Sub 16 und Sub 16A habe ich ja in meinem Programm schon drin. Ich sagte ja schon, bin ein Newbie sorry. Danke für eure mühe
Bodo wrote: > Hallo > > > > Zur Verständnis. > > Wenn der Wert des einschalt punkt überschritten ist wird ein Flag > gesetzt auf 1. > > Aber wie frage ich den Flags ab? Ich glaube das das die Zeile ist mit > btfss STATUS, C. Richtig. Die Flags stehen im Statusregister und werden mit btfss ( Bit testen im Speicher (f) und skip wenn Bit gesetzt) oder btfsc (Das selbe, halt nur wenn bit nicht gesetzt) abgefragt. > > Aber muss ich nicht noch irgendwo definieren welcher Flags für was ist? > Nein, steht im Datenblatt. > Wie binde ich das in mein Programm ein? Die Status Flag werden bei jedem Befehl, den die CPU ausführt durch die CPU gesetzt. Welche Flags wie und bei welchem Befehl gesetzt werden erfährst du auch im Datenblatt (bei der Befehlsübersicht). Im wesentlichen brauchst du aber nur zwei Flags. C (wenn ein Byte überläuft, nach einer Addition, Subtraktion oder Verschiebebefehle) und Z (wenn das Ergebnis 0 ist). > > Das mit dem Sub 16 und Sub 16A habe ich ja in meinem Programm schon > drin. > > Ich sagte ja schon, bin ein Newbie sorry. Dann ließ mal sprut.de durch. Da erfährst du ganz gut die Grundlagen. > > Danke für eure mühe Gerne. Sven
Hallo Also ich bekomme es einfach nicht hin. Ich habe mir alles mögliche durchgelesen, finde meinen Fehler nicht. Wer kann mir BITTE ganz konkret meinen Denkfehler sagen? Mfg Bodo und DANKE im voraus.
Hallo Also ich bin der meinung das der Flags Carry immer 1 ist. Da mein Ausgang immer High ist, egal was ich für eine Temp habe. Also ist f0 nicht da. zB 0 für aktuelle Temp. - 38Grad für Toff1 = -38 Flegs 1 also Ausgang immer da. Selbst wenn ich 110 Grad am Fühler habe ändert sich nichts am Ausgang immer High. HILFE Danke Gruß Bodo
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.