Hallo zusammen! Ich versuche einen AVR (TINY2313) über ei RFM12 senden zu lassen. Als Code verwende ich einen einfachen Sendecode aus einer RMF-Library. Die Beschaltung hab ich wie in den vielen Google-Ergebnissen vorgeschlagen vorgenommen ;-) Leider funktioniert das ganze nicht (es kommt nichts am Empfänger an). Nun bin ich auf Fehlersuche... Nun aber zu meiner konkreten Frage: es scheint keine Kommunikation zwischen AVR und RFM stattzufinden. Wenn ich das richtig verstanden habe werden die 3 Pins MISO, MOSI und SCK (bzw. SDO, SCI und SCK am RFM) zur Übertragung verwendet. Müsste man da was messen können? Mein Multimeter zeigt zumindest konstant 0V an allen 3 Pins an... "Muss dat so?" Oder liegt da schon der Hund begraben? Danke, Mirko
Ein Multimeter ist keine gute Möglichkeit die SPI Signale zu messen. Du brauchst ein Digitalspeicheroszilloskop oder einen Logic Analyzer. Aber als Anhaltspunkt zum testen könntest du natürlich per SPI einfach mal 0xFF dauerhaft senden und schauen ob du am MOSI Pin annähernd 3,3V/5V messen kannst. Falls das nicht der Fall ist, dann stimmt schon etwas mit deiner SPI Kommunikation nicht. Ciao, Rainer
OK, das klingt doch gut. Dann werd ich das mal so machen... Danke!
Sooo, leider hat das nicht hingehauen. Das mit dem dauerhaft senden scheint nicht möglich zu sein, da der Sendecode den ganzen Programmablauf blockiert. Es wird nichts gesendet, und das Programm steckt an der Stelle fest. Muss ich mir das wie einen Unfall auf der Autobahn vorstellen, der einen Stau verursacht? Der Code selber sollte eigentlich funktionieren, da ich ja nur ein Beispielprojekt aus dem Internet verwende... Könnte es an der Hardware, also der Verbindung zwischen den beiden Geräten liegen? Was passiert, wenn z.B. der Gesprächspartner vom AVR falsch angeschlossen oder sogar tot ist? (in diesem Fall das RFM12 Modul)
Mirko schrieb: > Könnte es an der Hardware, also der Verbindung zwischen den beiden > Geräten liegen? > Was passiert, wenn z.B. der Gesprächspartner vom AVR falsch > angeschlossen oder sogar tot ist? (in diesem Fall das RFM12 Modul) Es könnte sein, das dein Code auf die Reaktion des RFM12 wartet... Poste doch mal die Sende Funktion... Hast du zudem das RFM Korrekt verbunden? nSel muss auch verbunden werden! Übrigens... ein bisschen werbung muss sein :) Du könntest dir ja meinen LogicAnalyzer nachbauen... Ich habe mit diesem auch kommunikationsprobleme mit meinem RFM aufgedeckt! http://endasmedia.ch/projects/openlogic.php
Also, die Sende-Funktion habe ich von hier: http://www.mydani.com/dl/myrfm12/help/ Der Code sieht so aus:
1 | /* Correct functions are enabled for HW SPI*/
|
2 | #if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_HW
|
3 | /* HW SPI specific init function */
|
4 | void myrfm12_port_init_hw_spi(void); |
5 | #define myrfm12_spi_init myrfm12_port_init_hw_spi
|
6 | |
7 | /* HW SPI specific transfer function */
|
8 | uint16_t myrfm12_trans(uint16_t wert) |
9 | {
|
10 | #if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
|
11 | myrfm12_debug(cmd); |
12 | #endif
|
13 | |
14 | CONVERTW val; |
15 | val.w=wert; |
16 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS); |
17 | SPDR = val.b[1]; |
18 | while(!(SPSR & (1<<SPIF))); |
19 | val.b[1]=SPDR; |
20 | SPDR = val.b[0]; |
21 | while(!(SPSR & (1<<SPIF))); |
22 | val.b[0]=SPDR; |
23 | sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS); |
24 | return val.w; |
25 | |
26 | /* Implementation without union usage, needs more ROM */
|
27 | /*
|
28 | uint16_t feedback = 0x00;
|
29 | cbi(MYRFM12_PORT, MYRFM12_CS);
|
30 | SPDR = (uint8_t)(wert&0x00FF);
|
31 | while(!(SPSR & (1<<SPIF)));
|
32 | feedback |= SPDR;
|
33 | SPDR = (uint8_t)((wert&0xFF00)>>8);
|
34 | while(!(SPSR & (1<<SPIF)));
|
35 | feedback |= (SPDR << 8);
|
36 | sbi(MYRFM12_PORT, MYRFM12_CS);
|
37 | return feedback;
|
38 | */
|
39 | }
|
40 | #endif
|
41 | |
42 | /* Correct functions are enabled for SW SPI*/
|
43 | #if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_SW
|
44 | /* SW SPI specific init function */
|
45 | void myrfm12_port_init_sw_spi(void); |
46 | #define myrfm12_spi_init myrfm12_port_init_sw_spi
|
47 | |
48 | /* SW SPI specific transfer function */
|
49 | uint16_t myrfm12_trans(uint16_t cmd) |
50 | {
|
51 | #if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
|
52 | myrfm12_debug(cmd); |
53 | #endif
|
54 | |
55 | unsigned char i; |
56 | |
57 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS); // Select RFM12 |
58 | for (i=0; i<16; i++) // Iterate 16 times (for 16 bits) |
59 | {
|
60 | if (cmd&0x8000) |
61 | sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI); |
62 | else
|
63 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI); |
64 | cmd<<=1; |
65 | |
66 | if (MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO)) |
67 | cmd|=1; |
68 | |
69 | sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK); |
70 | //_delay_us(0.2);
|
71 | asm("nop"); |
72 | asm("nop"); |
73 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK); |
74 | }
|
75 | sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS); // Deselect RFM12 |
76 | //cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI); // SDI to low
|
77 | |
78 | return cmd; // Return received value |
79 | }
|
80 | #endif
|
81 | |
82 | void myrfm12_cmd_datarate(uint16_t baud) |
83 | {
|
84 | if (baud<5400) |
85 | myrfm12_trans(0xC680|MYRFM12_CALC_R_WITH_PRESCALER(baud)); |
86 | else
|
87 | myrfm12_trans(0xC600|MYRFM12_CALC_R_WITHOUT_PRESCALER(baud)); |
88 | }
|
89 | |
90 | #if (MYRFM12_CONF_SETUPMETHOD == MYRFM12_CONF_SETUPMETHOD_STD)
|
91 | void myrfm12_setup() |
92 | {
|
93 | /* Setup connection to RFM12 */
|
94 | myrfm12_spi_init(); |
95 | |
96 | /* wait until POR is done */
|
97 | uint8_t i; |
98 | for (i=0; i<20; i++) |
99 | _delay_ms(10); |
100 | |
101 | /* Setup basic configration, base frequency, capacitor */
|
102 | myrfm12_cmd_config(MYRFM12_CONF_SETUP_BASEFREQ|MYRFM12_CONF_SETUP_CAPACITOR|MYRFM12_CMD__CONFIG__RXFIFO_ON|MYRFM12_CMD__CONFIG__TXFIFO_ON); |
103 | |
104 | /* Setup power management, enable oscillator pin */
|
105 | myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR); |
106 | |
107 | /* Setup frequency */
|
108 | myrfm12_cmd_frequencysetting(MYRFM12_CONF_SETUP_ADDFREQ); |
109 | |
110 | /* Setup baud rate */
|
111 | myrfm12_cmd_datarate(MYRFM12_CONF_SETUP_BAUDRATE); |
112 | |
113 | /* Setup receiver part */
|
114 | myrfm12_cmd_rxcontrol(MYRFM12_CMD__RXCTRL__PIN20_VDIOUT | MYRFM12_CMD__RXCTRL__VDIRESPTIME_FAST | MYRFM12_CMD__RXCTRL__BASEBANDWITH_200KHZ | MYRFM12_CMD__RXCTRL__LNAGAIN_MIN6DB | MYRFM12_CMD__RXCTRL__DRSSI_M79DB); |
115 | |
116 | /* Setup data filer */
|
117 | myrfm12_cmd_datafilter(MYRFM12_CMD__DF__CLKRECAUTOLOCK_ENABLE | MYRFM12_CMD__DF__DQDTHRESH(3) | MYRFM12_CMD__DF__FILTERTYPE_DIGITAL); |
118 | |
119 | /* Setup the fifo */
|
120 | myrfm12_cmd_fifo(MYRFM12_CMD__FIFO__FIFOIRLEVEL(8)| MYRFM12_CMD__FIFO__HSRESETMODE_ENABLE | MYRFM12_CMD__FIFO__FIFO_FILL); |
121 | |
122 | /* Setup the AFC */
|
123 | myrfm12_cmd_afc(MYRFM12_CMD__AFC__AUTOMODE_MCU|MYRFM12_CMD__AFC__AUTOMODE_OFFSETKEEP | MYRFM12_CMD__AFC__RANGE_NARROW|MYRFM12_CMD__AFC__ENABLEHIGHACCURACY|MYRFM12_CMD__AFC__ENABLEOUTREG|MYRFM12_CMD__AFC__ENABLEAFC); |
124 | |
125 | /* Setup TX power,frequency deviation,modulation polarity */
|
126 | myrfm12_cmd_modulation_power(MYRFM12_CONF_SETUP_POWER,MYRFM12_CONF_SETUP_FREQDEV,MYRFM12_CONF_SETUP_MODULATIONPOLARITY); |
127 | |
128 | /* Setup Wakeup */
|
129 | myrfm12_cmd_wakeuptimer(MYRFM12_CMD__WAKEUP__BASE(0)|MYRFM12_CMD__WAKEUP__EXPONENT(0)); |
130 | |
131 | /* Setup low duty cycle */
|
132 | myrfm12_cmd_lowdutycycle(MYRFM12_CMD__LOWDUTY__DUTY(0)); |
133 | |
134 | /* Setup Low Battery Detector and clock divider */
|
135 | myrfm12_cmd_lowbatandclockdivider(MYRFM12_CMD__LOWBATCLOCK__CLOCK_10MHZ|MYRFM12_CMD__LOWBATCLOCK__LOWBATVOLT(0)); |
136 | }
|
137 | #endif
|
138 | |
139 | void myrfm12_ready() |
140 | {
|
141 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI); |
142 | cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS); |
143 | asm("nop"); |
144 | while (!(MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO))); |
145 | }
|
146 | |
147 | void myrfm12_sendsyncrobytes() |
148 | {
|
149 | uint8_t i; |
150 | for(i=0;i<3;i++) |
151 | {
|
152 | myrfm12_ready(); |
153 | myrfm12_trans(0xB8AA); |
154 | }
|
155 | }
|
156 | |
157 | void myrfm12_sendsyncbytes() |
158 | {
|
159 | myrfm12_ready(); |
160 | myrfm12_trans(0xB82D); |
161 | myrfm12_ready(); |
162 | myrfm12_trans(0xB8D4); |
163 | }
|
164 | |
165 | void myrfm12_txdata(uint8_t* data, uint8_t number) |
166 | {
|
167 | MYRFM12_CONF_SETUP_TX_START
|
168 | |
169 | /* Enable transmitter */
|
170 | myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR | MYRFM12_CMD__POWER__ENABLETRANSMITTER | MYRFM12_CMD__POWER__ENABLESYNTHESIZER); |
171 | |
172 | /* Send Syncro Bytes */
|
173 | myrfm12_sendsyncrobytes(); |
174 | |
175 | /* Send Sync Bytes */
|
176 | myrfm12_sendsyncbytes(); |
177 | |
178 | /* Send Length Byte */
|
179 | myrfm12_ready(); |
180 | myrfm12_cmd_txbyte(number); |
181 | |
182 | /* Send Data */
|
183 | uint8_t i; |
184 | for (i=0; i<number; i++) |
185 | {
|
186 | myrfm12_ready(); |
187 | myrfm12_cmd_txbyte(*data++); |
188 | }
|
189 | |
190 | /* Send Syncro Bytes */
|
191 | myrfm12_sendsyncrobytes(); |
192 | |
193 | _delay_us(10); |
194 | |
195 | /* Disable transmitter */
|
196 | myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR); |
197 | |
198 | MYRFM12_CONF_SETUP_TX_STOP
|
199 | }
|
Verwenden tue ich ihn so:
1 | myrfm12_setup(); |
2 | |
3 | unsigned char test[]="This is a myrfm12 test."; |
4 | for (;;) |
5 | {
|
6 | myrfm12_txdata(test,23); |
7 | |
8 | //<uart_puts_P("sende...\n");
|
9 | for ( i=0; i<100; i++) |
10 | _delay_ms(10); |
11 | }
|
Die Verbindung (hardwaremäßig) zwischen ATTINY2313 und RFM12 sieht so aus: RFM -> AVR --------------------------- SDO -> MISO (PB6) nIRQ -> PCINT3 (PB3) FSK -> über 10kOhm an VCC (3,3V) DCLK - > ? CLK -> ? nRES -> ? GND -> GND ANT -> 16cm Antenne VDD -> VCC (3,3V) GND -> GND nInt -> ? SDI -> MOSI (PB5) SCK -> SCL (PB7) nSEL -> über 10kOhm an VCC und an PCINT4 (PB4) Dem entsprechend initialisiere ich die RFM library so:
1 | /*! \def MYRFM12_PORT
|
2 | * \brief Port of the AVR on which the module is connected to */
|
3 | #define MYRFM12_CONF_PORT PORTB
|
4 | /*! \def MYRFM12_DDR
|
5 | * \brief Data direction register of the used port */
|
6 | #define MYRFM12_CONF_DDR DDRB
|
7 | /*! \def MYRFM12_PIN
|
8 | * \brief Pin assignment */
|
9 | #define MYRFM12_CONF_PIN PINB
|
10 | /*! \def MYRFM12_SDI
|
11 | * \brief The Pin-Number of the AVR that is connected with the SDI-Pin MOSI
|
12 | * of the RFM12 */
|
13 | #define MYRFM12_CONF_SDI 5
|
14 | /*! \def MYRFM12_SCK
|
15 | * \brief The Pin-Number of the AVR that is connected with the SCK-Pin SCK
|
16 | * of the RFM12 */
|
17 | #define MYRFM12_CONF_SCK 7
|
18 | /*! \def MYRFM12_CS
|
19 | * \brief The Pin-Number of the AVR that is connected with the nSEL-Pin
|
20 | * of the RFM12 */
|
21 | #define MYRFM12_CONF_CS 4
|
22 | /*! \def MYRFM12_SDO
|
23 | * \brief The Pin-Number of the AVR that is connected with the SDO-Pin MISO
|
24 | * of the RFM12 */
|
25 | #define MYRFM12_CONF_SDO 6
|
26 | /*! \def MYRFM12_NIRQ
|
27 | * \brief Optional Pin-Assignments; The Pin-Number of the AVR that is
|
28 | * connected with the nIRG-Pin of the RFM12 */
|
29 | #define MYRFM12_CONF_NIRQ 3
|
Das mit dem logic analyzer übersteigt im Moment noch meine Fähigkeiten ;-)
ok und wie hast du 0xFF übertragen um die Leitungen zu prüfen? Mirko schrieb: > Das mit dem logic analyzer übersteigt im Moment noch meine Fähigkeiten > ;-) Es wird in absehbarer zeit eine käufliche version geben :)
> SPDR = val.b[1]; > while(!(SPSR & (1<<SPIF))); Tiny2313 kennt keines von diesen beiden Registern. Du hast den Code also für einen falschen Prozessor übersetzt und in den Tiny gebrannt.
Argh! Danke für den Hinweis! Gibt es denn irgendwo einen Tiny kompatiblen sample Code (AVR<->RFM12) den man verwenden könnte? Leider finde ich nichts brauchbares :-(
Mirko schrieb: > Argh! Danke für den Hinweis! > Gibt es denn irgendwo einen Tiny kompatiblen sample Code (AVR<->RFM12) > den man verwenden könnte? > Leider finde ich nichts brauchbares :-( Ich hab meines genau mit dem Attiny2313 verwendet Ich kann dir den Code zukommen lassen sobald ich wieder zuhause bin das wäre morgen nachmittag
Das wäre wirklich super. Dank dir! Meine Adresse ist VanKurt at gmx.de Hast du auch noch eine Liste der verbundenen Pins? Einen Schaltplan oder ähnliches? Das wäre das Sahnehäubchen ;-)
Mirko schrieb: > Hast du auch noch eine Liste der verbundenen Pins? Einen Schaltplan oder > ähnliches? Das wäre das Sahnehäubchen ;-) Ja natürlich... Hab ich alles... Aber eben zuhause... Sende ich dir alles morgen nachmittag - abend :)
Hat vielleicht noch jemand ein bisschen Code/einen Schaltplan? Hedie scheint mich leider vergessen zu haben :-(
Und gleich noch eine Frage: Ist es eigentlich richtig, dass der nIRQ Pin des RFM12 auf 0V liegt? Ich habe ihn über einen Pullup an VCC angeschlossen, aber trotzdem liegt er auf 0V...
nIRQ ist ein Ausgang und benötigt keinen Pull-up. Wenn er low ist, dann liegt ein Ereignis im RFM12 an, welches noch nicht abgefragt wurde. Aber zum testen würde ich sowieso erst mal Polling beutzen und nicht den Interruptbetrieb (also nIRQ ignorieren). Ich habe damals zum Testen ein paar sehr simple Sende- und Empfangsprogramm geschrieben gehabt. Diese sind für einen LPC935 (8051er) und dementsprechend kann der Code nicht 1:1 auf einen AVR übernommen werden. Aber die eigentlichen Steuerbefehle sind ja identisch und dadrin gut zu erkennen. Du findest sie unter [1] mit den Namen Test_RFM12_*. Ciao, Rainer [1] https://quakeman.homelinux.net/viewvc/uVision/trunk/
Um zu sehen ob der Sender wirklich sendet hab ich die Stromaufnahme gemessen. Also eine Sekunde irgendwas senden, dann ne Pause und wieder senden. Dann sollte man mit einem Messgerät schön sehen können ob der RFM sendet. Dann weißt du zumindest, dass die SPI Kommunikation schonmal stimmt. Ob das Modul dann richtig konfiguriert ist kannst du dann aber noch nicht sagen...
Merkwürdig... Bei mir funktioniert der Code einwandfrei so wie ich ihn dir gesendet habe :S
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.