Forum: Mikrocontroller und Digitale Elektronik Atmega8 kommuniziert mit RFM12BP nur nach reset.


von GoGi (Gast)


Lesenswert?

Hallo,

Ich versuche mit einem Atmega8 einen RFM12BP mit der rfm12lib 
(http://www.hansinator.de/rfm12lib/) anzusteuern. Anpassungen für die 
zwei zusätzlichen Pins am -BP habe ich eingebaut. Mein Problem ist nun 
folgendes:

Wenn ich Spannung an meine Schlatung anlege, dann kann der Atmega8 
anscheinend nicht mit dem RFM12BP kommunizieren, es werden jedenfalls 
per SPI immer Nullen gelesen.

Wenn ich nun einen Reset des Atmega8 durchführe (durch manuelles Anlegen 
einer Brücke) funktioniert die Kommunikation anscheinend, ich erhalte 
jedenfalls ein korrektes Statusbyte per SPI.

Wenn ich die Spannung entferne und wieder anlege funktioniert es wieder 
nicht.

Ganz ganz selten funktioniert es auch direkt nach anlegen einer 
Spannung, ohne Reset.

Hat jemand eine Idee woran das liegen könnte? Gibt es denn einen 
Unterschied zwischen einem Reset und dem erstmaligen Anlegen einer 
Spannung?

Schonmal vielen Dank.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Das Verhalten wäre erklärbar, wenn der RFM12BP nach dem Power-On länger 
für sein erstes Hochfahren (Reset) braucht als der Atmega8.

Ein solches Verhalten kann gelegentlich bei LCD-Controllern beobachtet 
werden.

Du könntest mal nach dem Power-On deines Systems auf dem Atmega8 länger 
warten ("2 Sekunden") bis du die ersten Aktionen mit dem RFM12BP machst. 
Das betrifft u.a. auch alle Änderungen am Status/Pegel der Leitungen 
zwischen Atmega8 und RFM12BP.

Wenn das grundsätzlich eine Verbesserung bringt, kannst du die Wartezeit 
durch Probieren verringern und/oder am Brownout und/oder Clockwartezeit 
des Atmega8 schrauben.

von Matthias D. (marvin42)


Lesenswert?

Hallo,

ich hatte mit meinen RFM12B ähnliche Probleme, mit so ziemlich jeder 
Bibliothek. Irgendwann habe ich den Code dann so geschrieben:

vielleicht hilft's dir...

-------schnipp-----------


#include <avr/io.h>
#include <stdio.h>

#define F_CPU 8000000UL

#include <util/delay.h>

// RFM12B Sender auf Basis ATtiny45
// RFM12B interface angepasst auf ATtiny45

#define SCK    2     // PB2
#define SDO    0     // PB0   MOSI
#define SDI    1     // PB1
#define CS     3     // PB3   ..
#define NIRQ   4     // PortB INT0

#define HI(x)  PORTB |=  (1<<(x))
#define LO(x)  PORTB &= ~(1<<(x))

#define WAIT_NIRQ_LOW()   while (PINB&(1<<NIRQ))

#define LED    5     // PortD 6
#define LED_OFF()    PORTB &= ~(1<<LED)
#define LED_ON()     PORTB |=  (1<<LED)

#define nop()  _asm__ __volatile_ ("nop" ::)


void portInit()
{
   HI(CS);
   HI(SDI);
   LO(SCK);
   DDRB = (1<<CS) | (1<<SDI) | (1<<SCK) | (1 <<LED);
}


unsigned int writeCmd(unsigned int cmd)
{
   unsigned char i;
   unsigned int recv;
   recv = 0;

   LO(CS);
   LO(SCK);
   for (i=0; i<16; i++)
   {
      if (cmd & 0x8000) HI(SDI); else LO(SDI);
      HI(SCK);
      recv<<=1;
      if (PINB & (1<<SDO)) recv |= 0x0001;
      LO(SCK);
      cmd<<=1;
   }
   HI(CS);

   return recv;
}


void rfInit()
{
   writeCmd(0x80E7);    // EL, EF, 868 MHz, 12 pF
   writeCmd(0x8238);    // 8239- Transmit !
   writeCmd(0xA640);    // freq select
   writeCmd(0xC647);    // 4800 baud
   writeCmd(0x94A4);    // 94A0- : VDI, Fast, 0dBm, -103dBm
   writeCmd(0xC2AC);    // AL, !ml, DIG, DQD4
   writeCmd(0xCA81);    // FIFO8, SYNC, !ff, DR (FIFO level=8)
   //writeCmd(0xCED4);    // Sync=2DD4
   writeCmd(0xC483);    // @PWR, NO RSTRIC, !st, !fi, OE, EN
   writeCmd(0x9850);    // !mp, 90Khz, MAX OUT
   //writeCmd(0xCC17);    // !OB!, !OB0, LPX, !ddy, DDIT, BWO
   writeCmd(0xE000);    // not used
   writeCmd(0xC800);    // not used
   writeCmd(0xC090);    // c040- 1,66 MHz, 2.2V
}


void rfSend(unsigned char data)
{
   unsigned int cmd;
   unsigned char i;

   cmd = 0xB800 + data;

   LO(CS);
   LO(SCK);
   for (i=0; i<16; i++)
   {
      if (cmd & 0x8000) HI(SDI); else LO(SDI);
      HI(SCK);
      nop();
      LO(SCK);
      cmd<<=1;
   }

   // warten bis SDO=1 wird, erst dann ist das
   // TX Register fürs nächste Byte bereit
   while ( (PINB & (1<<SDO)) == 0)
   {
      nop();
   }

   HI(CS);
}


int main()
{
   unsigned char base;
   volatile unsigned int i,k;
   char txMsg[18];
   int adval;

   base = 00;

   // das hier scheint zum stabilen Betrieb nötig zu sein..
   asm("cli");
   for (i=0; i<1000; i++) for (k=0; k<100; k++);
   portInit();
   rfInit();
   for (i=0; i<1000; i++) for (k=0; k<100; k++);


   // damit etwas halbvoll sinnvolles passiert, versenden
   // wir eine Textnachricht die den internen Temperatursensor
   // des ATtiny enthält

   ADMUX=0x8F;    // int 1.1 V ref,
   ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADATE | 0<<ADPS2 | 1<<ADPS1 | 
1<<ADPS0;;
   ADCSRB = 0;

   while (1)
   {
      LED_ON();

      // 0123456789abcdef
      // ii.aaaa.abcd0123
      adval = ADCW;
      sprintf(txMsg, "%02x.%04d°.abcd012",
              base, adval );

      writeCmd(0x0000);
      rfSend(0xAA);
      rfSend(0xAA);
      rfSend(0xAA);
      rfSend(0x2D);
      rfSend(0xD4);
      for (i=0; i<16; i++) rfSend(txMsg[i]);
      rfSend(0xAA);
      rfSend(0xAA);
      rfSend(0xAA);

      LED_OFF();

      // ca 10 sec Pause
      for (i=0; i<1000; i++) for (k=0; k<123; k++);

      // irgendso ein Zähler...
      base++;

   }
}

-------schnapp-----------

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.