Forum: Mikrocontroller und Digitale Elektronik PIC Mikrocontroller


von Mario H. (mariohorvat)


Lesenswert?

Halloo Jungs,

ich habe ein problem...

warum kann ich so keine 2 Ausgänge gleichzeitig auf logisch 1 schalten??


  bsf    PORTA,0
  bsf    PORTA,1
  call           wait3s   ; Wartezeit von 3s
  bcf    PORTA,0
  bcf    PORTA,1

hat jemand eine ide??

PIC 16F628A
Assembler
Mario

von Jan S. (jan_s)


Lesenswert?

Mario Horvat schrieb:
> warum kann ich so keine 2 Ausgänge gleichzeitig auf logisch 1 schalten??

WIe meinst Du das? Was geht denn nicht?

von Lehrmann M. (ubimbo)


Lesenswert?

Mario Horvat schrieb:
> warum kann ich so keine 2 Ausgänge gleichzeitig auf logisch 1 schalten??

Wer sagt, dass es nicht geht. Bzw-Weise woran machst du fest, dass es 
nicht geht ?

Taktquelle, Stromversorgung, Schaltplan, Layout, kompletter Code, ist 
PORTA definiert, wie sieht die wait loop aus, Config-Bits ?

Es gibt tausende Fehlerquellen - alles was oben steht müssen wir wissen 
...

Mario Horvat schrieb:
> hat jemand eine ide??

um eine Idee zu haben bräuchte man mehr Infos.

Dem Fakt, dass du annimmst, dass du keine 2 Ausgänge gleichzeitig auf 
logisch 1 schalten kannst entnehme ich, dass deine Anwendung nicht 
funktioniert ?!

Oder möchtest du wissen wie du 2 Bits auf einmal setzten kannst ?

von Mario H. (mariohorvat)


Angehängte Dateien:

Lesenswert?

alsoo sobald ich auf die taste drücke die mir diese 2 ausänge setzten 
würden, ist nur auf einem Ausgang logisch 1 und beim 2 bleibt 0.....

genau ich kann keine 2 Ausgänge auf logisch 1 schalten..

Schaltplan mitdabei

von tt4u (Gast)


Lesenswert?

mit BSF bzw. BCF kann man keine Ausgänge gleichzeitig schalten, da sind 
4 Oszillatortakte dazwischen.

Es geht aber trotzdem:

   MOVFW PORTA           ; Port A lesen
   ANDLW B'11111100', W  ; Bit 0 und 1 löschen
   MOVWF PORTA           ; Port A zurückschreiben

   MOVFW PORTA           ; Port A lesen
   IORLW B'00000011',W   ; Bit 0 und 1 setzen
   MOVWF PORTA           ; Port A zurückschreiben

oder auch

   MOVLW B'11111100', W  ; Bit 0 und 1 sollen gelöscht werden
   ANDWF PORTA, F        ; Port A lesen, ändern und zurückschreiben

   MOVLW B'00000011', W  ; Bit 0 und 1 sollen gesetzt werden
   IORWF PORTA, F        ; Port A lesen, ändern und zurückschreiben

von Carsten S. (dg3ycs)


Lesenswert?

Hi,

Mario Horvat schrieb:
> Halloo Jungs,
>
> ich habe ein problem...
>
> warum kann ich so keine 2 Ausgänge gleichzeitig auf logisch 1 schalten??
>
>
>   bsf    PORTA,0
>   bsf    PORTA,1
>   call           wait3s   ; Wartezeit von 3s
>   bcf    PORTA,0
>   bcf    PORTA,1
>
> hat jemand eine ide??
>
> PIC 16F628A
> Assembler
> Mario

Hat da jemand nicht das Datenblatt gelesen...

Natürlich kannst du zwei Ausgänge gleichzeitig schalten...
Was du nicht kannst ist zwei Pins desselbens Ports extrem KURZ 
nacheinander schalten wie du es tust.

Wenn du mit BSF das Register eines Ports veränderst, dann braucht der 
Ausgangstreiber einige ns bis die Spannung am Ausgang auch tatsächlich 
vorhanden ist (Anstiegszeit!)

Bei einem zugriff auf Porta (Portb, Portc...) mit bsf, bcf usw. passiert 
nun folgendes:
Als erstes wird der aktuelle Portzustand eingelesen, dann wird das 
jeweilige Bit gesetzt und dann zurückgeschrieben.
Wenn deine Taktfrequenz nun nicht gerade langsam ist passiert bei deiner 
methode nun das
>   bsf    PORTA,0 ;Das BIT 0 im Register PORTA 0 wird auf 1 gesetzt, Die Spannung 
am PORTA 0 beginnt zu steigen!
>   bsf    PORTA,1 ; Nun wird PORTA aber als ganzes sofort wieder eingelesen... je 
nach Takt ist die Spannung an PORTA 0 aber noch gar nicht über die HIGH schwelle 
gekommen, wird also als LOW gelesen,
Das Ergebniss mit dem fälschlich als LOW gelesenen PORTA0 wird nun an 
Bit 1 auf HIGH gesetzt und mit dem falsch erkannten LOW an PORTA0 (zum 
Beispiel als 00000010) zurückgeschrieben.
Im Ergebniss ist PORTA0 dann wieder LOW, PORTA1 aber High...

Abhilfe:
Man könnte es so machen:
>   bsf    PORTA,0
>   nop
>   nop
>   nop
>   nop
>   bsf    PORTA,1
ich glaube 4 Befehlszyklen waren empfohlen, schaue aber noch mal unter 
PORTS in DB. Diese Lösung ist aber nicht die Optimale.

Wenn du an dieser Stelle des Programms weist wie die anderen BITS von 
PORTA aussehen kannst du natürlich auch direkt das ganze Byte schreiben:
> movlw b'00000011'
> movwf PORTA

kann der Zustand der anderen PORTAUSGÄNGE verschiedene Zustände zu 
diesem Zeitpunkt annehmen muss man OR (oder) verknüpfen:
> movlw b'00000011'
> iorwf PORTA, 1
(setzt nur die beiden Ausgänge PORTA0 &1 auf High, der Rest belibt 
unverändert)
Analog dazu kann man dann mit der AND Verknüpfung auch geziehlt mehrere 
Ausgänge gleichzeitig löschen:
statt:
>   bcf    PORTA,0
>   bcf    PORTA,1

 also
> movlw b'11111100'
> andwf PORTA, 1

GRuß
Carsten

von Michael S. (rbs_phoenix)


Lesenswert?

Carsten Sch. schrieb:
> Was du nicht kannst ist zwei Pins desselbens Ports extrem KURZ
> nacheinander schalten wie du es tust.

Uff das hab ich auhc noch nicht gewusst;) Aber ergibt Sinn. Ich hab in 
der Ausbildung mal einen PIC16F84 mit 4MHz Takt gehabt (Programmtakt 
1MHZ) und da hats funktioniert. Ist warscheinlich zu langsam gewesen. 
Doch egal wie schnell es geht, mit dieser Methode ist es (meiner Meinung 
nach) am besten gelöst und ist auch wirklich gleichzeitig (oder am 
gleichzeitigsten;) )

tt4u schrieb:
> Es geht aber trotzdem:
>
>    MOVFW PORTA           ; Port A lesen
>    ANDLW B'11111100', W  ; Bit 0 und 1 löschen
>    MOVWF PORTA           ; Port A zurückschreiben
>
>    MOVFW PORTA           ; Port A lesen
>    IORLW B'00000011',W   ; Bit 0 und 1 setzen
>    MOVWF PORTA           ; Port A zurückschreiben

von Dieter W. (dds5)


Lesenswert?

Es handelt sich vermutlich um das "read-modify-write" Problem.

Ein bsf Befehl auf eine Portadresse liest erstmal die anliegenden Daten 
ein. Dann wird das entsprechende Bit gesetzt und die Daten werden wieder 
ausgegeben.
Beim ersten Mal klappt das auch. Beim zweiten Befehl ist aber das 
gesetzte Bit des vorhergehenden Befehls noch nicht am Port angekommen 
(z.B. wegen kapazitiver Belastung) und wird wieder als low eingelesen 
und dann wieder ausgegeben.

Mach mal ein oder wenn das nicht reicht auch zwei nop zwischen die 
beiden Befehle.

Die neueren PICs haben deshalb zwei Register für jeden Port, zum Lesen 
das PORT und zum Schreiben das LATCH.


Grmpf, zu lange getippt ...

von Mario H. (mariohorvat)


Lesenswert?

ok ein riesengroßes dankeschön
an euch alle

seit wirklich wahnsinn

dankee

von Jan S. (jan_s)


Lesenswert?

Hammer, wusste ich auch nicht, muss gleich mal gucken ob das beim AVR 
auch so ist ;-) Da wäre mir das bislang noch nicht aufgefallen.

von Jan S. (jan_s)


Lesenswert?

Alsoo beim AVR dürfte das aufgrund des extra Latch Registers PORTn kein 
Thema sein, aber die Funktionsweise ist wohl auch hier 
Read-Modify-Write.

von Sven P. (Gast)


Lesenswert?

Ja. Allerdings wird der Ausgangszustand separat gespeichert. Wobei die 
Treiber auch nicht so abartig lahm sind, ein paar MHz bekommt man da 
schon am Pin gewackelt.
Mein liebes Beispiel:

DDRx = 1, PORTx = 1, dann den Pin außen kurzschließen. PORTx liest 1, 
PINx liest 0...

Hatten die PIC nicht auch irgendwo mal solche 'LAT'-Registersätze?

von Geist (Gast)


Lesenswert?

AD-Wandler abgeschaltet?? Sonst machen die bcf/bsf Befehle auf dem PORTA 
genau solche blöden Effekte...
PIC16F628 hat AD-Wandler, PIC16F84 nicht.

von Jan S. (jan_s)


Lesenswert?

Sven P. schrieb:
> DDRx = 1, PORTx = 1, dann den Pin außen kurzschließen. PORTx liest 1,
> PINx liest 0...

Öhm, wie lange hält er das aus? ;-)

von Carsten S. (dg3ycs)


Lesenswert?

Geist schrieb:
> AD-Wandler abgeschaltet?? Sonst machen die bcf/bsf Befehle auf dem PORTA
> genau solche blöden Effekte...
> PIC16F628 hat AD-Wandler, PIC16F84 nicht.

Nööö...
Mit den AD Wandlern hat das nichts -aber gar nichts- zu tun...
Das wurde oben schon von drei verschiedenen Usern (incl. mir) richtig 
beantwortet. Siehe auch das Datenblatt zum PIC16F628

PIC16F628 DB - Seite 42 Abschnitt 5.3.1
BI-DIRECTIONAL I/O PORTS
> Any instruction which writes, operates internally as a
> read followed by a write operation. The BCF and BSF
> instructions, for example, read the register into the
> CPU, execute the bit operation and write the result
> back to the register

PIC16F628 DB - Seite 42 Abschnitt 5.3.2
SUCCESSIVE OPERATIONS ON I/O PORTS
> The actual write to an I/O port happens at the end of an
> instruction cycle, whereas for reading, the data must be
> valid at the beginning of the instruction cycle (Figure 5-
> 16). Therefore, care must be exercised if a write
> followed by a read operation is carried out on the same
> I/O port.
(Anmerkung: Wie im Zitat von 5.3.1 zu sehen ist, ist ein Write durch 
BCF/BSF auch eine Read operation! Daher gilt dies also auch für BCF/BSF)
> The sequence of instructions should be such
> to allow the pin voltage to stabilize (load dependent)
> before the next instruction which causes that file to be
> read into the CPU is executed. Otherwise, the previous
> state of that pin may be read into the CPU rather than
> the new state. When in doubt, it is better to separate
> these instructions with a NOP or another instruction not
> accessing this I/O port.

Gruß
Carsten

von Geist (Gast)


Lesenswert?

Carsten Sch. schrieb:
> Nööö...
> Mit den AD Wandlern hat das nichts -aber gar nichts- zu tun...

Wir haben beide Recht ;-)
Ports, die auf 'analog' stehen, ergeben beim Einlesen über den 
PORT-Befehl wohl immer eine Null. Was natürlich bei den bcf/bsf 
(Read-modify-write Befehle!) zu seltsamen verhalten führt. Weil setzen 
kann man so einen analogen Port, alber bein lesen kommt doch wieder Null 
zurück.
Egal ob AD-Wandler oder Komperator-Eingänge.

von Dirk W. (Gast)


Lesenswert?

Sehr lesenswert in diesem Zusammenhang:

http://www.sprut.de/electronic/pic/fallen/fallen.html

(das in diesem Thread genannte Problem wird unter "Die in/out-Falle" 
erläutert)

von Carsten S. (dg3ycs)


Lesenswert?

Hi,

Dirk W. schrieb:
> Sehr lesenswert in diesem Zusammenhang:
>
> http://www.sprut.de/electronic/pic/fallen/fallen.html
>
> (das in diesem Thread genannte Problem wird unter "Die in/out-Falle"
> erläutert)

guter Link, nur der Unterabschnitt ist nur Fast richtig...
Die IN/OUT Falle beschreibt ein anderes "Problem" das aber natürlich die 
Grundlage in demselben VErhalten hat wie das hier behandelte Problem.

Zutreffend ist hier: "Die I/O-Speed-Falle" von derselben Seite.

Geist schrieb:
> Wir haben beide Recht ;-)
Naja, nicht ganz, denn was du hier beschreibst:
> Ports, die auf 'analog' stehen, ergeben beim Einlesen über den
> PORT-Befehl wohl immer eine Null. Was natürlich bei den bcf/bsf
> (Read-modify-write Befehle!) zu seltsamen verhalten führt. Weil setzen
> kann man so einen analogen Port, alber bein lesen kommt doch wieder Null
> zurück.
>
> Egal ob AD-Wandler oder Komperator-Eingänge.
ist eine Sonderversion der "In / Out Falle" um bei der verlinkten Sprut 
Seite zu bleiben.
Für diesen Thread passt das aber nicht, da ja ein Analogeingang kein 
Ausgang sein kann und hier ja keine Umschaltung stattfindet!

Gruß
Carsten

von Geist (Gast)


Lesenswert?

Carsten Sch. schrieb:
> Für diesen Thread passt das aber nicht, da ja ein Analogeingang kein
> Ausgang sein kann und hier ja keine Umschaltung stattfindet!

Oh doch, ist ein undokumentiertes 'Feature' von Microchip. Zumindest bei 
den 16er PICs, im speziellen der 16F877 (getestet, leider...). Also 
vermutlich auch der 16F628. Der ist ja so etwa aus der selben 
Generation.

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
Noch kein Account? Hier anmelden.