Forum: HF, Funk und Felder ATMEGA 128RFA1 - Bit übertragen


von Florian J. (Firma: Ostfalia WF) (codef)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

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?

von Florian J. (Firma: Ostfalia WF) (codef)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.