Forum: Mikrocontroller und Digitale Elektronik Carrybit? Assembler


von Stefan (Gast)


Lesenswert?

Hallo
Wir benutzen den AT89S52.
Wollen eine I²C Verbindung zu einer Eingabeplatine bestehend aus 8 
Schaltern mit dem PCF8574P aufbauen.
Ausgegeben soll der Zustand über 8 LEDs auf dem µC-Board, welche am P0 
angeschlossen sind.

Mit dem unten stehenden Code klappt dies auch, einzige Einschränkung 
ist, dass wenn wir den achten Schalter betätigen und dann mit P3.2 bzw 
P3.3 das Bitmuster auf die LEDs übertragen wollen, diese machen was sie 
wollen. Kann es sein das hiermit das Carrybit geschrieben wird? Also ein 
Übertrag?
Was müßten wir machen damit dies funktioniert?


#include "8051.h"
#include "I2C_ASM.h"
;
; 8574er Kennung: 0100xxxy
;
SEND000  .equ  01000000b  ;  ON  ON ON
SEND001  .equ  01000010b  ;  ON  ON off
SEND010  .equ  01000100b  ;  ON off ON
SEND100  .equ  01001000b  ;  off ON ON
SEND101  .equ  01001010b  ;  off ON off
;
READ000 .equ  01000001b  ;  ON  ON ON
;
MAIN
LOOP
TASTEN
  jnb P3.2, UNDLOS  ; Taster KISS-Board
  jnb P3.3, UNDLOS  ; Taster 8574-Platine
  ljmp TASTEN

UNDLOS  lcall I2C_START

  mov A, #READ000
  lcall I2C_WRITE

  lcall I2C_READ

  lcall I2C_STOPP
  mov P0, A
  ljmp LOOP

.end

von 8051 MCU (Gast)


Lesenswert?

da wird kein Carry geschrieben.
Um den Fehler zu finden brauchen wir schon den Rest von Code.
Carry wird bei math. Operationen geändert und beim schieben über Carry.

von Stefan (Gast)


Lesenswert?

Das die I²C - Header -Datei

;*********************************************************
; I2C-Routinen
;*********************************************************

; Assembler-Routinen zur Kommuinikation uber einen I2C-Bus.
; Einbinden in das *.asm-File durch "include" am Anfang.
; 24.2.2008 E. Ofenbach

SDA  .equ P3.5  ;Datenleitung
SCL  .equ P3.4  ;Taktleitung

  ljmp I2C_ENDE


I2C_START:    ;Startbedingung am Bus erzeugen
  ;*************************************************
  ; Aufruf:
  ; SDA=H, SCL=H
  ; keine Uebergabe
  ; Ende:
  ; SDA=L, SCL=L
  ; keine Rueckgabe
  ; keine Register unveraendert
  ;*************************************************
      ;lcall vom Aufruf    2Z
  clr SDA    ;Daten auf LOW
  nop    ;4us warten      1Z
  nop    ;        1Z
  nop    ;        1Z
  nop    ;        1Z
  clr SCL    ;Takt auf LOW
  ret    ;        2Z
;*********************************************************

I2C_STOPP:    ;Stoppbedingung am Bus erzeugen
  ;*************************************************
  ; Aufruf:
  ; SDA=X, SCL=L
  ; keine Uebergabe
  ; Ende:
  ; SDA=H, SCL=H
  ; keine Rueckgabe
  ; Register unveraendert
  ;*************************************************
      ;lcall beim Aufruf    2Z
  clr SDA    ;SDA auf L, falls noch nicht da 1Z
  setb SCL  ;Takt auf HIGH
  nop    ;4us warten      1Z
  nop    ;        1Z
  nop    ;        1Z
  nop    ;        1Z
  setb SDA  ;SDA=H
  nop    ;4.7us/2 warten      1Z
  ret    ;        2Z
;*********************************************************

I2C_WRITE:    ;Schreiben eine Bytes
  ;*************************************************
  ; Aufruf:
  ; SDA=X, SCL=L
  ; Akku enthaelt Datenbyte
  ; Ende:
  ; SDA=H, SCL=L
  ; ACK-Bit wird in Carry zurueckgegeben
  ; Register unveraendert
  ;*************************************************
      ;lcall vom Aufruf    2Z
  push 0    ;Register 0 sichern    2Z
  push ACC  ;Akku sichern      2Z
  mov R0,#8  ;Schleifenzähler (8Bit)    1Z
I2C_WRITE_LOOP:
  rlc A    ;Bit in Carry schieben    1Z
  mov SDA,C  ;Carry auf Bus legen    2Z
      ;setup time=250ns
  setb SCL  ;pos. Taktflanke
  nop    ;4us warten      1Z
  nop    ;        1Z
