Hallo,
ich bekomme die USI im 3-wire-mode bei einem ATtiny2313 einfach nicht zu
laufen. Auf Interrupts möchte ich hierbei verzichten, da sie eventuell
in andere Programmteile "reinhauen" könnten, daher habe ich folgende
einfache Implementierung zum Testen gewählt (nach ASM-Beispiel aus
Datasheet):
1
#include<avr/io.h>
2
3
#define USI_DDR DDRB
4
#define USI_PORT PORTB
5
#define USI_PIN PINB
6
#define USI_SS 4
7
#define USI_DO 5
8
#define USI_DI 6
9
#define USI_SCK 7
10
11
voidwait(void);
12
13
intmain(void)
14
{
15
unsignedinti;
16
17
//Initialization
18
USI_DDR|=((1<<USI_DO)|(1<<USI_SCK)|(1<<USI_SS));
19
USI_DDR&=~(1<<USI_DI);
20
USI_PORT|=(1<<USI_SS);
21
22
while(1)
23
{
24
USI_PORT&=~(1<<USI_SS);//start frame by pulling SS low
USI_PORT|=(1<<USI_SS);//end frame by pulling CS high
37
wait();
38
}
39
40
return(0);
41
}
42
voidwait(void)
43
{
44
volatileunsignedlongl=50000;
45
46
while(l>0)l--;
47
}
Der Taktpin toggelt und das CS-Signal wird auch ordentlich generiert.
Leider bleibt der Datenpin konstant "low"?! Was ist los, habe ich
Tomaten auf den Augen?!
Gruß Karl
Vielen Dank Jörg,
Dein Code funktioniert aber leider auch nicht. Die USI-Optionen
irritieren mich auch, ich habe schon folgendes probiert:
1) USICS1 und USICS0 sind gelöscht / USICLK und USITC generieren Takt
Meiner Meinung nach ist das die software clock strobe Variante. Das
gleiche Problem, Daten bleiben konstant low!
2) USICS0 oder USICS1 gesetzt / USICLK und USITC generieren Takt
Ich habe mehrere Codebeispiele (Datenblatt+Forum) gefunden, in denen
unterschiedlich USICS0 oder USICS1 gesetzt werden. Das gleiche Problem,
Daten bleiben konstant low!
3) USICS0 oder USICS1 gesetzt / USICLK oder USITC generieren Takt
Egal ob ich USICLK oder USITC setze, die Daten bleiben low?!
Wie Du also siehst, habe ich schon alle möglichen Kombinationen
ausprobiert und KEINE hat funktioniert?!
Viele Grüße
Karl
PS: Zwischenzeitlich habe ich den DO-Pin mal ohne USI per PORT auf
HIGH/LOW gezogen. Diese Funktionialität ist nicht kaputt... ;-)
Hallo,
in der Zwischenzeit habe ich mir eine komplette Software-SPI
geschrieben, dann bin ich auch flexibler mit den Pins und es
funktioniert wenigstens... ;-)
1
voidSPI_Init(void)
2
{
3
//Initialization
4
SPI_DDR|=((1<<SPI_DO)|(1<<SPI_SCK)|(1<<SPI_SS));
5
SPI_DDR&=~(1<<SPI_DI);
6
SPI_PORT|=(1<<SPI_SS);
7
}
8
9
unsignedintSPI_Transfer(unsignedintdata)
10
{
11
unsignedinti;
12
13
SPI_PORT&=~(1<<SPI_SS);//start frame by pulling SS low
Wenn Du mal in das Assemblerlisting schaust, wirst Du sehen, daß da ganz
schön viel Code erzeugt wird.
(1<<i) mag der Compiler nicht, da es dafür keinen Opcode gibt.
Auch macht es keinen Sinn, 16Bit Variablen zu verwenden, wenn man nur
8Bit braucht.
Wesentlich kürzer und schneller wirds daher so:
Hallo Peter,
danke für Deine Korrekturen.
Stimmt, mein Fehler "unsigned int" auf dem Atmel zu verwenden, da kommt
davon wenn man immer zwischen Controllern hin- und her schalten muss...
;-)
Peter Dannegger wrote:
> Wenn Du mal in das Assemblerlisting schaust, wirst Du sehen, daß da ganz> schön viel Code erzeugt wird.>> (1<<i) mag der Compiler nicht, da es dafür keinen Opcode gibt.>> Auch macht es keinen Sinn, 16Bit Variablen zu verwenden, wenn man nur> 8Bit braucht.>
Für das Schieben (1<<i) gibt es keinen Opcode? Ich hatte mir extra der
Übersichtlichkeit wegen die Schreibweise: PORT |= (1<<BIT); angewöhnt?!
Oder kann dies der Compiler optimieren, da ja BIT eine Konstante ist?
Gruß Karl
Karl W. wrote:
> Oder kann dies der Compiler optimieren, da ja BIT eine Konstante ist?
Richtig, das muss nicht der Prozessor machen, anders als 1 << i.
Hallo,
ich spiele grade schon eine Weile mit einem Attiny 45 und habe ein
ähnliches USI-Problem. Jörgs Code funktionierte bei mir auf Anhieb. Nun
kann ich damit auch ohen Probleme einen 74HC595 zum Ausgeben zwingen.
Mein Problem besteht darin, dass ich nicht weiss, wie ich die Clockphase
für einen 74HC165 ändere? Ich hab aus dem Datenblatt mal die Tabelle
rausgesucht, die denke ich die notwendigen Register beinhaltet und die
Funktion folgendermaßen implementiert:
1
staticuint8_tspi165(void)
2
{
3
USISR=_BV(USIOIF);
4
do{
5
USICR=_BV(USIWM0)|/* USIWM0=1, USIWM1=0 -> Three Wire Mode */
6
_BV(USICS1)|_BV(USICS0)|_BV(USICLK)|/* all 3 set -> Configure external clock, negative edge */
7
_BV(USITC);/* writing to the USITC strobe bit will directly clock the 4-bit counter */
8
}while((USISR&_BV(USIOIF))==0);
9
returnUSIDR;
10
}
Nun toggle ich den Latchpin und lasse die Funktion durchlaufen. Die
Daten werden nun auf dem 74HC595 geschrieben. Komischerweise bekomme ich
aber jedesmal 0xFF dort angezeigt -> Es scheint also nicht zu
funktionieren. Kann mir bitte jemand sagen warum nicht und was ich
anders machen sollte?
MfG sb
Hallo,
ich hab die Sache gelöst. Damit die Daten von den Eingängen in die
internen Register übernommen werden, musste der SCK-Pin auch High sein.
Es lag also am schalten des Latches...
LG sb
ich weiß, ich graber hier einen alten Artikel aus, aber ich hatte gerade
das selbe Problem.
@ Karl W.
bei dir sind DI und DO vertauscht, darum bekommst du auch keinen Output.
Leider wird bei der USI immer MOSI mit DI und MISO mit DO geshared, da
sind Verwechslungen ja schon fast vorprogrammiert, wenn man von den
größeren AVRs mit richtiger SPI Schnittstelle kommt ;-)