Danke für die schnelle Antwort.
Ich weiß jetzt also, dass ich die HW SPI Pins wie ganz normale IOs benutzen kann. Aber wie aktiviere oder deaktiviere ich denn die HW SPI?
Bzw. welches Register ist dafür zuständig?
Werbung
Danke für die schnelle Antwort.
Ich weiß jetzt also, dass ich die HW SPI Pins wie ganz normale IOs benutzen kann. Aber wie aktiviere oder deaktiviere ich denn die HW SPI?
Bzw. welches Register ist dafür zuständig?
Nichts existiert durch sich allein!
![]()
Hi,
wie du die HW SPI aktivierst, bzw deakivierst steht im Datenblatt. Ab Seite 132 geht es allgemein mit der SPI los, ab Seite 136 beginnt die "Register Description".
Zum aktivieren benutzt man das SPCR Register (S. 136) hier sind erklärt was die einzelnen Bits machen. Wir wollen die SPI im "Master Mode" (MSTR) betreiben und sie aktivieren (SPE). Eventuell musst du noch die SPI Clock Rate anpassen und die entsprechenden Pins müssen auf Ausgan bzw Eingang gestzt werden.
Als nächstes muss eine Routine zum Senden und Empfangen geschrieben werden. Dazu muss als erstes CHip Select aktiviert werden, danach werden die Daten in das Datenregister SPDR (S. 138 ) geschrieben. Die SPI beginnt sofort mit dem Übertragen, man muss lediglich darauf warten, dass die Schnittstelle fertig wird. Das kann man in dem SPSR (S. 138 ) Register feststellen mit dem SPIF Bit.Code:DDRB |= (1<<PB7) | (1<<PB5) | (1<<PB4); PORTB |= (1<<PB4); SPCR = (1<<SPE) | (1<<MSTR);
Hoffe das war verstädnlich viele GrüßeCode:PORTB &=~ (1<<PB4) //Chip select auf low SPDR = data; while(!(SPSR & (1<<SPIF)); PORTB |= (1<<PB4); return SPDR;
KR-500
So Ich hab es jetzt nach einer Pause endlich geschafft die Funkmodule zum funken zu bringen.![]()
Dabei benutze ich eine abgeänderte Software von Benedikt K. http://www.mikrocontroller.net/topic/67273
Leider hat das ganze keine hohe Effektivität. (um die 10%)Code:#include <avr/io.h>#include <avr/interrupt.h> #include "rfm12.h" #define F_CPU 1000000UL #include <util/delay.h> #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif #define IRQ_Port PORTD #define IRQ_Pin PIND #define IRQ_DDR DDRD #define IRQ 2 #define IRQ_Output() IRQ_DDR |= (1<<IRQ) #define IRQ_Input() IRQ_DDR&=~ (1<<IRQ) #define IRQ_High() IRQ_Port|= (1<<IRQ) #define IRQ_Low() IRQ_Port&=~(1<<IRQ) #define IRQ_Wait_Low() while(IRQ_Pin&(1<<IRQ)) #define RF_PORT PORTB #define RF_DDR DDRB #define RF_PIN PINB #define SDI 5 #define SCK 7 #define CS 4 #define SDO 6 void _delay_s(int s) { for (unsigned char i=0; i<s*100; i++) _delay_ms(10); } unsigned short rf12_trans(unsigned short wert) { unsigned short werti=0; unsigned char i; cbi(RF_PORT, CS); for (i=0; i<16; i++) { if (wert&32768) sbi(RF_PORT, SDI); else cbi(RF_PORT, SDI); werti<<=1; if (RF_PIN&(1<<SDO)) werti|=1; sbi(RF_PORT, SCK); wert<<=1; _delay_us(0.3); cbi(RF_PORT, SCK); } sbi(RF_PORT, CS); return werti; } void rf12_init(void) { RF_DDR=(1<<SDI)|(1<<SCK)|(1<<CS); RF_PORT=(1<<CS); IRQ_Input(); for (unsigned char i=0; i<10; i++) _delay_ms(10); // wait until POR done rf12_trans(0xC0E0); // AVR CLK: 10MHz rf12_trans(0x80D7); // Enable FIFO rf12_trans(0xC2AB); // Data Filter: internal rf12_trans(0xCA81); // Set FIFO mode rf12_trans(0xE000); // disable wakeuptimer rf12_trans(0xC800); // disable low duty cycle rf12_trans(0xC4F7); // AFC settings: autotuning: -10kHz...+7,5kHz } void rf12_ready(void) { cbi(RF_PORT, CS); while (!(RF_PIN&(1<<SDO))); // wait until FIFO ready } void rf12_txdata(unsigned char data) { rf12_trans(0x8238); // TX on rf12_ready(); rf12_trans(0xB8AA); rf12_ready(); rf12_trans(0xB8AA); rf12_ready(); rf12_trans(0xB8AA); rf12_ready(); rf12_trans(0xB82D); rf12_ready(); rf12_trans(0xB8D4); rf12_ready(); rf12_trans(0xB800|(data)); rf12_ready(); rf12_trans(0x8208); // TX off } char rf12_rxdata(void) { unsigned char data; rf12_trans(0x82C8); // RX on rf12_trans(0xCA81); // set FIFO mode rf12_trans(0xCA83); // enable FIFO rf12_ready(); data=rf12_trans(0xB000); rf12_trans(0x8208); // RX off return data; }
Deswegen wollte ich fragen, was ich machen kann um die Genauigkeit zu verbessern?
Dafür spielt ja wahrscheinlich die Funktion rf12_ready() eine Rolle und auch diese
"Dummy Bytes".
Wie genau funktioniert das eigentlich?
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB82D);
rf12_ready();
rf12_trans(0xB8D4);
Nichts existiert durch sich allein!
![]()
Vermutlich muss am Empfänger etwas an der Frequenz (Stichwort: AFC) optimiert werden. Und das sind keine Dummy-Bytes sondern Kommandos. Wie wäre es, wenn du dich Mal mit dem Datenblatt des RF12 auseinander setzt?
mfG
Markus
Tiny ASURO Library: Thread und sf.net Seite
Das ist der Link zu einem gut erklärten Datenblatt.
http://www.mikrocontroller.net/articles/RFM12#Senderegister_schreiben_.28TX_Register_Write _B8xx.29
Zum Thema Senderegister steht da:
- Senden von mehr oder weniger Takteinlauf-Bytes (viele Flankenwechsel, möglichst gleich viele 0-Bits und 1-Bits, etwa 0xAA, 0x55, 0xCC usw.
- Senden des Synchronmusters
- Senden der Daten
Natürlich sind0xB8xx Kommandos, aber es bedeutet, dass xx in den Sender geschrieben wird.
Ich wollte eigentlich nur wissen, wie der Empfänger weiß, dass er Daten im FIFO hat und was 0xB8AA, 0xB82D und 0xB8D4 bewirken bzw. warum sie nicht gesendet werden.
In dem Datenblatt steht übrigens auch :ein Dummy-Byte (typischerweise 0xAA)
Also wird dieses 0/1 Bit wohl doch als Dummy verwendet.
Nichts existiert durch sich allein!
![]()
Das ist kein Datenblatt. Das Datenblatt gibt es beim Hersteller, in englischer Sprache formuliert, deutlich Umfangreicher und auch nicht ganz fehlerfrei![]()
Mit 0xB8 wird der Sende-Fifo adressiert, das zweite Byte sind die zu schreibenden Daten. Zur Taktsynchronisation benötigen die RF-Chips ein geeignetes Bitmuster, hier 0xAA (1010...) das hat aber nichts mit Dummy zu tun. Der Beginn eines Datenpaketes wird dann durch das Synchronmuster signalisiert, dieses ist 0x2DD4. Wenn der Receiver dieses Muster erkennt, beginnt er empfangene Daten im Fifo zu speichern. (Mit al=1) Das Synchronmuster wird dabei, wenn ich mich richtig erinnere, verschluckt.
Das Dummy-Byte zum Schluss dient nur dazu, auf Senderseite nach den Nutzdaten den Sender rechtzeitig abschalten zu können. Wenn das letzte Datenbyte gesendet wurde, ist ein Byte im Fifo frei, der RFM12 wackelt dann nochmal an der Leitung um neue Daten anzufordern. Genau an dieser Stelle kann der Sender dann deaktiviert werden. Mit dem RGUR-Interrupt geht das auch ohne Dummy-Byte.
mfG
Markus
Tiny ASURO Library: Thread und sf.net Seite
Danke für die Erklärung. War hilfreich.
Ich habe noch mal unter IRQ nachgeschaut, weil ich vorher vergeblich versucht hatte den Interrupt von dort zu beziehen. Ich glaube der Code ist immer an der Stelle hängengeblieben wo er warten sollte bis das RFM12 bereit ist.
Jedenfalls steht dort, dass man 0xCAF3 zur Konfiguration des FIFOs benutzen soll um das Problem zu beheben. Das würde ja bedeuten, dass ein Interrupt erst ausgelöst wird, wenn der FIFO komplett voll ist (15 bit) oder? Bei 0xCA83 wird der Interrupt ja schon bei 8 bit ausgelöst also
der Hälfte an Speicherplatz.
Ich kann mir nur nicht erklären, warum das eine Fehlerursache sein sollte.
Nichts existiert durch sich allein!
![]()
Lesezeichen