Hallo, Für meine Abschlussarbeit ist es erforderlich einen PIC12F675 in C zu Programmieren. MPLAB und der Hitech C Compiler arbeiten einwandfrei. Als Board habe ich das Vellemann V111 K8048 (oder so ähnlich geholt)... Nun habe ich folgende Situation: Zum testen habe ich einen PIC16F84A Programmiert. Das Programm und das Brennen, sowie die Abarbeitung des Programms haben einwandfrei funktioniert. (Dieser PIC wird über einen externen Quarz getaktet). Nun wollte ich ein kleines Testprogramm in C für den PIC12F675 schreiben. Das Problem ist dass ich keine Erfahrungen mit PIC Mikrokontrollern habe und nicht weiß wie ich bei diesem PIC die Register setzen muss um die Pins als Ein-Oder ausgänge zu verwenden. Außerdem wird dieser PIC nicht über einen externen Quarz getaktet, sondern muss den internen verwenden (das sollte ja möglich sein). Ich hoffe dass es in diesem Forum einige Experten gibt, die mir einen kleinen C-Code zukommen lassen könnten. ich benötige lediglich einen eingang und einen Ausgang (Erstmal egal welche Pins, das zu ändern krieg ich auch noch hin). Wäre toll wenn mir jemand helfen könnte, vielleicht auch über MSN oder ICQ oder sonnstwas. Stefan
Stefan Haussmann schrieb: > Das Problem ist dass ich keine Erfahrungen mit PIC Mikrokontrollern habe > und nicht weiß wie ich bei diesem PIC die Register setzen muss um die > Pins als Ein-Oder ausgänge zu verwenden. Es reicht völlig die "Erfahrung", daß man sich das Datenblatt vom Hersteller runter laden kann. Und dann einfach anschauen, wo die IO-Pins beschrieben sind und deren Konfigurationsregister. Peter
Kleiner Stolperstein, während bei den größeren PICs wie 16F84 die Ports als PORTA, PORTB usw. bezeichnet ist, lautet die Bezeichnung beim 12F675 "GPIO" (general purpose I/O). Also statt PORTA fuer den Port TRISA fuer die Datenrichtung (Eingang/Ausgang) verwendet man GPIO und TRISIO. Ansonsten hilft wie von Peter gesagt ein Blick ins Datenblatt - Ansprechen der Ports ist bei beiden PICs ansonsten identisch, bloss die RAM-Adressen sind anders. Die Oszillatorauswahl ist auch ausführlich beschrieben, das wichtig Register ist hier OSCCON. Wolfgang
Gast
#2434029
Kann ich einzelne ports so ansprechen?: GPIO3=1; oder muss ich das hier anders machen (beim 16F84 sind die Bezeichnungan ja RA, beziehungsweise RB...)
Gast
#2434084
MPLAB versteht beim 12F675 sowohl GP4 als auch GPIO4 für das Bit4 des Ports (wobei der 12F675 natürlich nur die Bits 0 bis 5 hat). Für das Datenrichtungsregister gibt es TRISIO4 für das Bit4 (auch nur 0 bis 5).
Gast
#2435623
Hat von euch jemand das Velleman PIC Board?
Gast
#2435635
Stefan Haussmann schrieb: > und nicht weiß wie ich bei diesem PIC die Register setzen muss um die > Pins als Ein-Oder ausgänge zu verwenden. Tipp: vergiß nicht die Pins von Analog-Eingang auf Digital umzukonfigurieren. Ansonsten: Die Initialisierung steht prinzipiell im Datenblatt. Gruß Anja
Gast
#2435639
Hey Anja... hast du vielleicht ein kleines Programm für diesen PIC? Ich glaub dieser Tip war bisher der wichtigste :-)
Gast
#2435640
Ja habe ich.
Gast
#2435641
Cool...mcht es dir was aus den Code hier zu veröffentlichen?
Gast
#2435651
ANSEL = 0 CMCON = 7 GPIO = 0 TRISIO.0 = 0 Ausgang 0 TRISIO.1 = 0 Ausgang 1 TRISIO.2 = 1 Eingang 2 GP0_bit = 0 Ausgang 0 auf 0 GP1_bit = 0 Ausgang 1 auf 0 Wenn dein Compiler das versteht.
Gast
#2435659
Dein Programm ist ein sehr guter Anhaltspunkt... Ich versuch morgen mal den Code in meinen Compiler zu übertragen...welchen Compiler verwendest du?
Gast
#2435667
Von Mikroelektronika
Standard-Lektüre für PIC-Einsteiger: http://www.sprut.de/electronic/pic/index.htm http://www.holger-klabunde.de/pichelp.htm Grüße.
Wenn du den HI-Tech verwendest, kannst du mal in den "include"-Ordner im Compilerverzeichnis schauen und nach der Datei "pic16f675.h" oder ähnlich suchen; dort stehen alle definierten Symbole drin, die der Compiler kennt. Jetzt musst du das nur noch mit dem Datenblatt abgleichen, ist nicht so wild. Für eine Abschlussarbeit sollte das drin sein ;-) Wenn du dann detailliertere Fragen hast, kannst du dich hier ja noch einmal melden. Gruß Jens
Vielen Dank...werde ich auf jeden fall tun...
Also... Vorweg erstmal besten Dank an euch... Ich bin jetzt auf den micro C PRO Compiler vom Mikroelectronica umgestiegen bei welchem die Konfiguration sofort Funktioniert hat. Ein/Ausgänge ansprechen war überhaupt kein Problem mehr. Jetzt kommt allerdings der Hauptteil. Ich möchte (muss!!!) eine Pulsweitenmodulation Programmieren (für einen Modellbauservo) Das heißt, dass alle 20ms ein Signal zwischen 900us und 2ms an einem Ausgang (Welcher ist egal) anliegen sollte. Gibt es irgendwelche Ideen oder Tips, wie man das mit dem oben genannten PIC (12F675) oder einem anderen PIC der 12F Reihe diese Aufgabe Lösen kann. Hier dachte ich an den PIC12F683, welcher laut Datenblatt einen integrierten PWM Generator hat. Das Programm sollte also so sein, dass über eine Variable alle 20ms eine neue Pulslänge eingestellt werden kann (zum Beispiel soll nach 5 Minuten das Signal die Pulsweite von 900us bis 1,5ms durchlaufen) Der PIC ist in meiner Abschlussarbeit leider nur eine Nebensache mit der ich fast schon auf Kriegsfuß stehe, aber man beißt sich irgendwie durch. Wär cool, wenn wieder mal ein paar Experten ihr Know How zur verfügung stellen würden...
Ja, MikroC gefaellt mir auch, weil da aben vieles gleich mal funktioniert. Das PWM-Modul kann leider so lange Perioden nicht erzeugen, ausser du laesst den PIC auf einer sehr geringen Taktfrequenz laufen (dann wird aber die Abarbeitungsgeschwindigkeit fuer alles andere sehr langsam). Eine Periode von 20ms ist aber fuer den PIC ohnehin sehr lange, da kann man das - wenn sonst nichts zu tun ist - einfach als Schleife implementieren. Die Funktionen Delay_ms und Delay_us in MikroC (oder Mikrobasic) kommen da gerade recht. Achtung, diese Funktionen akzepieren nur Konstanten, und du musst built_in.h einbinden. Also in etwa so while (1) { hier Variable hochzaehlen, Zeit in 100usEinheiten for (high_time = 90; high_time <= 150; high_time++) { low_time = period - high_time; N-mal wiederholen (N so waehlen, dass die Aenderung der Pulsbreite mir der gewuenschten Geschwindigkeit verlaeuft, z.B. N=50 umd die Breite alles 1sec um 100us zu erhoehen): for (j = N; j; j--) { pin auf low setzen for (i=low_time; i; i--) { Delay_us(100); } pin auf high setzen for (i=high_time; i; i--) { Delay_us(100); } } } } // Pulsbreite wieder auf Minimum und wieder vom Anfang an Wenn mann es genauer machen will, muss man noch die Ausfuehrungszeit der Befehle abziehen, das ist aber eine eher kleine Korrektur hier (deshalb habe ich auch 100us als Basiseinheit gewaehlt - mit 1us waere das nicht der Fall!). Wolfgang
Klasse Sache... Ich werde morgen das mal ausprobieren...mal schauen ob ich das hinbekomme. Danke Wolfgang dass du deine Zeit für mich aufbringst...
Ich habe das im Anhang hinterlegte Programm ja schon durch eure Hilfe hinbekommen. Allerdings scheitere ich bei der Implementierung folgender Zusatzfunktionen: -Wenn an GP0 kein Signal mehr anliegt, soll sich die Pulsweite nichtmehr verändern. -Wenn der obere Block (PWM UP) einmal durchlaufen ist, soll die Pulsweite gehalten werden (Servo bewegt sich nicht)und es soll ein Signal an GP4 ausgegeben werden. Mit einem Signal an GP5 soll dann der untere Block (PWM DOWN) gestartet werden, welcher den Servo auf die ursprüngliche Position zurücksetzt und das Signal an GP5 soll auf 0 gehen. Ich hoffe ihr versteht was ich meine :-) Danke im voraus Stefan
Wolfgang M. schrieb: > Das PWM-Modul kann leider so lange Perioden nicht erzeugen, ausser du > laesst den PIC auf einer sehr geringen Taktfrequenz laufen (dann wird > aber die Abarbeitungsgeschwindigkeit fuer alles andere sehr langsam). Bei dem PIC12F1822 oder 12F1840 kann man einen Prescaler von 64 einstellen, bei dem 683 nur von 16. D.h. bei internen 2Mhz sind das Als Periodendauer: (PR2 + 1) 4 Tosc * TMR2Prescaler -> (155 + 1) 4 1/2MHz * 64 = 19,968ms. Bei dem 10bit PWMModul ist das eine Auflösung von 19,5µs, was ja ausreichen sollte. Damit wäre 46 (0x00 0010 1110) 0,897ms und 77 (0x00 0100 1101) 1,5015ms. Nur musst du entscheiden, ob eine Frequenz von 2Mhz (also intern 500kHz) ausreichend ist und ob du den PIC nehmen kannst/willst. Was sind denn deine Vorgaben bzw was musst du benutzen und was darfst du nicht benutzen? Im ersten Beitrag meintest du ja, dass "es erforderlich einen PIC12F675 in C zu Programmieren". Später bist du zum 683 gewechselt, also warum nicht auch zum 1822 oder 1840 (oder was ganz anderes?)
Gast
#2540003
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
Michael Skropski schrieb: > Bei dem PIC12F1822 oder 12F1840 kann man einen Prescaler von 64 > einstellen, bei dem 683 nur von 16. D.h. bei internen 2Mhz sind das Als > Periodendauer: (PR2 + 1) 4 Tosc * TMR2Prescaler -> (155 + 1) 4 > 1/2MHz * 64 = 19,968ms. Bei dem 10bit PWMModul ist das eine Auflösung > von 19,5µs, was ja ausreichen sollte. Damit wäre 46 (0x00 0010 1110) > 0,897ms und 77 (0x00 0100 1101) 1,5015ms. Ich hab nochmal nachgeguckt. Die Maximale Frequenz, die du nehmen kannst, gibt es sogar als Quarz bei Reichelt -> 3,2768 MHz (819,2kHz intern). Dann hast du (255 + 1) mal 4 mal 1/3,2768MHz mal 64 = 20ms. Auflösung bleibt so ziemlich gleich, da die Zeit ja kaum unterschiedlich ist. Aber wie gesagt, schreib mal deinen Auftrag bzw was musst du benutzen und was darfst du nicht und was muss es am Ende können.
Tut mir leid für meinen Ausdruck...ich werde heute Mittag eine Datailierte Beschriebung liefern....danke für eure Hilfe
Also...hier die vollständige Eklärung: Das Aktuelle Programm lässt einen servo im Prinzip hin und her fahren. Der Obere Teil des Programms (PWM UP) lässt den servo ansteigen, der untere Teil (PWM DOWN) lässt diesen kontrolliert zurückfahren. Das Signal des Servos wird an GP4 Ausgegeben. Nun sollen folgende Verbesserungen Stattfinden. 1. Die Pulsweite soll sich nur verändern wenn an GP5 ein High Signal anliegt (Der Servo soll seine Position halten). 2. Das zurückfahren des Servos (PWM DOWN) soll erst erfolgen, sobald an dem Eingang GP0 ein High Signal anliegt (Taster). 3.Sobald der Servo seinen Zielwert erreicht hat (im angefügten Programm 120 -->im PWM UP Teil) solll GP4 auf High schalten (LED Signalisiert, dass der Servo seinen Zielwert erreicht hat). Diese LED Soll nach dem Zurückstellen des Servos wieder Erlischen. Ich hoffe diese Beschreibung ist etwas besser...
Also hattest du das Programm schon gegeben und sollst es nur erweitern? Dann bringt dir auch kein PIC mit PWM-Modul was, auch wenn der Timer einen großen Vorteiler hat. Wenn du dein Programm, was du angehängt hast, benutzen bzw erweitern musst, ist das ja nicht weiter tragisch, ein paar ifs an der richtigen stelle. Z.b. Wenn GP5==1, high_time++, ansonsten das weglassen. Ich glaube aber nicht, dass das Programm gegeben ist (es sei denn der Aufgabensteller will nicht nur eine Erweiterung sondern auch eine Fehlersuche), denn die Deklaration von Variablen kommen ganz am Anfang der Funktionen. Also haben die in der while nichts zusuchen, sondern gehören direkt unter das "void main(){". Wenn du es denn so willst, was eine neue programmierung bedeutet, kannst du (wenn du in der PIC12F Familie bleiben sollst) den von mir erwähnten PIC12F1822 mit dem 3,2768MHz Quarz nehmen und kannst das PWM-Modul benutzen. Es ist nicht nur angenehmer zu programmieren, sondern auch übersichtlicher, eleganter und vorallem läuft das PWM-Modul automatisch im Hintergrund. Das heißt, er gibt die PWM aus und du kannst im Programm machen, was du willst. Wenn du eine Schleife mit wartefunktionen im Programm stehen hast, verfälscht du die Zeit mit jedem Befehl (sogar schon mit dem Setzen/Löschen des Ausgangs und der Schleife). Das ist bei hoher Taktfrequenz und kleiner PWM-Frequenz natürlich weniger schlimm, aber solche Module gibts ja nicht umsonst. Und ~800kHz reicht aus, um ne LED zu setzen oder nen Eingang abzufragen. Die Konfiguration vom PWM-Modul steht ja quasi schon oben, also wird es außer der einmaligen Initialisierung am Anfang vom Programm nen 10-20 Zeiler.
OK, ich bin jetzt am Rande des Wahnsinns... Ich habe hier nochmal die Aufgabe hineinkopiert: Das Programm PWM.c findet ihr weiter oben. Das Programm lässt einen servo im Prinzip hin und her fahren. Der Obere Teil des Programms (PWM UP) lässt den servo ansteigen, der untere Teil (PWM DOWN) lässt diesen kontrolliert zurückfahren. Das Signal des Servos wird an GP4 Ausgegeben. Nun sollen folgende Verbesserungen Stattfinden. 1. Die Pulsweite soll sich nur verändern wenn an GP5 ein High Signal anliegt (Der Servo soll seine Position halten). 2. Das zurückfahren des Servos (PWM DOWN) soll erst erfolgen, sobald an dem Eingang GP0 ein High Signal anliegt (Taster). 3.Sobald der Servo seinen Zielwert erreicht hat (im angefügten Programm 120 -->im PWM UP Teil) solll GP4 auf High schalten (LED Signalisiert, dass der Servo seinen Zielwert erreicht hat). Diese LED Soll nach dem Zurückstellen des Servos wieder Erlischen. Ich bin absolut kein Programmiergenie so wie manch andere hier...ich benötige deswegen einen Leitfaden oder persönlichen Kontakt. Ich Programmier das Ding neu, anhand dem was ihr mir hier sagen werdet...es reicht auch eine Strategie z.B. Bit....Setzen TCON....Setzen ... ... ... Gibt es eine Möglichkeit die PWM Ohne den externen Oszillator zu machen? Zum beispiel mit einem Timer oder sowas??? Das zurückfahren des Servos könnte man ja Mithilfe eines Interrupts an GP2 machen. Also sobald an GP2 eine High Flanke kommt kann ja das "Rückfahr Programm" Ausgeführt werden und die Pulsweite im normalen Programm wieder zurückgesetzt werden. Danke an alle die mich so geduldig ertragen!!!
Viel Zeit habe ich gerade nicht, deshalb keine vollstaendige Loesung. Aber ich hab mal einen Blick auf Dein urspruengliches Programm geworfen. Da ist TRISIO=0 gesetzt. Das heisst aber, alle Pins sind als Ausgaenge geschaltet - klar, dass Du da kein Eingangssignal lesen kannst. Stattessen // GP--> 76543210 TRISIO = 0b00100001; // binaer ist es leichter lesbar - ein bit pro Pin macht GP0 und GP5 zu Eingaengen. JETZT kannst Du da Signale anlegen und einlesen. Wenn das ueber Taster geschehen soll, brauchst Du noch Pull-Down-Widerstaende. Also Taster zwischen VCC und Eingang, einen 1 kOhm-Widerstand zwischen Eingang und GND. Damit ist der Eingang solide auf GND, wenn der Taster nicht betaetigt ist. LED Einschalten: gp4_bit = 1; LED Ausschalten: gp4_bit = 0; GP5 high? abfragen: if (gp5_bit) { .... } oder if (gp5_bit > 0) { .... } warten solange GP0 noch low ist: while (!gp0_bit) {} oder while (gp0_bit == 0) {} PWM und externer Oszillator haben miteinander nichts zu tun. Du kannst genauso den internen Oszillator verwenden, und den kann man auch verschnieden schnell einstellen (oder genauer gesagt, den Takt verschieden herunterteilen). Wenn Du MikroC verwendest, gibt es vorgefertigte Funktionen in der Library zum Einschalten der PWM sowie zum Veraendern des Tastverhaeltnisses (= Pulsbreite, Duty Cycle). Wolfgang
Das mit den Eingängen ist korrekt...die waren in dem ersten Programm noch nicht mit drin... Ich hoffe, dass die Aufgabe jetzt etwas klarer beschrieben ist. Ich benutze MicroC...Wie komme ich auf die vorgefertigten Funktionen? Das PWM Zeugs kenne ich bisher nur aus dem Datenblatt. Theoretisch kann ich die Pausenzeit ja Fix auf 15ms lassen und mit dem PWM Modul einen High Puls erzeugen der von ca. 500us bis 1500us ansteigt, oder?
Ich weiß nicht ob mikroC eine Software PWM Library hat. Das normale PWM1_Init ist jedenfalls für das interne PWM Modul. Das nützt dir nur nichts, wenn du die Frequenz nicht weit genug teilen kannst. Du kannst auch eine Fix-Pause von 18ms nehmen und die differenz von der Highzeit zu 2ms zusätzlich auch Low schalten und warten. Nur bringt es nicht unbedingt Vorteile. Du hast eine Variable die du hochzählst, wenn GP5 und GP0 auf high ist und zusätzlich, wenn die Variable kleiner als die maximale Highzeit ist. Beim runterzählen entsprechend. Und wenn der maximalwert erreicht ist, soll gp4 gesetzt werden.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Ich bin am Handy also kann ich nichts nachgucken. Du musst gucken, ob das Programm das so macht wie es soll. Ich weiß auch nicht die konstanten für die Bits (GP5 z.b. glaube es is eher GPIO.GP5_bit oder so) oder wie genau die funktion heißt, die eine variable zeit wartet aber das kannst du ja nachgucken. Vielleicht hilft das ja.
Einige schreiben, dass das mit dem internen PWM Modul nicht funktioniert...ist das so oder nicht. Ich habe auch eine Lösung gesehen, in der mit 2 Timern gearbeitet wird...allerdings wäre mir das PWM Modul lieber...
Wie schon früher erwähnt: Das PWM-Modul hat Grenzen in der Frequenz nach unten. PWM benutzt einen Hardware-Timer (Zähler), dessen Eingangstakt kommt vom Oszillatortakt, u.U. heruntergeteilt (typischerweise in Zweierpotenzen bis 2^8=256 möglich). Für eine bestimmte Oszillatorfrequenz kann man also das PWM nicht beliebig langsam laufen lassen. Natürlich kann man sich selber ein Timer-PWM basteln. Du verwendest MikroC, da schau mal in den mitgelieferten Beispielen unter Timer nach. Da hast Du ein vollständiges, lauffähiges Programm dazu. Musst nur noch Prescaler und Preload-Werte verändern, damit Du statt 1 Hz eben z.B. 20 Hz bekommst. (schau auch das "alte" MikroC an, also nicht MikroC Pro, da gibt es sogar ein Besipiel genau für the 12F673).
Ich probier die Strategie mit den Timern, das klingt am vielversprechensten. Da kann man relativ leicht sachen hinzuprogrammieren. Die werte ausrechnen ist kein problem..das hat nichts mit Syntax oder erfahrung zu tun :-) Tausend Dank
Wie ich weiter oben schon geschrieben hatte hat der 683 nur einen prescaler von 16. Bei 20ms PWM Periodendauer, also 50Hz kannst du den PIC nur bis zu einer bestimmten Frequenz takten. Da der PIC12F1822/1840 einen 64 Teiler haben, kannst du ihn also 4 mal schneller takten, da du ihn halt mehr teilen kannst. Deswegen frag ich ja auch was deine Aufgabe ist. Wenn du dieses von dir gepostete Programm erweitern sollst, bringt dir ein PWM-Modul rein garnichts, weil das im Programm ja garnicht vorkommst. Und wenn du die Freiheit hast, das ganze Programm neu zu schreiben, nämlich mit einem PWM-Modul, dann hast du ja evtl auch die Freiheit einen anderen PIC zu wählen, eben den 12F1822. Das Beispiel dazu hab ich ja weiter oben schon geschrieben. Wenn der PIC aber nichts anderes machen soll ist es egal ob delay (aus dem letzten Post von mir), timer mit interrupt oder pwm modul in Verbindung mit einem sehr langsamen Takt.
Das hier ist der Versuch das genze mit einem interrupt zu gestalten. Das Programm (welches natürnich NICHT funktioniert) hat folgenden Ablauf: Timer0 löst alle 20ms einen interrupt aus GP2 Ausgang geht auf 1 Timer1 Bestimmt die Pulslänge Wenn Timer1 überlauf bekommt geht der GP2 Ausgang wieder auf 0. Allerdings funktioniert da was nicht. Bitte mal durchschauen. Das Programm ist ohne Extras, soll also nur mal eine feste Pulslänge erzeugen (Länge ziemlich egal). MfG Stefan
Gast
#2557652
Wenn ich mich nicht verrechnet habe, komme ich auf ca. 65 ms für Timer 0. Hier muß ein H hin: TMR1H=253; //High Byte berechnen TMR1L=232; //Low Byte berechnen
Stefan Haussmann schrieb: > Timer0 löst alle 20ms einen interrupt aus > GP2 Ausgang geht auf 1 > Timer1 Bestimmt die Pulslänge > Wenn Timer1 überlauf bekommt geht der GP2 Ausgang wieder auf 0. Welchen Grund gibt es, dafür verschiedene Timer zu nehmen? Wenn Timings aufeinander folgen, nehme ich dazu auch den gleichen Timer, das ist einfacher. Ideal ist dazu ein Compareinterrupt. Dann kann der Timer durchlaufen und man setzt einfach nur den nächsten Comparewert. Peter
Das Programm soll später die Pulsweiten verändern. Außerdem hab ich nicht wirklich ahnung was du meinst.
Stefan Haussmann schrieb: > Außerdem hab ich > nicht wirklich ahnung was du meinst. Sorry, hab grad ins Datenblatt geschaut. Die Timer sind ja wirklich nur sehr rudimentär ausgestattet. Comparemode gibt es keinen. Ich bin das vom AVR so gewöhnt, daß selbst die kleinen 8-Pinner sehr flexible Timerfunktionen haben. Da gibt es mindestens 2 Compareregister, die auch einen Pin direkt umschalten können. D.h. es entsteht kein Jitter durch die Interruptlatenz. Das Schalten erfolgt auf den CPU-Zyklus genau. Gibt es irgendeinen Grund, warum Du gerade diesen PIC nimmst? Ich würde einen mit leistungsfähigerem Timer nehmen. Peter
Ich möchte keinen anderen Mikrocontroller verwenden...hab den 10 mal hier rumliegen. Ich habe das Programm übertragen und es funktioniert irgendwie nicht und ich weiß nicht warum. Ich bin im Programmieren nicht unbedingt ein Experte. Falls du da ahnung hast kannst du dir mal die Aufgabe durchlesen und schauen warum das nicht geht...bin schon am verzweifeln.
Das hier sieht schonmal komisch aus.
1 | |
2 | |
Zweimal TMR1L? Vielleicht kann Dein Compiler den Timer als 16Bit zugreifen, dann muß man low und high-Byte nicht selber auseinanderfriemeln. Auch kann C Konstanten selber ausrechnen. Man schreibt daher besser die Formel hin und keine magischen Zahlenwerte. Hier mal ein Beispiel für den AVR-GCC:
1 | |
2 | |
3 | |
4 | |
Peter
Gast
#2557862
PIE1 muß gesetzt werden und das INTCON Register auch. Aber nicht in der Interrupt Routine. Was sonst noch falsch war hab ich ja schon geschrieben.
Ich muss doch nur GIE setzen, das tu ich in "void timer0()"...das ist ja nicht die interrupt routine...Der schreibfehler (H und L) ist behoben. Funktioniert aber nicht. Ich möchte erstmal überhaupt einen Puls haben bevor ich die genauen werte berechne.
Gast
#2557904
Ich rede von Timer 1 und nicht von Timer 0.
was genau muss ich denn da setzen oder nicht setzen...kannst du mir die zeilen gschwind schiecken?
Ich versteh nicht was du genau meinst mit dem INTCON Register und Timer1. Bitte erklär mir das mal oder sag wo ich was reinschreiben muss.
Gast
#2559512
3 dinge die mir aufgefallen sind: 1- Du startest Timer0 nicht (daher keinen interrupts) 2- Du sollst den Timer0 Int Flag am ende des ISR wieder löschen. 3- Wenn Timer1 geschrieben wird ist es empfohlen den Timer vorher anzuhalten.
Wie Starte ich Timer0?? ich hab da so nichts gefunden
Gast
#2559580
Stefan Haussmann schrieb: > Wie Starte ich Timer0?? ich hab da so nichts gefunden Sorry hast recht, dachte an einen anderen PIC gerade. Ich hab dein SW ein wenig angepasst. Es ist noch ungetestet da ich keinen 12F675 da habe, aber vom Prinzip soll es gehen. Ich glaub dein problem lag an den "TMR1IF". Anderseits sagts du "T0IF_bit". Ich benutze den HiTech compiler zu wenig um das richtige zu erkennen, also bitte nachschlagen. ------------------------------------------------------------------------ -- int Count; //Zähler für durchläufe void Init() { ANSEL=0; CMCON=7; TRISIO=0; OPTION_Reg=0b11000111; /* 1-------; Betrifft nicht Timer0 -1------; Betrifft nicht Timer0 --0-----; Intern Takt für Timer0 verwenden ---0----; Bei ext. Takt b. stg Flanke inkr. (nicht relevant) ----0---; Prescaler für Timer 0 verwenden -----111; Prescaler (1:256) */ T0IF_bit=0; //Timer0 Interrupt Flag löschen T1IF_bit=0; //Timer1 Interrupt Flag löschen T0IE_bit=1; //Timer0 Interrupt erlauben T1IE_bit=1; //Timer1 Interrupt erlauben TMR0=180; // Timer0 Value } static void interrupt (void) //ISR { if (T0IF_bit) // Timer0 überlauf { GP2_bit=1; //Ausgang auf 1 TMR1H=253; //High Byte berechnen TMR1L=232; //Low Byte berechnen //Timer1 Starten T1CON=0b00000001; /* 0-------; Nicht relevant -0------; Nicht relevant --00----; Precsaler (1:1) ----0---; Sync. m. ext. Takt (Hier nicht relevant) -----0--; Internet Tackt verwenden -------1; Timer starten */ T0IF_bit=0; //Timer0 Interrupt Flag löschen } if (T1IF_bit) // Timer1 überlauf { GP2_bit=0; //Ausgang auf 0 Count++; //Zähler um 1 erhöhen //Timer1 Stoppen T1CON=0b00000000; T1IF_bit=0; //Timer1 Interrupt Flag löschen } } void main() { Init(); GIE_bit=1; //Alle unmaskierten interrupts erlauben while(1) {} } ----------------------------------------------------------------------
Gast
#2559585
Stefan Haussmann schrieb: > Wie Starte ich Timer0?? ich hab da so nichts gefunden RTFM Seite 29 > Timer mode is selected by clearing the T0CS bit > (OPTION_REG<5>). Das ist dein erstes Kommando > In Timer mode, the Timer0 > module will increment every instruction cycle (without > prescaler). Das macht er dann > Counter mode is selected by setting the T0CS bit > (OPTION_REG<5>). In this mode, the Timer0 module > will increment either on every rising or falling edge of > pin GP2/T0CKI. Das willst du nicht > 4.2 Timer0 Interrupt > A Timer0 interrupt is generated when the TMR0 > register timer/counter overflows from FFh to 00h. This > overflow sets the T0IF bit Das Flag kannst du ohne Interrupt Abfragen. Stefan Haussmann schrieb: > Ich hoffe dass es in diesem Forum einige Experten gibt, die mir einen > kleinen C-Code zukommen lassen könnten. > http://forum.htsoft.com/all/showflat.php? Cat=0&Board=pic&Number=193402&Searchpage=1&Main=193122&Words=+NexxuSix&t opic=&Search=true Google: code example 12F675 hightech c (1 Eintrag)
Hey PICfan, du bist klasse...das ding funktioniert...du bist einer der ersten die mal konkret gesagt haben wo das Problem liegt und was zu tun ist. Dass du das Pgogramm selber geändert hast finde ich riesig. Danke
Gast
#2559627
Bitte sehr. Es freut mich das ich helfen könnte (und vor allem das es funktioniert hat :-))
Gast
#2559640
Hi, um niedrigere Frequenzen zu Stefan Haussmann schrieb: > Kann ich einzelne ports so ansprechen?: > > GPIO3=1; > > oder muss ich das hier anders machen (beim 16F84 sind die Bezeichnungan > ja RA, beziehungsweise RB...) Also wenn du schon für die einfachsten Fragestellungen die Hilfe vom Forum benötigst, dann wirst du es nicht weit bringen. Willst du denn dann dein gesamtes Projekt durch Foren zusammenpicken?
Es gibt doch noch ein kleines Problem...ich erhalte mit dem Programm eine gleichmäßige Pulsfolge, kann aber die Hochzeit nicht einstellen. Irgend was ist da noch faul. Ich habe den Timer0 jetzt auf etwa 15ms eingestellt. Nun erhalte ich 15ms low und 15ms high...
Gast
#2559940
Stefan Haussmann schrieb: > Nun erhalte ich 15ms low und 15ms high Wenn du z.B den Pin nur toggelst GPIOx != GPIOx kann nur ein symmetrisches Puls/Pausenverhältnis rauskomnmen.
Gast
#2559956
Stefan Haussmann schrieb: > Wie Starte ich Timer0?? ich hab da so nichts gefunden Krass
Der Rächer der Transisitormorde schrieb: > Stefan Haussmann schrieb: >> Nun erhalte ich 15ms low und 15ms high > > Wenn du z.B den Pin nur toggelst > > GPIOx != GPIOx > > > kann nur ein symmetrisches Puls/Pausenverhältnis rauskomnmen. Also das klingt zwar gut aber ich weiß nicht was du meinst...
Hallo... Also jetzt tick ich demnächst aus. Ich hab eine Schaltung aufgebaut, so wie im Anhang. Allerdings habe ich das Problem, dass ich aus irgend einem Grund die Eingangssignale nicht lesen. Ich verwende folgende Konfiguration:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
was ist des eigentlich für eine Abschlussarbeit? Tüftelst du da jetzt schon 3 Monate an dem Problem? Zeig halt mal dein ganzes Programm. Vielleicht ist ja auch die Abfrage falsch...
Das mit dem Servo ist nur Bonus...also das sahnehäubchen...das wollt ich nebenher machen...jetzt bin ich mit dem andern zeug fertig, doku ist auch fast fertig und jetzt will ich das auch noch auf die reihe kriegen. Also das Programm funktioniert auf der Vellemann-Entwicklungsplatine, aber bei meiner selbst gelöteten schaltung ist das net so :-) Das hier ist das Vollständige Programm:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
Stefan Haussmann schrieb: > void main() //MAIN LOOP > { > Init(); //Konfiguration ausführen > } //END MAIN LOOP Das ist keine Main-Loop, sondern eine Main-Funktion, die einmal durchläuft. Da du kein "while(1);" drin hast, ist das Programm durch und ist entweder irgendwo im undefinierten Programmspeicher oder aber am Ende. Stefan Haussmann schrieb: > counter=RateOfChange Dir ist bewusst, dass das eine Zuweisung ist und kein Vergleich auf Gleichheit? Meist wird in if-Bedingungen ja geprüft ob es gleich ist. Stefan Haussmann schrieb: > if((HighTime<HighTimeMax)&&(counter=RateOfChange)) > { > Hightime++; //Impuls verlängern > } > > if (Hightime==HighTimeMax) //Hochzeit erreicht? > { > GPIO.B1=1; //Ausgang HALTESIGNAL setzen > } > else > { > GPIO.B1=0; //Ausgang HALTESIGNAL löschen > } > > if (GPIO.B5==1) //Prüfen ob Reset Taster==1 > { > Hightime=HighTime; //HighTime auf Startwert setzen > } Also wenn ich das Programm richtig verstehe, dann müsste es hier überall statt HighTime nur Time heißen, außer ganz unten dann time = HighTime. Damit wäre Time die Variable, die hochgezählt wird und die immer größer werdende Zeit, wielange das signal auf high ist und HighTime wäre der Startwert (der demnach nicht hochgezählt werden soll). Doch dann muss das Time = Hightime ganz oben weg, denn dann überschreibst du das hochgezählte immer wieder mit dem Startwert. Dann müsste aber Time bei der Definition den Startwert bekommen. Wenn du das so wie oben geschrieben behalten willst, brauchst du eine Variable mit dem Startwert der Hightime, den du nicht veränderst (so wie im moment mit "HighTime++;"). Dann wäre aber folgendes überflüssig: Stefan Haussmann schrieb: > Time=HighTime; //Timer auf High Pulslänge setzen > TMR1H=(65536-Time)/256; //Highbyte setzen > TMR1L=(65536-Time)%256; //Lowbyte setzen Denn dann könntest du auch schreiben: > TMR1H=(65536-HighTime)/256; //Highbyte setzen > TMR1L=(65536-HighTime)%256; //Lowbyte setzen Und wenn du das so änderst und die Variable für den Startwert hinzufügst, wirst du sehen, es ist genau das gleiche wie ich davor beschrieben hab, nur dass die Variablen-Namen anders sind;)
OK, was ist mit den Abfragen an den beiden Eingängen...passt das zum Schaltplan...(Verschaltung, TRISIO Register usw...)
Ansich ja. Ist die Schaltung da mit Target gezeichnet? Wenn ja ist meines Wissens so ein Quadrat mit nem Kreuz drin ein Fehler, also keine Verbindung oder zu dicht etc. Ist deine Platine geätzt oder gefräst oder so iwie mit Lochraster. Wenns bei einer Platine funktioniert und bei einer anderen nicht, liegt es meist bei der Platine. Wobei ich bezweifle, dass das Programm da oben so funktioniert, wie es soll.
Haha...ich hab das vorhin schnell abgezeichnet von meinem Blockblatt gg....hab das mit Silberdraht gelötet. Und ja.....es ist Target. Das dauert noch bis die Platine Ätzfertig ist...
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.