Hi,
ich habe einen ATTiny2313 und versuche dort über USI ein Signal an
meinen Rechner zu schicken.
ich hatte im Internet Beispiele zu Ähnlichen µC's gefunden und habe so
folgendes Programm geschrieben.
Hab dort aber bereits in der Simulation das Problem, das ich das
USISR-Register nicht setzten kann. (Dieses benötige ich um den
Überlauffläg zu löschen.
Hier das von mir geschriebene Programm:
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
void SPI_init(void)
{
//Eigene Initialisierung WatchDog
MCUSR =0;
MCUCR = 0x80; //JTAG abschalten
MCUCR = 0x80;
DDRA |= (1<<PB7)|(1<<PB6); //Output: PB7=USCK, PB6=DO
DDRA &= ~(1<<PB5); //Input: PB5=DI
DDRA |= (1<<PD5); //LED auf Ausgang
USICR = (1<<USIWM0) | (1<<USICLK)|(1<<USITC)| (1<<USICS1);
// USIWM0 = 1: SPI-Betrieb mit DO, DI und USCK
// USICLK = 1, USITC = 1, USICS1 = 1: generiert den Taktimpuls für das
Schieberegister und
// den 4bit Timer. Der Takt wird am USCK-Pin (PA4) ausgegeben.
}
void SPI_transfer(int data)
{
USIDR = data; //Daten in Data Register laden
USISR = (1<<USIOIF); //Überlaufflag löschen
while (!(USISR & (1<<USIOIF))) //solange kein Timerüberlauf...
{
USICR |= (1<<USITC); //Toggle clk (2x)
USICR |= (1<<USITC);
}
}
int main (void)
{
SPI_init();
while(1)
{
SPI_transfer(0x41); // Daten (A) senden
PORTA |= (1<<PD5); // Led on
_delay_ms(100);
PORTA &= !(1<<PD5); // Led off
_delay_ms(100);
}
}
Hat jemand eine Idee wo der Fehler sein könnte?
Gruß
Anthony
Die Zeile
> USICR |= (1<<USITC);
funktioniert als XOR.
Das Problem das ich habe, ist das er in der Zeile
> USISR = (1<<USIOIF); //Überlaufflag löschen
den Wert für USIOIF nicht setzt. Das USISR Register bleibt komplett
leer.
Gibts es dafür eine Erklärung
> den Wert für USIOIF nicht setzt. Das USISR Register bleibt komplett> leer.
Das ist richtig so.
Das sind flags. Die werden von der Hardware gesetzt und müssen durch
schreiben einer 1 zurück gesetzt werden. Wenn du da eine 1 reinschreibst
wird das bit also zurück gesetzt!
Thor
OK, verständlich.
Aber dann würde die while-schleife nie beendet werden.
(Was bei mir auch der Fall ist)
Zudem habe ich diese Whileschleife mit genau den befehlen öfters im
Internet gesehen. Ist der Code dann so Falsch? Und wenn ja wie würde es
Richtig gehören?
Schonmal Danke
Anthony
Mhh, ich sehe grade, dass USITC auch eine flag ist. Das bedeutet, dass
das bit ebenfalls selbstständig zu 0 zurück kehrt. Das |= wirkt also
nicht als xor sondern schreibt einfach nur eine 1 in USITC, während es
sich selbst zurücksetzt.
Ich muss da nochmal drüber nachdenken. Ist schon zu spät um das jetzt
noch zu lösen. Bis morgen.
Thor
Hab schonmal einen großen Fehler gefunden.
Bei der Initialisierung sowie an ein paar anderen stellen, habe ich beim
übernehmen des Codes nicht alle
> PORTA in PORTB etc.
umgeändert.
Jedoch hat sich in der Simulation nichts geändert:
-> weiterhin das Problem, das er dort nicht aus der Whileschleife wieder
rauskommt.
Programmiere ich allerdings den µC mit dem Code:
-> die LED blinkt -> er scheint doch aus der Whileschleife raus zu
kommen.
Ich kann allerdings weder am Oszi noch am Rechner (verbunden über USB
TTL Serial Kabel) ein Signal erkennen. Lediglich ein Rauschen um den
Nullpunkt herrum.
Vieleich noch einen Idee?
Gruß
Anthony
> (1<<USICS1)
Bedeutet, trigger auf external positiv edge. Das ist richtig. Du
solltest aber auch noch USICLK setzen. UU wird sonst der counter nicht
imkrementiert.
Thor
Nein außer beim init brauchst du das nicht zu setzen. Aber warum
toggelst du eigentlich schon beim init USITC?
Äham, wo ich mir deine post grade noch mal so duch lese: Du hast
gemerkt, dass du einige PortA statt PortB stehen hast aber hast du auch
gemerkt, dass das auch für die DDRs gilt?
Thor
Ja das hatte ich auch gemerkt. Das hab ich alles ausgebessert.
Habs jetzt dazu gebracht, das ich das Signal am Oszi sehe, allerdings
kommt an meinem zweiten Mikrocontroller noch nichts an.
Ich glaube das der Fehler irgendwas damit zu tun hat das ich beide µCs
als Master programmiert habe.
Weißt du was ich genau Einstellen muss um einen als Slave zu
programmieren?
Reicht es wenn ich folgende Implementierung mache?:
> DDRA |= (1<<PB7)|(1<<PB6); //Output: PB7=USCK, PB6=DO> DDRA &= ~(1<<PB5); //Input: PB5=DI> DDRA |= (1<<PD5); //LED auf Ausgang> USICR = (1<<USIWM0)|(1<<USICS1);
Nochmal vielen Dank für die bisherige Hilfe
Gruß
Anthony
Du hast immer noch DDRA da stehen. Das macht mich etwas nervös.
Ansonsten musst du um beide µC zu verketten an deinem setup kaum etwas
verändern. Die DDRs von DO und DI bleiben gleich. Du musst aber
bedenken, dass DO und DI gekreuzt werden müssen. Auch das setting von
USICR bleibt gleich: external clock source. Nur das DDR von USCK muss
aus, weil nur der master die clock treibt.
Thor
OK, da war jetzt der Fehler ich hatte "USCK" noch als output
eingestellt.
>Hab jetzt aber ein Problem mit meinem Probeprogramm.
Ich hatte dieses so Programmiert das:
-der eine µC_1 "UART" Signale erhält und diese über "USI" wieder ausgibt
-der anderen µC_2 die ausgegebenen "USI" Signale erhält und diese über
"UART" wiederum ausgibt
Die beiden UART Schnittstellen sind am Rechner angeschlossen, sodass ich
von dort die Signale Senden und Empfangen kann.
>Jetzt habe ich folgendes Problem:
-Endet das zu Sendene Signal auf 0 ("B" ; 0x42 ; 0100 0010) kommt es
einwandfrei an
-Endet das zu Sendene SIgnal auf 1 ("A" ; 0x41 ; 0100 0001) kommt
irgendwas an
>FRAGE1:
Eine Idee woran das liegen könnte?
(Ich hatte dazu feststellen können, das der µC_2 ZWEI Byte rauschickt
obwohl er eigendlich nur EINEN Byte erhalten haben sollte)
>FRAGE2:
Da ich ja jetzt beim µC_2 die Clock (USCK) auf input gestellt habe
stellt sich mir dort jetzt die Frage:
-Wie kann der µC_2 der die Clock als Input hat Signale rauschicken ohne
selber die Clock zu erzeugen?
Gruß
Anthony
> Eine Idee woran das liegen könnte?> (Ich hatte dazu feststellen können, das der µC_2 ZWEI Byte> rauschickt obwohl er eigendlich nur EINEN Byte erhalten haben> sollte)
Uff, das war jetzt etwas kurz. Mit "irgendwas" meist du reproduzierbar
"irgendwas"?
> Da ich ja jetzt beim µC_2 die Clock (USCK) auf input gestellt> habe stellt sich mir dort jetzt die Frage:> -Wie kann der µC_2 der die Clock als Input hat Signale rauschicken> ohne selber die Clock zu erzeugen?
Du meinst SPI seitig. Das clocking des USI läuft bei master und slave
genau gleich. Beide holen sich die clock vom USCK pin rein. Nur muss
klar sein wer die clock erzeugt und das ist halt der master. Deshalb hat
der master das DDR auf und der slave zu.
Thor
>Uff, das war jetzt etwas kurz. Mit "irgendwas" meist du reproduzierbar>"irgendwas"?
Habs mir gerade nochmal genauer angeschaut:
Er scheint das Ganze Signal um EINE Stelle zu Verschieben und ein High
ans Ende zu hängen.
--> Aus ("A" ; 0x41 ; 0100 0001)
Wird ("ƒ" ; 0x83 ; X100 0001 1)
--> Aus ("C" ; 0x43 ; 0100 0011)
Wird ("‡" ; 0x87 ; X100 0011 1)
Eine Idee?
Also erstmal könntest du das setzen der DDRs beim µC2 noch zusammen
fassen. Die DDRs von PB5 und PB7 sind immerhin im selben Register.
Dein Problem könnte sein, dass du die Beendigung des Empfangs beim µC2
durch das bloße Prüfen auf Verschiedenheit von null beurteils. Leider
ist USIDR aber nicht gepuffert und es kann daher dazu kommen, dass deine
Warteschleife zu früh abbricht. Trigger am besten auf den counter
overflow. Der sagt dir zuverlässig, wann der shfit fertig ist.
Thor
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.