PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 74HC595 bzw. SPI Problem



Snaper
22.11.2010, 20:35
Hallo zusammen,

versuche schon den ganzen Tag erfolglos mein 74HC595 vernünftig anzusteuern. Das Problem ist, dass es zwar mit dem veränderten Pseudocode aus dem rn-wissen Tutorial funktioniert aber mir das etwas sehr spektakulär aussah und so habe ich versucht nach bestem Wissen selber etwas hinzubekommen aber so richtig was ankommen tut nichts. Vielleicht kann ja mal einer drüber schauen und Tipps geben

spi.h


#ifndef SPIF
#define SPIF 7
#endif

unsigned char spi(unsigned char data)
{
SPDR=data;
while ((SPSR & (1<<SPIF))==0);
return SPDR;
}


main.c


#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
#define F_CPU 16000000UL /* Quarz mit 3.6864 Mhz */
#endif


#include <avr\io.h>
#include <util\delay.h>
#include "spi.h"


#define DD_MOSI PINB5

#define DD_SCK PINB7

#define DDR_SPI PORTB

void SPI_MasterInit(void)

{

// Set MOSI and SCK output, all others input

DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);

// Enable SPI, Master, set clock rate fck/16

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);

}



int main(void) {

SPI_MasterInit();


while (1)
{
PORTB |= (1<<PB4);
// Place your code here
spi(0xff);
_delay_ms(2000);
spi(0);
_delay_ms(2000);
PORTB &= ~(1<<PB4);

};


}


Benutze einen atmega32 und ja ich weiss alles etwas wirsch aber wäre trotzdem über Hilfe dankbar.

Gruß Snaper[/code]

Besserwessi
22.11.2010, 21:08
Die Definition von DDR_SPI ist fasch.
Das ist der erste Fehler der mir auffiel.

Snaper
22.11.2010, 21:17
Beim ATMega32 ist doch MOSI und SCK an PORTB also was ist daran falsch? Oder was meintest du ? :)

Besserwessi
22.11.2010, 22:46
Mit DDR_SPI sollte wohl auch das Datenrichtungsregister gemeinst sein, nicht der Port selber. Da müßte also schon DDRB nicht PORTB stehen.

Snaper
24.11.2010, 21:53
Also es sieht wie folgt aus. Wenn ich einen 74HC595 dran habe dann
funktioniert es jedoch nicht mehr wenn ich 2 kaskadierte dran habe...

Bevor die Frage kommt was icht genau funktioniert möchte ich
diese natürlich vorher klären. ;) Und zwar kommt mehr oder weniger an
den Ports nur "Mist" an. Wenn ich z.b. serpa[0] = 0xff; serpa[1] = 0xff;
schreibe dann sollten ja alle Ports durchschalten aber es sind nur
vereinzelt LEDs an bzw werden nur einzelne Ports durchgeschaltet.
Atmega32 @16Mhz wird genutzt. Für Hilfe wäre ich sehr dankbar.

Folgenden Code nehme ich dazu:
serpa.h


/* SERiell nach PArallel (serpa) im SPI-Protokoll */
#ifndef _SERPA_H_
#define _SERPA_H_

/* 4 Bytes (32 Ports) */
#define SERPA_SIZE 2
/* Das muss auf 1 sein, wenn man nur ein Schieberegister benutzt ... das wir dauch bei dem serp-- und so benutzt.*/

extern unsigned char serpa[];
extern void serpa_out (void);
extern void serpa_init (void);

#endif /* _SERPA_H_ */

//SERPA.h ende ------------------------


schiebe.c


#ifndef F_CPU
#define F_CPU 16000000UL
#endif

// SERiell nach PArallel (serpa) mit Hardware-Unterstuetzung
#include <avr/io.h>
#include "serpa.h"
#include <util\delay.h>

unsigned char serpa[SERPA_SIZE];
unsigned char maske(unsigned char input);

// Array fuer die Daten

void serpa_init (void)
{

DDRB=0xff;
PORTB |= (1<<PB4);

// !!! SS muss OUT sein, damit SPI nicht in Slave-Mode wechselt !!!
// entfaellt, falls PORT_RCK = PORT_SS

// SPI als Master
// High-Bits zuerst
// SCK ist HIGH wenn inaktiv
SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);

// pullup an MISO vermeidet Floaten
PORTB |=(1<<PB6);

// maximale Geschwindigkeit: F_CPU / 2
SPSR |= (1 << SPI2X);
}

void serpa_out (void)
{

unsigned char anz = SERPA_SIZE;
unsigned char* serp = serpa+SERPA_SIZE;

do
{
unsigned char data = *--serp;

// SPDR schreiben startet Uebertragung
SPDR = data;

// warten auf Ende der Uebertragung für dieses Byte
while (!(SPSR & (1 << SPIF)));

// clear SPIF durch Lesen von SPDR
SPDR;
}
while (--anz > 0);


// Strobe an RCK bringt die Daten von den Schieberegistern in die Latches
PORTB &=~ (1<<PB4);
PORTB |= (1<<PB4);
}

int main (void)
{
serpa_init();
while(1)
{


serpa[0] = 0xff;
serpa[1] = 0xff;
serpa_out();
}
}

unsigned char maske(unsigned char input)
{
return 0xFF ^ input;
}

Snaper
25.11.2010, 13:23
So langsam schließe ich einen Softwarefehler aus also das Problem ist, dass die Nullen nahezu "verschluckt" werden. Wenn ich auf beide 0xff schreibe, dann gehen alle an aber sobald ich eine Null drin habe geht es den Bach runter und es kommen ziemlich "wilde" Zustände zum vorschein. Woran könnte dies liegen?