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.
Hi Datenblatt S.120. Sollte recht einfach nach C zu übersetzen sein. MfG Spess
Niemand zwingt Dich, das USI zu nehmen. Nimm ne ganz einfache SW-SPI und gut is. Peter
OK, aber hab ich noch nie gemacht. Hast du ein gutes Beispiel?
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
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.
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. :-)
Hi >Die Realisierung in Code überlass ich dir. >:-) Das ist aber nicht Copy&Paste-Fähig. MfG Spess
spess53 schrieb: > Das ist aber nicht Copy&Paste-Fähig. Dafür müsste er ja auch seine Programmiersprache angeben ^^
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
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
Peter Dannegger schrieb: > if( SPI_MISO_PIN ) > val += 1; sollte man das Einlesen nicht während der Clockperiode machen? :-)
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
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 | }
|
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.