Forum: Mikrocontroller und Digitale Elektronik Hat jemand für den ATtiny44 eine funktionierende USI to SPI Routine?


von H. G. (ledi)


Lesenswert?

Da ich einen Funkchip über SPI ansteuern muss und mein ATtiny44 nur USI 
kann, wäre ich über eine Routine in C oder entsprechende Hinweise sehr 
dankbar.

von spess53 (Gast)


Lesenswert?

Hi

Datenblatt S.120. Sollte recht einfach nach C zu übersetzen sein.

MfG Spess

von Peter D. (peda)


Lesenswert?

Niemand zwingt Dich, das USI zu nehmen.
Nimm ne ganz einfache SW-SPI und gut is.


Peter

von H. G. (ledi)


Lesenswert?

OK, aber hab ich noch nie gemacht.
Hast du ein gutes Beispiel?

von spess53 (Gast)


Lesenswert?

Hi

>OK, aber hab ich noch nie gemacht.
>Hast du ein gutes Beispiel?

Das ist auf dem Niveau: 2 LEDs blinken lassen. Wenn es schon daran 
hapert, wie willst du dann einen 'Funkchip' ansteuern?

MfG Spess

von H. G. (ledi)


Lesenswert?

spess53 schrieb:
> Hi

> Das ist auf dem Niveau: 2 LEDs blinken lassen. Wenn es schon daran
> hapert, wie willst du dann einen 'Funkchip' ansteuern?

Was ist falsch daran, nach einem Beispiel zu fragen, wenn ich das noch 
nie gemacht habe? Und der Funkchip der funktioniert bereits, aber eben 
über die SPI.

von Floh (Gast)


Lesenswert?

Heimo G. schrieb:
> Hast du ein gutes Beispiel?

Nur senden:

Zähler = 8

Schleife:
  Mosi = oberstes Bit im Datenbyte
  Sck = high
  kurz warten
  Sck = low
  Datenbyte einmal links schieben
  Zähler dekrementieren,
wenn Zähler != 0, wieder die Schleife

Die Realisierung in Code überlass ich dir.
:-)

von spess53 (Gast)


Lesenswert?

Hi

>Die Realisierung in Code überlass ich dir.
>:-)

Das ist aber nicht Copy&Paste-Fähig.

MfG Spess

von Floh (Gast)


Lesenswert?

spess53 schrieb:
> Das ist aber nicht Copy&Paste-Fähig.

Dafür müsste er ja auch seine Programmiersprache angeben ^^

von spess53 (Gast)


Lesenswert?

Hi

>Dafür müsste er ja auch seine Programmiersprache angeben ^^

Hat er doch:

>...wäre ich über eine Routine in C oder entsprechende Hinweise sehr
>dankbar.

MfG Spess

von Peter D. (peda)


Lesenswert?

1
#include <avr\io.h>
2
3
4
struct bits {
5
  uint8_t b0:1;
6
  uint8_t b1:1;
7
  uint8_t b2:1;
8
  uint8_t b3:1;
9
  uint8_t b4:1;
10
  uint8_t b5:1;
11
  uint8_t b6:1;
12
  uint8_t b7:1;
13
} __attribute__((__packed__));
14
15
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
16
17
18
#define SPI_CLK         SBIT( PORTB, 0 )        // clock
19
#define SPI_CLK_DDR     SBIT( DDRB,  0 )
20
#define SPI_MISO_PIN    SBIT( PINB,  2 )
21
#define HC165_LD        SBIT( PORTB, 3 )
22
#define HC165_LD_DDR    SBIT( DDRB,  3 )
23
#define SPI_MOSI        SBIT( PORTB, 1 )
24
25
26
uint8_t spi_io( uint8_t val )
27
{
28
  uint8_t i;
29
30
  for( i = 8; i; i-- ){
31
    SPI_MOSI = 0;
32
    if( val & 0x80 )
33
      SPI_MOSI = 1;
34
    val <<= 1;
35
    if( SPI_MISO_PIN )
36
      val += 1;
37
    SPI_CLK = 0;
38
    SPI_CLK = 1;
39
  }
40
  return val;
41
}


Peter

von Floh (Gast)


Lesenswert?

Peter Dannegger schrieb:
> if( SPI_MISO_PIN )
>       val += 1;

sollte man das Einlesen nicht während der Clockperiode machen?
:-)

von Peter D. (peda)


Lesenswert?

Floh schrieb:
> sollte man das Einlesen nicht während der Clockperiode machen?
> :-)

Man sollte es so machen, wie es im Datenblatt des zu kontrollierenden 
Chips steht (den wir aber nicht kennen).

Mein Bespiel liest einen 74HC165 ein.


Peter

von H. G. (ledi)


Lesenswert?

Hallo Peter!

Ich habe nun doch eine USI-SPI Routine geschrieben.

Soweit ich das überprüfen konnte, sollte es funktionieren.
Leider kann ich aber am DO (Pin PA5) kein Signal messen.

Was ist falsch?


Hier der Code:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
void SPI_init(void)
7
{
8
  DDRA  |=  (1<<PA4)|(1<<PA5);   //Output:   PA4=USCK, PA5=DO
9
  DDRB  |=  (1<<PB1);      //Output:   PB1=CS
10
  DDRA  &=  !(1<<PA6);      //Input:   PA6=DI
11
  PORTA  |=  (1<<PA6);      //int. Pull-up an PA6 aktivieren
12
  DDRA   |=   (1<<PA7);      //LED auf Ausgang
13
14
  USICR   =   (1<<USIWM0) | (1<<USICLK)| (1<<USITC)| (1<<USICS1);
15
}
16
17
void SPI_transfer(int data)
18
{
19
    PORTB  &=  !(1<<PB1);    //CS = 0
20
    USIDR = data;        //Daten in Data Register laden
21
    USISR   |=  (1<<USIOIF);  //Überlaufflag löschen  
22
23
    while (!(USISR & (1<<USIOIF)))  //solange kein Timerüberlauf...
24
    {
25
      USICR  |=  (1<<USITC);    //Toggle clk
26
      USICR  |=  (1<<USITC);
27
    }
28
    PORTB  |=  (1<<PB1);    //CS = 1
29
}
30
31
int main (void)
32
{
33
  SPI_init();
34
  sei();
35
  while(1)
36
  {
37
    SPI_transfer(0xAF);
38
    PORTA |= (1<<PA7);  // Led on
39
    _delay_ms(1000);
40
    PORTA &= !(1<<PA7);  // Led off
41
    _delay_ms(1000);
42
  }
43
}

von H. G. (ledi)


Lesenswert?

Funktioniert schon! :-)

Der "Fehler" war bei der Initialisierung des Input-Pins (PA6):

DDRA  &=  !(1<<PA6);

habe ich auf
DDRA  &=  ~(1<<PA6);
ausgebessert.

Warum nimmt das AVR-Studio das ! als Negation hier nicht an?

von Karl H. (kbuchegg)


Lesenswert?

Heimo G. schrieb:

> Warum nimmt das AVR-Studio das ! als Negation hier nicht an?

1) weil das eine C-Sache ist
2) weil ! die logische Negierung ist und nicht die bitweise

   Am Beispiel von 5 (0b00000101)
   !5     ergibt 0, weil 5 nicht 0 ist ( 5 ist logisch TRUE und
          dessen Negierung ist logisch FALSE)
   ~5     ergibt 0b11111010, weil jedes Bit umgedreht wird

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.