Hallo Daniel,
dann mach ich mal ne kleine Zusammenfassung des aktuellen Werkes ...
Code:
.include "m32def.inc"
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
; Die Definitionen müssen an den jeweiligen AVR angepasst werden
.equ F_CPU = 4000000
.equ BAUD = 9600
.equ SCHIEBE_DDR = DDRB
.equ SCHIEBE_PORT = PORTB
.equ RCK = PB4 ; SS
.equ SCK = PB7 ; SCK
.equ SIN = PB5 ; MOSI
.equ PL = PB3
.equ CLK = PB7 ; SCK
.equ DIN = PB6 ; MISO
;Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1)))
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler
.error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
.dseg
.org 0x60
Daten: .byte 2 ; Speicherplatz für Eingangsdaten
;-----------------------------------------------------------------------------
;
; Programmsegment im FLASH
;
;-----------------------------------------------------------------------------
.cseg
ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp1
ldi temp1, HIGH(RAMEND)
out SPH, temp1
; CLK und PL als Ausgänge schalten
ldi temp1,(1<<CLK) | (1<<PL)
out SCHIEBE_DDR,temp1
; SCK, MOSI, SS als Ausgänge schalten
;
in temp1, SCHIEBE_DDR
ori temp1, (1<<SIN) | (1<<SCK) | (1<<RCK)
out SCHIEBE_DDR,temp1
receive_loop:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;EINGABE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SPI Modul konfigurieren
;
ldi temp1, 0b01011000
out SPCR, temp1 ; keine Interrupts, MSB first, Master
; CPOL = 1, CPHA =0
; SCK Takt = 1/2 XTAL
ldi temp1,1
out SPSR,temp1 ; double speed aktivieren
out SPDR,temp1 ; Dummy Daten, um SPIF zu setzen
;-----------------------------------------------------------------------------
; Zwei Bytes einlesen
ldi ZL,low(Daten)
ldi ZH,high(Daten)
ldi temp1,2
rcall schiebe_eingang
;-----------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;Verarbeitung;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;Ausgabe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ldi temp1, (1<<SPE) | (1<<MSTR)
out SPCR, temp1 ; keine Interrupts, MSB first, Master
; CPOL = 0, CPHA =0
; SCK Takt = 1/2 XTAL
ldi temp1, (1<<SPI2X)
out SPSR, temp1 ; double speed aktivieren
out SPDR, temp1 ; Dummy Daten, um SPIF zu setzen
ldi temp1, ZL
rcall schiebe
rcall schiebeout
rjmp receive_loop
;
; Die Daten im Schieberegister in das Ausgaberegister übernehmen
;
; Dazu am RCK Eingang am Schieberegister einen 0-1-0 Puls erzeugen
;
SchiebeOut:
sbis SPSR, SPIF ; prüfe ob eine alte Übertragung beendet ist
rjmp SchiebeOut
sbi SCHIEBE_PORT, RCK
cbi SCHIEBE_PORT, RCK
ret
;-----------------------------------------------------------------------------
;
; 8 Bits aus temp1 an das Schieberegister ausgeben
;
Schiebe:
sbis SPSR, SPIF ; prüfe ob eine alte Übertragung beendet ist
rjmp Schiebe
out SPDR, Ausgang ; Daten ins SPI Modul schreiben, Übertragung beginnt automatisch
ret
int_rxc:
Ruck:
rjmp receive_loop
;-----------------------------------------------------------------------------
;
; N Bytes seriell einlesen
;
; temp1 : N, Anzahl der Bytes
; Z : Zeiger auf einen Datenbereich im SRAM
;-----------------------------------------------------------------------------
schiebe_eingang:
push temp2 ; Register sichern
; CLK ist im Ruhezustand schon auf HIGH, CPOL=1
cbi schiebe_port, pl ; Daten parallel laden
sbi schiebe_port, pl
schiebe_eingang_1:
sbis SPSR,7 ; prüfe ob eine alte Übertragung beendet ist
rjmp schiebe_eingang_1
schiebe_eingang_byte_schleife:
out SPDR,temp1 ; beliebige Daten ins SPI Modul schreiben
; um die Übertragung zu starten
schiebe_eingang_2:
sbis SPSR,7 ; auf das Ende der Übertragung warten
rjmp schiebe_eingang_2
in temp2, spdr ; Daten lesen
st z+,temp2 ; Datenbyte speichern
dec temp1 ; Anzahl Bytes um eins verringern
brne schiebe_eingang_byte_schleife ; wenn noch mehr Bytes zu lesen sind
pop temp2
ret
Si sieht also anscheinend die aktuelle Situation aus ...
Ich hab mir das mal wegen der Übersicht ausgedruckt. Mal sehen was ich so finde ...
Heißt aber nicht das nur ich nach dem Fehler will. Man kann ja parallel arbeiten
EDIT: ... Hmmm ... Hardware-SPI ... hab ich noch nie benutzt ... müßte ich erstmal mit nem Datenblatt daneben genauer ansehen. Das wird wohl heute zeitlich nicht mehr ganz passen
... Also etwas Geduld ... Ich muß wegen fehlendem Hardwareaufbau auch alles im Kopf und auf Papier durchspielen. Na mal sehen ...
EDIT2: Also mal die Basics zuerst ... Der Code ist recht gut zu lesen. Rech sauber programmiert. Aber nach meinem Geschmack zu wenig Bemerkungen. Aber über Geschmack kann man ja streiten
- Also der SPI läuft im Master-Mode.
- Der Takt läuft mit halbem CPU-Takt. Bei deinem 4MHz Quarz also mit 2MHz.
- Es wird "MSB first" gearbeitet. Also wird zuerst das Bit 7 ausgegeben oder gesampelt.
- SCK ist im Idle-Zustand auf High
- MISO ist Input (bei Masterbetrieb)
- MOSI ist Output (bei Masterbetrieb und DDRB.5 = 1)
- Bei der ersten Flanke (die fallende Flanke) wird MISO in das SPDR gesampelt
- Bei der zweiten Flanke (die steigende Flanke) wird der Datenwert am MOSI geändert
- Der Datenwert am MOSI ist also bei der ersten fallenden Flanke gültig.
- der 74595 muß also mit der fallenden Flanke das anliegende Bit übernehmen
- der 74165 muß mit der steigenden Flanke das nächste Bit anlegen
soviel erstmal als erste Analyse der Abläufe an den ICs und am SPI-Bus.
=== 74595 Ser-In Par-Out ===
- Pin 10 (/SCL oder /MR) ist auf High , also kein Masterreset
- Pin 13 (G oder /OE) !!! muss !!! auf GND damit die Daten an den Ausgängen erscheinen => ändern !!!
- Pin 11 (SCK oder SH_CP) übernimmt mit steigender Flanke die Daten von Pin 14 (Ser oder DS) ins Schieberegister
- Pin 12 (RCK oder ST_CP) übergibt mit steigender Flanke die Daten vom Schieberegister ins Ausgangslatch
==> paßt bis auf Pin 13 soweit
=== 74165 Par-In Ser-Out ===
- Pin 15 (INH oder /CE) ist auf Low und damit der Baustein aktiv
- Pin 2 (CLK oder CP) übergibt mit steigender Flanke das nächste Bit des Schieberegisters an Pin 9 (QH)
- Pin 1 (LD oder /PL) übernimmt mit Lowpegel die Daten der Eingänge ins Schieberegister. Also High im Schiebebetrieb!
==> sollte auch soweit passen
EDIT3 : Also irgendwie ... warum nimmst du bei Eingabe und Ausgabe zwei verschiedene Initialisierungen ? (CPOL)
Wenn es damit läuft dann kann es evtl auch nur wegen Durchlaufzeiten durch die IC-Gatter laufen. Also irgendwo ein paar Nanosekunden Luft (so auf letzter Rille) ... Das muß ich mir mal genauer ansehen ... heute wird das nix mehr. Schon über ne Stunde am analysieren und das Programm hab ich noch nicht voll in der Logik durchschaut. Ich glaube aber das du es evtl zu kompliziert machst ...
EDIT4 : noch ne blöde Frage. Hast du die Probleme auch ohne den Programmer dran ? Dann könnte es sein das er dir den Pegel vom IC6 über den 10k am MISO kaputt macht.
Gruß
Dino