Hallo, im Rahmen einer Studienarbeit soll ich zum Thema HF-Technik eine Antenne für den 128RFA1 entwickeln. Dabei stelle ich zwei Platinen mit Planar-Antennen her, an die jeweils ein 128RFA1 angeschlossen wird. Um die korrekte Funktion zu demonstrieren, soll irgendwas übertragen werden. Da habe ich mir überlegt, dass es das einfachste ist 1 Bit zu übertragen. Bedeutet: Wenn ich bei dem einen Controler eine Taste drücke, so soll auf der anderen Platine eine LED leuchten. Leider habe ich bisher nicht herausfinden können, wie ich den RF-Kanal nutzen kann, und konnte bisher auch keine genauen Informationen im Internet finden. Vieleicht kann mir jemand zeigen, wie ich dieses Problem am einfachsten lösen kann. Vielen Dank schon einmal im Voraus. Florian
:
Verschoben durch Moderator
Vergiss das Bit. Die Leib und Mageneinheit eines µC ist 1 Byte. Alles andere ist zusätzlicher Aufwand. Zum Thema: wie geht man mit der Funkeinheit um? Würde mich wundern, wenn es da von Atmel keine AppNote zu dem Thema gäbe. Schon mal danach gesucht?
Ja das Bit habe ich jetzt vergessen und versuche nun ein Byte zu übertragen. Der Inhalt ist ja zunächst auch egal. Folgendes Programm habe ich jetzt am laufen: main.c
1 | #include <asf.h> |
2 | #include <avr/io.h> |
3 | #include "RadioFunctions.h" |
4 | |
5 | |
6 | int main (void) |
7 | {
|
8 | board_init(); |
9 | |
10 | DDRE = 0b11111111; |
11 | //DDRE |= (1 << DDE5);
|
12 | |
13 | DDRE &= ~(1<<PE5); /* Pin PC7 als Eingang */ |
14 | PORTE |= (1<<PE5); /* internen Pull-Up an PC7 aktivieren */ |
15 | rfBegin(11); // Initialize ATmega128RFA1 radio on channel 11 (can be 11-26) |
16 | |
17 | |
18 | while(1) |
19 | {
|
20 | PORTE = 0xFF; |
21 | |
22 | if ( PINE & (1<<PINE5) ) //Taste senden |
23 | {
|
24 | |
25 | //PORTE |= (1<<PE4);
|
26 | |
27 | } else |
28 | {
|
29 | rfWrite(0xFF); // ...send it out the radio. |
30 | //
|
31 | |
32 | }
|
33 | |
34 | if (rfAvailable()) // If data receievd on radio... |
35 | {
|
36 | //ggf. LED ansteuern
|
37 | }
|
38 | }
|
39 | |
40 | }
|
RadioFunctions.h
1 | uint8_t rssiRaw; // Global variable shared between RX ISRs |
2 | #include <asf.h> |
3 | #include <string.h> |
4 | #include <stdio.h> |
5 | #include <stdlib.h> |
6 | #include <util/delay.h> |
7 | #define F_CPU 20000000
|
8 | |
9 | const int RF_BUFFER_SIZE = 127; |
10 | struct ringBuffer |
11 | {
|
12 | unsigned char buffer[127]; |
13 | volatile unsigned int head; |
14 | volatile unsigned int tail; |
15 | } radioRXBuffer; |
16 | |
17 | |
18 | // Initialize the RFA1's low-power 2.4GHz transciever.
|
19 | // Sets up the state machine, and gets the radio into
|
20 | // the RX_ON state. Interrupts are enabled for RX
|
21 | // begin and end, as well as TX end.
|
22 | uint8_t rfBegin(uint8_t channel) |
23 | {
|
24 | for (int i=0; i<128; i++) |
25 | {
|
26 | radioRXBuffer.buffer[i] = 0; |
27 | }
|
28 | radioRXBuffer.tail = 0; |
29 | radioRXBuffer.head = 0; |
30 | |
31 | // Transceiver Pin Register -- TRXPR.
|
32 | // This register can be used to reset the transceiver, without
|
33 | // resetting the MCU.
|
34 | TRXPR |= (1<<TRXRST); // TRXRST = 1 (Reset state, resets all registers) |
35 | |
36 | // Transceiver Interrupt Enable Mask - IRQ_MASK
|
37 | // This register disables/enables individual radio interrupts.
|
38 | // First, we'll disable IRQ and clear any pending IRQ's
|
39 | IRQ_MASK = 0; // Disable all IRQs |
40 | |
41 | // Transceiver State Control Register -- TRX_STATE
|
42 | // This regiseter controls the states of the radio.
|
43 | // First, we'll set it to the TRX_OFF state.
|
44 | TRX_STATE = (TRX_STATE & 0xE0) | TRX_OFF; // Set to TRX_OFF state |
45 | |
46 | |
47 | PORTE &= ~(1<<PE2); |
48 | _delay_ms(1000); |
49 | PORTE |= (1<<PE2); |
50 | |
51 | // Transceiver Status Register -- TRX_STATUS
|
52 | // This read-only register contains the present state of the radio transceiver.
|
53 | // After telling it to go to the TRX_OFF state, we'll make sure it's actually
|
54 | // there.
|
55 | |
56 | if ((TRX_STATUS & 0x1F) != TRX_OFF) // Check to make sure state is correct |
57 | return 0; // Error, TRX isn't off |
58 | |
59 | // Transceiver Control Register 1 - TRX_CTRL_1
|
60 | // We'll use this register to turn on automatic CRC calculations.
|
61 | TRX_CTRL_1 |= (1<<TX_AUTO_CRC_ON); // Enable automatic CRC calc. |
62 | |
63 | // Enable RX start/end and TX end interrupts
|
64 | IRQ_MASK = (1<<RX_START_EN) | (1<<RX_END_EN) | (1<<TX_END_EN); |
65 | |
66 | // Transceiver Clear Channel Assessment (CCA) -- PHY_CC_CCA
|
67 | // This register is used to set the channel. CCA_MODE should default
|
68 | // to Energy Above Threshold Mode.
|
69 | // Channel should be between 11 and 26 (2405 MHz to 2480 MHz)
|
70 | if ((channel < 11) || (channel > 26)) channel = 11; |
71 | PHY_CC_CCA = (PHY_CC_CCA & 0xE0) | 11; // Set the channel to 11 |
72 | |
73 | // Finally, we'll enter into the RX_ON state. Now waiting for radio RX's, unless
|
74 | // we go into a transmitting state.
|
75 | TRX_STATE = (TRX_STATE & 0xE0) | RX_ON; // Default to receiver |
76 | |
77 | return 1; |
78 | }
|
79 | |
80 | |
81 | // This function will transmit a single byte out of the radio.
|
82 | void rfWrite(uint8_t b) |
83 | {
|
84 | uint8_t length = 3; |
85 | |
86 | // Transceiver State Control Register -- TRX_STATE
|
87 | // This regiseter controls the states of the radio.
|
88 | // Set to the PLL_ON state - this state begins the TX.
|
89 | TRX_STATE = (TRX_STATE & 0xE0) | PLL_ON; // Set to TX start state |
90 | while(!(TRX_STATUS & PLL_ON)) |
91 | ; // Wait for PLL to lock |
92 | |
93 | //digitalWrite(TX_LED, HIGH); // Turn on TX LED
|
94 | |
95 | PORTE &= ~(1<<PE3); |
96 | |
97 | // Start of frame buffer - TRXFBST
|
98 | // This is the first byte of the 128 byte frame. It should contain
|
99 | // the length of the transmission.
|
100 | TRXFBST = length; |
101 | // Now copy the byte-to-send into the address directly after TRXFBST.
|
102 | memcpy((void *)(&TRXFBST+1), &b, 1); |
103 | |
104 | // Transceiver Pin Register -- TRXPR.
|
105 | // From the PLL_ON state, setting SLPTR high will initiate the TX.
|
106 | TRXPR |= (1<<SLPTR); // SLPTR = 1 |
107 | TRXPR &= ~(1<<SLPTR); // SLPTR = 0 // Then bring it back low |
108 | |
109 | // After sending the byte, set the radio back into the RX waiting state.
|
110 | TRX_STATE = (TRX_STATE & 0xE0) | RX_ON; |
111 | }
|
112 | |
113 | // Returns how many unread bytes remain in the radio RX buffer.
|
114 | // 0 means the buffer is empty. Maxes out at RF_BUFFER_SIZE.
|
115 | unsigned int rfAvailable() |
116 | {
|
117 | return (unsigned int)(RF_BUFFER_SIZE + radioRXBuffer.head - radioRXBuffer.tail) % RF_BUFFER_SIZE; |
118 | }
|
119 | |
120 | // This function reads the oldest data in the radio RX buffer.
|
121 | // If the buffer is emtpy, it'll return a 255.
|
122 | char rfRead() |
123 | {
|
124 | if (radioRXBuffer.head == radioRXBuffer.tail) |
125 | {
|
126 | return -1; |
127 | }
|
128 | else
|
129 | {
|
130 | // Read from the buffer tail, and update the tail pointer.
|
131 | char c = radioRXBuffer.buffer[radioRXBuffer.tail]; |
132 | radioRXBuffer.tail = (unsigned int)(radioRXBuffer.tail + 1) % RF_BUFFER_SIZE; |
133 | return c; |
134 | }
|
135 | }
|
136 | |
137 | // This interrupt is called when radio TX is complete. We'll just
|
138 | // use it to turn off our TX LED.
|
139 | ISR(TRX24_TX_END_vect) |
140 | {
|
141 | PORTE |= (1<<PE3); |
142 | }
|
143 | |
144 | // This interrupt is called the moment data is received by the radio.
|
145 | // We'll use it to gather information about RSSI -- signal strength --
|
146 | // and we'll turn on the RX LED.
|
147 | ISR(TRX24_RX_START_vect) |
148 | {
|
149 | |
150 | rssiRaw = PHY_RSSI; // Read in the received signal strength |
151 | PORTE &= ~(1<<PE4); |
152 | }
|
153 | |
154 | // This interrupt is called at the end of data receipt. Here we'll gather
|
155 | // up the data received. And store it into a global variable. We'll
|
156 | // also turn off the RX LED.
|
157 | ISR(TRX24_RX_END_vect) |
158 | {
|
159 | uint8_t length; |
160 | // Maximum transmission is 128 bytes
|
161 | uint8_t tempFrame[RF_BUFFER_SIZE]; |
162 | |
163 | // The received signal must be above a certain threshold.
|
164 | if (rssiRaw & RX_CRC_VALID) |
165 | {
|
166 | // The length of the message will be the first byte received.
|
167 | length = TST_RX_LENGTH; |
168 | // The remaining bytes will be our received data.
|
169 | memcpy(&tempFrame[0], (void*)&TRXFBST, length); |
170 | |
171 | // Now we need to collect the frame into our receive buffer.
|
172 | // k will be used to make sure we don't go above the length
|
173 | // i will make sure we don't overflow our buffer.
|
174 | unsigned int k = 0; |
175 | unsigned int i = (radioRXBuffer.head + 1) % RF_BUFFER_SIZE; // Read buffer head pos and increment; |
176 | while ((i != radioRXBuffer.tail) && (k < length-2)) |
177 | {
|
178 | // First, we update the buffer with the first byte in the frame
|
179 | radioRXBuffer.buffer[radioRXBuffer.head] = tempFrame[k++]; |
180 | radioRXBuffer.head = i; // Update the head |
181 | i = (i + 1) % RF_BUFFER_SIZE; // Increment i % BUFFER_SIZE |
182 | }
|
183 | }
|
184 | |
185 | // Turn receive LED off, and we're out
|
186 | PORTE |= (1<<PE4); |
187 | }
|
Das Senden sollte meiner Meinung nach funktionieren, habe dies mittels Spektrumanalysater getestet (Beim Drücken der Sendetaste ist die Frequenz 2,405 GHz im Spektrum vorhanden). Wird die Taste gedrück, geht auch brav die TX-LED an. Allerdings tut sich beim zweiten uC nichts. Eigentlich sollte dort dann die RX Lampe agehen, gesteuert von der ISR. Auf beiden uC läuft das selbe Programm. Mehr zu diesem Problem habe ich im Internet noch nicht herausfinden können.
Karl Heinz Buchegger schrieb: > Die Leib und Mageneinheit eines µC ist 1 Byte. Alles andere ist > zusätzlicher Aufwand. In diesem Falle ist die Leib- und Mageneinheit ein Frame, denn nur einen solchen kann ein Transceiver nach IEEE 802.15.4 übertragen. Ansonsten würde ich dem TE mal das µracoli-Projekt nahelegen, besonders natürlich angesichts der Tatsache, dass sein Hauptaugenmerk ja gar nicht auf der eigentlichen Datenübertragung, sondern auf dem Antennendesign liegt. Wenn du eine wirklich gute Vergleichsantenne haben willst: nimm die aus der Appnote AVR2006. An deren 6,5 dBi darfst du, gemessen am vergleichsweise geringen Aufwand, den sie treibt, deine Experimente messen lassen. (Wenn du dich mal bei den Erklärungen zu meinen Boards von „Tic-Tac-Toe Reloaded“ umsiehst, kann man diese Antenne unter bestimmten Umständen direkt ohne Tiefpass an den ATmega128RFA1 klemmen, ohne die ETSI-Grenzwerte für die Störstrahlung zu überschreiten. Nimm aber dann möglichst die Sendeleistung etwas zurück.)
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.