PIC12F675 brauche Hilfe

OP #2433934
Lesenswert?

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
#2434003
Lesenswert?

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
#2434014
Lesenswert?

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 #2434084
Lesenswert?

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).
#2435723
Lesenswert?

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
OP #2438052
Lesenswert?

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...
#2438168
Lesenswert?

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
OP #2539742
Lesenswert?

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
Angehängte Dateien:
#2539993
Lesenswert?

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
Lesenswert?

1
#include <pic.h>
2
#include <htc.h>
3
__CONFIG(MCLREN & INTCLK &  INTIO);
4

5
main()
6
{
7
    int iTest;
8
    
9
    TRIS0 = 1; // Input
10
    TRIS5 = 0; // Output
11
    TRIS4 = 0; // Output
12
    WPU5  = 1; //Pullup 
13
    WPU4  = 1; //Pullup
14

15
    iTest = 1000;
16
    while(iTest--)
17
        {
18
        GPIO5 = 0;
19
        GPIO4 =1;
20
        }// endwhile
21
    iTest = 1000;
22
    while(iTest--)
23
        {
24
        GPIO5 = 1;
25
        GPIO4 = 0;
26
        }//endwhile
27
}// endfuction
#2540921
Lesenswert?

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.
OP #2541246
Lesenswert?

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...
Angehängte Dateien:
#2542375
Lesenswert?

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.
OP #2549476
Lesenswert?

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!!!
#2549504
Lesenswert?

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
OP #2549611
Lesenswert?

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?
#2549699
Lesenswert?

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
if(GP5) // musst gucken, wie die gp5 variable heißt
2
  if(!GP0 && variable_warten < maximalzeit) variable_warten++; //oder variable_warten += zeit_zum_addieren;
3
  if(GP0 && variable_warten > minimalzeit) variable_warten--;
4
}
5
if(variable_warten >= maximalzeit) GP4 = 1;
6
else GP4 = 0;
7

8
GP2 =1;
9
us_vdelay(variable_warten);
10
GP2 = 0;
11
us_vdelay(20000 - variable_warten);

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.
#2549795
Lesenswert?

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).
#2550212
Lesenswert?

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.
OP #2557619
Lesenswert?

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
Angehängte Dateien:
#2557659
Lesenswert?

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
#2557798
Lesenswert?

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
OP #2557807
Lesenswert?

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.
#2557845
Lesenswert?

Das hier sieht schonmal komisch aus.
1
        TMR1L=253; //High Byte berechnen
2
        TMR1L=232; //Low Byte berechnen
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
#define F_CPU 16e6                           // 16MHz
2
#define T1_PRESCALER 8                       // F_CPU / 8
3

4
  OCR1A = F_CPU / T1_PRESCALER * 20e-3 - 1;  // 20e-3 = 20ms


Peter
Gast #2559512
Lesenswert?

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.
Gast #2559580
Lesenswert?

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
Lesenswert?

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)
Gast #2559640
Lesenswert?

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?
OP #2569029
Lesenswert?

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
//##############VARIABLENDEFINITION#############################
2

3
//##############HARDWAREKONFIGURATION###########################
4
//Diese Variablen sind vom Anwender selbst einzutragen.
5

6
int LowTime=19000;         //Eingestellte Pausenzeit (18,5ms)
7
int HighTime=800;          //Eingestellte Pulslänge (STARTWERT)
8
int HighTimeMax=2000;      //Maximale Pulslänge (ENDWERT)
9
int RateOfChange=1000;     //Änderungsgeschwindigkeit
10

11
//##############SYSTEMVARIABLEN#################################
12
int Time;                  //Variable für Timerwert
13
char Ausgang=0;            //Status des Ausgangsports
14
int counter=0;             //Zähler für Änderungsgeschwindigkeit
15
//##############################################################
16

17

18
  void Init()             //Initialisierungsroutine für Timer
