Userport: Shift-Register und SPI
Suche
Index
FAQ
Kontakt
Zurück

Eine kurze Einführung in die serielle Datenübertragung.

Grundlagen

SPI
Programmierung
TTL-Shift-Register
MCP23S017 Port-Expander
Quelltext für den MCP23S017 Port-Expander



Grundlagen

Bei der seriellen Datenübertragung wird ein Byte , Bit für Bit über eine Datenleitung übertragen. Üblicherweise wird zuerst D7 also das MSB und danach die restlichen Bit in Folge gesendet. Zur Koordination der klassischen Übertragung wird eine Takt-Leitung hinzu gezogen, die dem Empfänger signalisiert, wann ein Bit vom Port abgeholt werden kann.
CLOCK: HLHLHLHLHLHLHLHLH
DATEN: 1#1#1#1#1#1#1#1#
Bei jeder Low-Phase wird das Bit vom Empfänger (#) übernommen.



SPI

SPI heißt nicht mehr als Serial Peripheral Interface und beschreibt einen lockeren Standard zu seriellen Kommunikation. Hierbei werden Sender und Empfänger als Master und Slave verbunden. Der Master steuert die serielle Kommunikation über die Takt-Leitung (Clock).
Zudem wird eine SS-Leitung (select slave) hinzugezogen, damit der Master den jeweiligen Bus ansprechen kann. Dieser Bus kann über Adress-Kodierung mancher SPI-ICs bis zu 8 Slaves verwenden. Je nach Anwendung variieren die beschreibbaren Register der verwendbaren Slaves. Die Produkt-Palette reicht vom DAC, ADC, Port-Expander, EEPROM bis hin zu hoch integrierten Temperatur-Messmodulen. Hier gibt das Datenblatt des jeweiligen IC ausreichend Auskunft.



Programmierung

Die Programmierung ist denkbar einfach. Üblicherweise verwenden SPI-ICs eine SS-Leitung (select slave), mit der die Kommunikation per Low-Pegel gestartet wird. Diese Leitung bleibt solange Low bis der Transfer beendet wurde. Beim Lesen eines Registers bleibt die Leitung beim Schreiben der Anfrage und Lesen des Register-Wertes in diesem Zustand. Sobald die Leitung den High-Zustand einnimmt, ist der Slave nicht mehr aktiv.
Manche ICs verwenden zusätzlich drei Adressleitungen, mit denen gesamt 8 Slaves an einem /SS-Bus betrieben werden können. Die Bit-Werte werden üblicherweise mit dem MSB (most significant bit oder D7) zuerst gesendet. Oft sind die Default-Werte so eingestellt, dass bei der Low-Phase der Clock das angelegte Bit übernommen wird.



TTL Sift-Register


Bild


Mit einem TTL-Shift-Register lässt sich leicht ein 8-Bit-Port aus wenigen Leitungen bauen. CLR kann man auf High-Pegel legen und ansonsten Bit für Bit in den Chip clocken. Hierbei ist es ratsam mit dem MSB anzufangen, damit der Wert nicht gespiegelt am Ausgang anliegt.


MCP23S017 Port-Expander

Bild


Mit dem preisgünstigen MCP23S017 lassen sich leicht zwei 8-Bit oder ein 16-Bit-Port steuern. Im unteren Quelltext ist eine Variante für vier Portbits mit 6502-Assembler dokumentiert.



Quelltext für den MCP23S017 Port-Expander


 C64 (6502) SPI-Communication
;
; for MCP23S017 Port-Expander
;
; PB0 : SO
; PB1 : SI
; PB2 : Clock
; PB3 : CS0
;
; higher portbits for more cs, with decoder = much more cs
;
; [/] 12.07.2013 M.Sachse , http://www.cbmhardware.de
;
; Updates:
; 13.07.2013 + send_buf, minor changes
; 17.07.2013 + bugfixes, + chip MCP23S017 arrived and write transfer works now
; 20.07.2013 + poll_register
;---------------------------------------------------------
;
; send_byte : shifts and send byte
; send_buf  : sends buffer using send_byte
; poll_register : reads register value
;
;---------------------------------------------------------

!to "spi.prg",cbm


 ddr  = $dd03
 port = $dd01
 outbuf =   $fb
 bytecount= $fc
 inbuf =    $fd
 register=  $fa


*= $0800
!byte $00,$0c,$08,$0a,$00,$9e,$32,$30,$36,$33,$00,$00,$00,$00

*=$080f
          lda #%00001101     ; set direction register
          sta ddr
          and #%00001000     ; set cs0/ss to high: chip deselected
          sta port
          ldy #$00
          sty bytecount
          clc
          jsr send_buf       ; initialize ports
          jsr poll_register  ; get port-register
          rts


;----------------------------
; send_byte
;
;   x-reg: bit counter
;   y-reg: indirect buffer
;   carry: bit carrier
;
;----------------------------
send_byte:
          ldx #$00
          txa
-         lda #$00
          asl outbuf         ; shift left: [Carry<-msb...lsb]
          bcc +
; --- send high bit ---------
          ora #%00000101     ; set bit and clock
          sta port
          and #%11111011     ; clock to low
          sta port
          clc
;         sta $0400,x        ; Debug-Line
          inx
          cpx #$08
          bne -
          rts
; --- send low bit ----------
+         ora #%00000100     ; set null and clock
          sta port
          and #%11111011     ; clock to low
          sta port
;         sta $0400,x        ; Debug-Line
++        inx
          cpx #$08
          bne -
          rts


;----------------------------
; poll_byte
;
;   wbuf:  $40+r,register
;   carry: bit carrier
;
;   poll-sequence:
;   cs:low ; write "$40+r,register" ; poll register; cs:high
;
;
;----------------------------
poll_register:
          lda #$00
          tay
          sta port           ; flip to low: chip selected
-         lda wbuf,y
          sta outbuf
          jsr send_byte      ; init poll-sequence
          iny
          cpy #$02
          bne -
; --- get register-value ---------
          ldx #$00
          txa
-         clc
          ora #%00000100     ; set clock high
          sta port
          lda port
          and #%00000011     ; clock to low
          sta port
          and #%00000010     ; extract received bit
;         sta $0400,x        ; Debug-Line
          beq +              ; write "0"
          sec                ; or feed carry with "1"
+         rol inbuf          ; rotate msb..lsb<-carry
          inx
          cpx #$08
          bne -
          lda #%00001000     ; chip deselected
          sta port
          rts


wbuf: !by $41,$12            ; read portA

;----------------------------
; send_buf
;
;   y-reg: indirect buffer
;
;----------------------------
send_buf:
          lda #$00
          sta port           ; flip to low: chip selected
-         lda buf,y
          sta outbuf
          jsr send_byte
          inc bytecount
          lda bytecount
          cmp #$04           ; 4 bytes: $40 (+w),registers,value,value
          bne +
          ora #%00001000     ; flip to high: chip deselected
          sta port
          and #%00000000     ; count next 4 bytes
          sta bytecount
          sta port           ; flip to low: chip selected
+         iny
          cpy #$08           ; whole bytes to transfer
          bne -
          rts

buf: !by $40,$00,$ff,$ff,$40,$12,$ff,$ff





 

Letzte Änderung: 2019-01-03 18:16:34
  Rubrik:  C64
Rubriken-Übersicht
 212 Besucher online 

Valid XHTML 1.0 Transitional Valid CSS!