I2C_WRITE_WAIT:
  jnb SCL,I2C_WRITE_WAIT ;Taktverlaengerung?  2Z
  clr SCL    ;neg. Taktflanke (hold time=0)
  nop    ;        1Z
  nop    ;        1Z
  djnz R0,I2C_WRITE_LOOP  ;Alle 8 Bit?    2Z
I2C_WRITE_ACK:
  setb SDA  ;SDA "loslassen"    1Z
  setb SCL  ;SCL=H, t_SU_DAT=250ns
  nop    ;t_HIGH_min=4us      1Z
  nop    ;        1Z
I2C_WRITE_ACK_WAIT:
  jnb SCL,I2C_WRITE_ACK_WAIT ;Taktverlaengerung?  2Z
  mov C,SDA  ;Status der SDA Leitung einlesen
  clr SCL    ;SCL=L
  pop ACC    ;Akku wieder herstellen    2Z
  pop 0    ;Register 0 wieder herstellen  2Z
  ret    ;        2Z
;*********************************************************

I2C_READ:    ;Lesen eines Bytes
  ;*************************************************
  ; Aufruf:
  ; SDA=X, SCL=L
  ; Wenn das F0-Flag=1 ist wird NACK gesendet.
  ; Notwendig beim letzten Byte vor Stopp
  ; Ende:
  ; SDA=H, SCL=L
  ; Byte wird im Akku zurueckgegeben
  ; keine Aenderung der Register
  ;*************************************************
      ;lcall vom Aufruf    2Z
  setb SDA  ;SDA freigeben
  push 0    ;Register 0 sichern    2Z
  mov R0,#8  ;Schleifenzähler (8Bit)    1Z
I2C_READ_LOOP:
  setb SCL  ;pos. Flanke
  nop    ;t_HIGH_min=4us      1Z
  nop    ;        1Z
I2C_READ_WAIT:
  jnb SCL,I2C_READ_WAIT ;Taktverlaengerung?  2Z
  mov C,SDA  ;Bit in Carry      1Z
  rlc A    ;aus Carry in Akku    1Z
  clr SCL    ;neg. Taktflanke
  nop    ;t_LOW_min=4.7us    1Z
  nop    ;        1Z
  nop    ;        1Z
  djnz R0,I2C_READ_LOOP  ;Alle 8 Bit?    2Z
  jbc F0,I2C_READ_ACK ;F0=1 => NACK (SDA=H, s.o.)
  clr SDA    ;ACK auf Bus      1Z
I2C_READ_ACK:
  setb SCL  ;pos. Flanke
  nop    ;t_HIGH_min=4us      1Z
  nop    ;        1Z
  pop 0    ;Register 0 wieder herstellen  2Z
  clr SCL    ;neg. Flanke
  setb SDA
  ret    ;        2Z
;*********************************************************

I2C_ENDE:




Brauchste die 8051 Header-Datei auch?

von 8051 MCU (Gast)


Lesenswert?

warum sicher Ihr vor I²C write den Akku ??
Wo ist der Teil mit dem setzen der LED ?

von 8051 MCU (Gast)


Lesenswert?

sorry LED gefunden

von Stefan (Gast)


Lesenswert?

Am P0 sind ja die LEDs

Also wenn der achte Schalter ein ist und dann mit den Tastern das Muster 
übertragen werden soll, ist mal die achte LED ein, mal nur halb so hell, 
mal aus - immer anders.

von 8051 MCU (Gast)


Lesenswert?

jbc F0,I2C_READ_ACK ;F0=1 => NACK (SDA=H, s.o.)

wo ist denn das F0 flag definiert ?? Und wie wird es gesetzt ?
Da sollte man suchen.

von Stefan (Gast)


Lesenswert?

Anders herum.
auf dem µC-Board sind auch 8 Taster. Wenn ich von hier auf eine 
Ausgabeplatine sende, klappt dies und es gibt keinen Fehler.

Dafür benutze ich folgenden Code:


#include "8051.h"
#include "I2C_ASM.h"
;
; 8574er Kennung: 0100xxxy
;
SEND000  .equ  01000000b  ;  ON  ON ON
SEND001  .equ  01000010b  ;  ON  ON off
SEND010  .equ  01000100b  ;  ON off ON
SEND100  .equ  01001000b  ;  off ON ON
SEND101  .equ  01001010b  ;  off ON off
;
READ000 .equ  01000001b  ;  ON  ON ON
;
MAIN
LOOP
TASTEN
  jnb P3.2, UNDLOS  ; Taster KISS-Board
  jnb P3.3, UNDLOS  ; Taster 8574-Platine
  ljmp TASTEN
UNDLOS  lcall I2C_START
  nop
  nop
  nop
  nop
  mov A, #SEND000
  lcall I2C_WRITE
  nop
  nop
  nop
  mov A, P2
  lcall I2C_WRITE
  nop
  nop
  nop
  lcall I2C_STOPP
  mov P0, A
  ljmp LOOP

.end

von Stefan (Gast)


Lesenswert?

Kannst du mir einen Tipp geben wie ich das mit dem F0 mache?

von T-D1 Aufsichtsrat (Gast)


Lesenswert?

Mov F0,x  ??

Woher kommt das Bit für F0 ?
Über I²C werden 8 Bits eingelesen.
Wenn es das 8te Bit ist dann eben
Mov F0,A.7
nachdem alle 8 eigelesen wurden.
Man kann auch Mov F0,C schreiben. das letzte Bit bleibt ja im C.

von Stefan (Gast)


Lesenswert?

MAIN
LOOP
TASTEN
  jnb P3.2, UNDLOS  ; Taster KISS-Board
  jnb P3.3, UNDLOS  ; Taster 8574-Platine
  ljmp TASTEN

UNDLOS  lcall I2C_START

  mov A, #READ000
  lcall I2C_WRITE

  lcall I2C_READ

  lcall I2C_STOPP
  Mov F0,C               <-------------------------
  mov P0, A
  ljmp LOOP



So klappt es
Danke!

von Stefan (Gast)


Lesenswert?

liegt das also doch am Carry-Bit oder was heißt das für mich?

von Ralf (Gast)


Lesenswert?

F0 ist ein frei verwendbares Flag im PSW, wenn ich's richtig im Kopf 
habe.

Ralf

von Stephan H. (stephan-)


Lesenswert?

langsam....
Im I²C read Teil wollt ihr die Schleife mit Afrage des F0 beenden.
 jbc F0,I2C_READ_ACK ;F0=1 => NACK (SDA=H, s.o.)

Ihr "füttert" F0 aber nicht in der Schleife. !!
Ihr macht: I²C write, Read ohne F0 zu tangieren und dann stop.
Wie bitte wollt Ihr JBC F0 erfüllen ???
im I²C_read_Wait ???
Nicht am Symtom basteln !! Die Ursache finden !!

Ob im PSW oder sonstwo. Flags müssen gesetzt und gelöscht werden !!
Nur sehe ich nichts vom setzen !!

von Stephan H. (stephan-)


Lesenswert?

Ralf schrieb:
> F0 ist ein frei verwendbares Flag im PSW, wenn ich's richtig im Kopf
> habe.
>
> Ralf

Jepp, ist richtig. Trotzdem muss es gesetzt werden wenn man mit
JBC F0 arbeiten will.
Das heist ja nur Springe wenn F0 gesetzt nach xy und lösche F0.

von Stephan H. (stephan-)


Lesenswert?

Stefan schrieb:
> liegt das also doch am Carry-Bit oder was heißt das für mich?

Das heißt nur das Du F0 als Flag nie benutzt hast.
Du hast es gelesen, aber nie gesetzt !!
Ich hasse I²C wie die Pest und bin daher auch nicht fit damit.
Aber ich denke das Stoppbit sollte nach F0.
Also 8 bit +1 Soppbit lesen. Read Schleifeenzähler mit #9 laden.
Aber nur 8 Mal RLC A machen. Das letzte Bit im c nach F0 laden.
Dann weißt Du das alles gesendet wurde und sendest dann dein ACK.
Vermutlich...

von Stefan (Gast)


Lesenswert?

Muß ich dieses F0 überhaupt verwenden? Oder kann man das in der 
Header-Datei ändern, das dieses überhaupt nicht aufgerufen wird?

von Stephan (Gast)


Lesenswert?

Stefan schrieb:
> Muß ich dieses F0 überhaupt verwenden? Oder kann man das in der
> Header-Datei ändern, das dieses überhaupt nicht aufgerufen wird?

Wer soll das beantworten ? DU mußt wissen was Du willst.
Du mußt F0 nicht benutzen. Du kannst auch ein anderes Flag definieren.
Du kannst auch JB c,xy nehmen wenn im Carry Dein Stopbit ist und auf ein 
zusätzliches Flag ganz verzichten. Schau Dir andere Routinen im Web an.
Aber nicht einfach nur kopieren, und geht. Dabei lernt man nicht. Diese 
Fragen sollte eigentlich Dein PAP beantworten.

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.