19
 {
20

21
      ANSEL=0;            //Alle Ausgänge Digital
22
      CMCON=7;            //Kein Komperator
23
      TRISIO=0b00110000;  //GP4,GP5 als Eingang
24
      T1CON=0b00000001;   //Timer 1 Konfigurieren und starten
25
       /*     0-------;    Nicht relevant
26
              -0------;    Nicht relevant
27
              --00----;    Precsaler (1:1)
28
              ----0---;    LP Oszilator aus (nicht relevant)
29
              -----0--;    Sync. ext. Takt (Hier nicht relevant)
30
              ------0-;    Internet Takt verwenden
31
              -------1;    Timer starten
32
       */
33
      GIE_bit=1;  //Alle unmaskierten interrupts erlauben
34
      PEIE_bit=1; //PERIPHERAL INTERRUPTS ENABLE
35
      T1IE_bit=1; //Timer1 Interrupt erlauben
Angehängte Dateien:
OP #2569343
Lesenswert?

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
//##############VARIABLENDEFINITION#############################
2

3
//##############HARDWAREKONFIGURATION###########################
4
//Diese Variablen sind vom Anwender selbst einzutragen.
5

6
int LowTime=19000;         //Eingestellte Pausenzeit (18,5ms)
7
int HighTime=800;          //Eingestellte Pulslänge (STARTWERT)
8
int HighTimeMax=2000;      //Maximale Pulslänge (ENDWERT)
9
int RateOfChange=1000;     //Änderungsgeschwindigkeit
10

11
//##############SYSTEMVARIABLEN#################################
12
int Time;                  //Variable für Timerwert
13
char Ausgang=0;            //Status des Ausgangsports
14
int counter=0;             //Zähler für Änderungsgeschwindigkeit
15

16
//##############################################################
17

18

19
  void Init()             //Initialisierungsroutine für Timer
20
 {
21

22
      ANSEL=0;            //Alle Ausgänge Digital
23
      CMCON=7;            //Kein Komperator
24
      TRISIO=0b00110000;  //GP4 und GP5 als Eingang
25
      T1CON=0b00000001;   //Timer 1 Konfigurieren und starten
26
       /*     0-------;    Nicht relevant
27
              -0------;    Nicht relevant
28
              --00----;    Precsaler (1:1)
29
              ----0---;    LP Oszilator aus (nicht relevant)
30
              -----0--;    Sync. ext. Takt (Hier nicht relevant)
31
              ------0-;    Internet Takt verwenden
32
              -------1;    Timer starten
33
       */
34
      GIE_bit=1;  //Alle unmaskierten interrupts erlauben
35
      PEIE_bit=1; //PERIPHERAL INTERRUPTS ENABLE
36
      T1IE_bit=1; //Timer1 Interrupt erlauben
37

38
 }
39

40
 void interrupt ()
41
 {                             //BEGIN ISR
42
   if (Ausgang==0)             //Ausf. wenn Status=0
43
   {   GPIO.B2 = 1;            //Ausgang auf High
44
   Time=HighTime;              //Timer auf High Pulslänge setzen
45
   TMR1H=(65536-Time)/256;     //Highbyte setzen
46
   TMR1L=(65536-Time)%256;     //Lowbyte setzen
47
   T1IF_bit=0;                 //Timer1 Interrupt Flag löschen
48
   Ausgang=1;                  //Status auf 1
49
   
50
   if (GPIO.B4==1)            //Prüfen ob Freigabe=1
51
    {   
52
     counter++;                //Impulszähler um 1 erhöhen
53
    }
54
    
55
   if((HighTime<HighTimeMax)&&(counter=RateOfChange))
56
    {
57
    Hightime++;                //Impuls verlängern
58
    }
59
     
60
    if (Hightime==HighTimeMax) //Hochzeit erreicht?
61
     {
62
     GPIO.B1=1;                //Ausgang HALTESIGNAL setzen
63
     }
64
    else
65
     {
66
     GPIO.B1=0;                //Ausgang HALTESIGNAL löschen
67
     }
68
    
69
    if (GPIO.B5==1)            //Prüfen ob Reset Taster==1
70
    {
71
    Hightime=HighTime;         //HighTime auf Startwert setzen
72
    }
73
   }
74

75
   else                        //Ausf. wenn Status=1
76
   {
77
   GPIO.B2 = 0;                //Ausgang auf Low
78
   Time=LowTime;               //Timer auf Low Pulslänge setzen
79
   TMR1H=(65536-Time)/256;     //Highbyte setzen
80
   TMR1L=(65536-Time)%256;     //Lowbyte setzen
81
   T1IF_bit=0;                 //Timer1 interrupt Flag löschen
82
   Ausgang=0;                  //Status auf 0
83
   }
84

85
 }                             //END ISR
86

87

88
void main()         //MAIN LOOP
89
{
90
     Init();        //Konfiguration ausführen
91
}                   //END MAIN LOOP
#2569391
Lesenswert?

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;)
#2569433
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren