PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme bei Initialisierung des RFM 01 Funkmod. Gelöst !!!



wkrug
09.06.2007, 13:01
Hallo Leute,

ich hab ein Problem bei der Initialisierung eines RFM 02 Empfänger Funkmodules (Pollin) mit einem ATMEGA 8.
Die erste Initialisierung im Hauptprogramm funktioniert die meiste Zeit nicht, ab und zu schon.
Als Sicherheit wurde im Programmcode eine Zyklische Initialisierung eingebaut, die das Funkmodul nach 3 Sekunden Untätigkeit neu Initialisiert.
Die funktioniert so gut wie immer.
Das Fehlerbild:
Nach dem Einschalten der Betriebsspannung wird nichts Empfangen. Nach 3 Sekunden bekomm ich dann die ersten Werte.
Möchte mal einer von Euch mal über den Quellcode drüberschauen, wo ich da einen Fehler gemacht hab. Mir fällt einfach nichts mehr dazu ein.
Am Sender kann es meiner Meinung nach nicht liegen, der sendet alle Sekunde ein neues Paket ab und wurde zum Testen nicht abgeschaltet.

#include <mega8.h>
// Standard Input/Output functions
#include <stdio.h>
#include <string.h>
#include <delay.h>
#asm
.equ portb=0x18
.equ portd=0x12
.equ sdi=0 ;PortB,0
.equ sck=1 ;PortB,1
.equ nsel=2 ;PortB,2
.equ sdo=3 ;PortB,3
.equ nirq=2 ;PortD,2
#endasm

// Declare your global variables here
bit newstring=0; /* Ein neuer gültiger Datenstring wurde empfangen */
flash unsigned int ui_frequ[32]={1240,1270,1300,1330,1360,1390,1420,1450,1480,151 0,1540,1570,1600,1630,1660,1690,1720,1750,1780,181 0,1840,1870,1900,1900,1900,1900,1900,1900,1900,190 0,1900,1900};
volatile unsigned char uc_receivebuffer[127];/* Empfangspuffer */
volatile unsigned char uc_receivebyte=0;/* Zeiger aktuelles Sendebyte */
volatile unsigned char uc_timeout=0;
volatile unsigned char uc_kanal; /* gewählter Kanal */

// Sende ein Byte zum RFM 01
void sendbyte(volatile unsigned char uc_byte)
{
#asm
push r26 ;Register retten
in r26,sreg
push r26
push r27
ldi r26,8 ;Schleifenzähler mit 8 laden
ld r27,y ;uc_Byte vom Ram holen

sendloop:
tst r26 ;Schleifenzähler eins runterzählen
breq endsend
dec r26
clc
rol r27 ;High Byte ins Carry schieben
brcs send1 ;Bei 1 -> High ausgeben
cbi portb,sdi ;Bei 0 -> Low ausgeben
rcall clockpulse
rjmp sendloop

send1:
sbi portb,sdi
rcall clockpulse
rjmp sendloop

clockpulse:
nop
nop
nop
sbi portb,sck ;Clock Port auf 1 setzen
nop
nop
nop
nop
nop
nop
cbi portb,sck ;Clock Port auf 0 setzen
nop
nop
nop
ret ;Zurück zur aufrufenden Routine

endsend:
cbi portb,sdi ;SDI Port auf 0 setzen zwecks kosmetik
pop r27
pop r26
out sreg,r26
pop r26
#endasm
}

// XOR Verknüpfung Code Vision kann kein EXOR
#pragma warn- // this will prevent warnings
unsigned char funk_xor (unsigned char uc_wert1,unsigned char uc_wert2)
{
#asm
push r26
in r26,sreg
push r26
ld r26,y ;uc_wert2 holen
ldd r30,y+1 ;uc_wert1 holen
eor r30,r26 ;Rückgabewert im Register r30
pop r26
out sreg,r26
pop r26
#endasm

}
#pragma warn+ // enable warnings

// Checksumme berechnen
unsigned char checksum (void)
{
volatile unsigned char uc_check[2]={0,0}; /* (Checksummenpuffer)*/
volatile unsigned char uc_i=0;
uc_check[0]=uc_receivebuffer[uc_receivebyte-4]; /* High nibble einlesen */
uc_check[1]=uc_receivebuffer[uc_receivebyte-3]; /* Low nibble einlesen */
if (uc_check[0]>0x39)
{
uc_check[0]=uc_check[0]-0x37; /*ASCII Code A...F */
}
else
{
uc_check[0]=uc_check[0]-0x30; /*ASCII Code 0...9 */
}
if (uc_check[1]>0x39)
{
uc_check[1]=uc_check[1]-0x37;
}
else
{
uc_check[1]=uc_check[1]-0x30;
}
uc_check[0]=uc_check[0]<<4; /* Checksummen zusammenführen */
uc_check[0]=uc_check[0]|uc_check[1];

for (uc_i=0;uc_i<(uc_receivebyte-4);uc_i++)
{
uc_check[0]=funk_xor(uc_check[0],uc_receivebuffer[uc_i]); /* XOR Verknüpfung */
}
return uc_check[0]; /* Rückgabe der Checksumme, sollte wenn richtig 0 sein */
}

//FIFO Puffer initialisieren bei Fehlern und Datensatzende
void reset_fifo (void)
{
/* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, stop FIFO */
#asm ("cbi portb,nsel");
sendbyte(0b11001110);
sendbyte(0b10001001);
#asm ("sbi portb,nsel");
#asm ("nop");

/* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, start FIFO */
#asm ("cbi portb,nsel");
sendbyte(0b11001110);
sendbyte(0b10001011);
#asm ("sbi portb,nsel");
#asm ("nop");
uc_receivebyte=0;
}

// Einen Taktimpuls erzeugen
void clockpulse(void)
{
#asm
nop
nop
nop
sbi portb,sck ;Clock Port auf 1 setzen
nop
nop
nop
nop
nop
nop
cbi portb,sck ;Clock Port auf 0 setzen
nop
nop
nop


#endasm
}

// Empfange Daten vom RFM 01
interrupt [EXT_INT0] void ext_int0_isr(void)
{
unsigned char uc_i=0;
unsigned char uc_buffer=0;
unsigned char uc_check=0;

uc_timeout=0; /* Timeout Zähler zurücksetzen */

/* Die ersten 16 Bit des Statuswortes übergehen */
#asm ("cbi portb,nsel");
sendbyte(0b00000000);
sendbyte(0b00000000);

for(uc_i=0;uc_i<8;uc_i++)/* 8 Bits auslesen */
{


if ((PINB&(1<<3))!=0) /* SDO abfragen = PortB,3 */
{
uc_buffer=(uc_buffer<<1)| 0x01;
}
else
{
uc_buffer=(uc_buffer<<1);
}
clockpulse();
}
#asm ("sbi portb,nsel"); /* nSel Leitung abschalten */
#asm ("nop");


uc_receivebuffer[uc_receivebyte]=uc_buffer;
uc_receivebyte++;

if (uc_buffer==10) /* Line Feed wurde empfangen*/
{
uc_receivebuffer[uc_receivebyte]=0;
reset_fifo();
uc_check=checksum();
uc_receivebyte=0;

if (uc_check==0);
{
newstring=1;
}
}
}




#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Transmitter buffer
#define TX_BUFFER_SIZE 127
char tx_buffer[TX_BUFFER_SIZE];

#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
#asm("sei")
}
#pragma used-
#endif


//RFM01 initialisieren
void init_rfm01(void)
{
volatile unsigned char uc_frequ[2]; /* Frequenz tuningword */
/* Frequenzwortermittlung aus der Kanalangabe */
uc_frequ[1]=ui_frequ[uc_kanal]/256;
uc_frequ[1]|=0b10100000;
uc_frequ[0]=ui_frequ[uc_kanal]%256;

/* Configuration Setting: 433MHz, CLK on, 11,5pf Kapaz., 67kHz */
#asm ("cbi portb,nsel");
sendbyte(0b10001001);
sendbyte(0b01101100);
#asm ("sbi portb,nsel");
#asm ("nop");

/* Low Batt Clock Divider Command: clock 5MHz */
#asm ("cbi portb,nsel");
sendbyte(0b11000010);
sendbyte(0b11000000);
#asm ("sbi portb,nsel");
#asm ("nop");

/* Frequency Setting: 434MHz (je nach Kanal) */
#asm ("cbi portb,nsel");
sendbyte(uc_frequ[1]);
sendbyte(uc_frequ[0]);
#asm ("sbi portb,nsel");
#asm ("nop");

/* Receiver Setting Command: VDI= Digital RSSI Out, -103dB, receiver disabled */
#asm ("cbi portb,nsel");
sendbyte(0b11000000);
sendbyte(0b10000000);
#asm ("sbi portb,nsel");
#asm ("nop");

/* Receiver Setting Command: VDI= Digital RSSI Out, -103dB receiver enabled */
#asm ("cbi portb,nsel");
sendbyte(0b11000000);
sendbyte(0b10000001);
#asm ("sbi portb,nsel");
#asm ("nop");

/* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, stop FIFO */
#asm ("cbi portb,nsel");
sendbyte(0b11001110);
sendbyte(0b10001001);
#asm ("sbi portb,nsel");
#asm ("nop");

/* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, start FIFO */
#asm ("cbi portb,nsel");
sendbyte(0b11001110);
sendbyte(0b10001011);
#asm ("sbi portb,nsel");
#asm ("nop");


/* Data Filter Command: */
#asm ("cbi portb,nsel");
sendbyte(0b11000100);
sendbyte(0b10101100);
#asm ("sbi portb,nsel");
#asm ("nop");


/* Data Rate Command: 2400 bit/s */
#asm ("cbi portb,nsel");
sendbyte(0b11001000);
sendbyte(0b10010001);
#asm ("sbi portb,nsel");
#asm ("nop");


/* AFC Command: Enable AFC, +3/-4, offset at VDI high */
#asm ("cbi portb,nsel");
sendbyte(0b11000110);
sendbyte(0b10111111);
#asm ("sbi portb,nsel");
#asm ("nop");

}

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
/* 1 Sekunde */
uc_timeout++;

if (uc_timeout>3)/* Wenn 3 Sekunden kein Bit mehr Empfangen wurde wird der FiFo resetet */
{
init_rfm01();
reset_fifo();
uc_timeout=0;
}
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here
unsigned char uc_i=0;
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x07;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=P State4=P State3=P State2=P State1=P State0=P
PORTC=0x3F;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
// CTC Mode : On
TCCR1A=0x00;
TCCR1B=0x0C;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x7A; /* Comparematch Register mit 31250 laden = 1 Sekunde */
OCR1AL=0x11;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: Off
GICR|=0x40;
MCUCR=0x02;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 38400
UCSRA=0x00;
UCSRB=0x48;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0C;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Kanalauswahl
uc_kanal=(PINC&0b00111111);

// RFM 01 initialisieren
delay_ms(200);
init_rfm01();
reset_fifo();

// Testroutinen
/*strcpyf (uc_receivebuffer,"$123456789ABCDEF#31");
uc_receivebyte=strlen(uc_receivebuffer);
uc_receivebuffer[uc_receivebyte]=13;
uc_receivebuffer[uc_receivebyte+1]=10;
uc_receivebuffer[uc_receivebyte+2]=0;

uc_receivebyte=strlen(uc_receivebuffer);
checksum();*/
// Ende der Testroutinen

// Global enable interrupts
#asm("sei")

while (1)
{
/*newstring=1;*/ /* zu Testzwecken */

if (newstring==1)
{
for (uc_i=0;uc_i<strlen(uc_receivebuffer);uc_i++)
{
putchar (uc_receivebuffer[uc_i]);
}
newstring=0;
}
};
}

stevensen
11.07.2007, 21:31
hi,
ich habe mir auch die beiden rfm01/rfm02 zugelegt und krieg sie nicht zum Laufen, habe auch schon in Foren nachgefragt, aber meistens gibts nur die Anwort:" Benutzte die Suchfunktion". Falls du es geschafft hast wäre es nett wenn du mir ein paar Tipps geben könntest.

wkrug
12.07.2007, 19:11
No meine Funkstrecke läuft soweit.

Der im ersten Post angegebene Code laäuft auch, allerding s hab ich immer noch das Problem mit der ersten Initialisierung.
Wenn Du mir mal schreibst, wo du Probleme hast, kann ich Dir schon helfen.
Fertigen Code in C und Schaltpläne mit nem ATMEGA 8 hab ich auch.
Wo genau liegt dein Problem ?

stevensen
14.07.2007, 19:48
Ja ich hab' verschiedene Sachen noch gar nicht verstanden. Ich weiß durch den Tipp eines anderen, daß der RFM02 keinen FIFO hat. Das war schonmal ein Fehler. Ich möchte die RFM01 /02 mit Bascom proggen,und verstehe den C-Code noch nicht richtig. Aber jetzt möchte erstmal paar allgemeine Funktionen usw. wissen. Ich kann ja die Teile mittels SPI configurieren, das klappt wohl, also die CLK-Mhz konnte ich ändern und hab's per Ozzi kontrolliert. Wenn ich z.B was Senden möchte muss ich ja das Commando &Hc6 per SPI senden, und das CS auf low setzen. Nun wird doch alles bis ich CS wieder auf High setze als Daten genommen. Und diese Daten muss ich Bit für Bit senden. Muss ich den SCK manuell wechseln und wenn ja in welcher Freq. und wie ist das mit dem IRQ nSEL?

wkrug
14.07.2007, 20:13
Mir ist da ein Lapsus unterlaufen, ich meine natürlich ein RFM 01 Empägermodul und das hat sehr wohl einen FiFo Puffer.
Es geht ja im Prinzip auch alles, nur leider initialisiert sich der Empfänger erst mit der "Sicherheits" Initiaisierung nach 3 Sekunden.

@stevensen

Wenn ich z.B was Senden möchte muss ich ja das Commando &Hc6 per SPI senden
Das klappt so nicht, weil das Senden von Datenströmen uber SDI nicht zum SPI Mode kompatibel ist (Steht auch so im Datenblatt).
Es darf während der Versendung von einzelnen Bits kein ! Takt (SCK) mit ausgegeben werden.
Die SPI gibt aber immer! ein Taktsignal raus und muss also während des Versendens von Bits nach dem Hc6 Kommando abgeschaltet werden.

Ich hab die Hardware SPI des Controllers überhaupt nicht genutzt und die SPI über Software realisiert, dann ist das natürlich kein Problem.

Ich lass den Baudrategenerator des RFM 02 laufen, der setzt nach dem Senden eines Bits den NIRQ und ich schieb dann das nächste Bit auf den SDI Pin.
Du kannst aber auch ohne diesen NIRQ arbeiten, dann muss allerdings dein Controller für das Bittiming sorgen.

Sind alle Bits gesendet sperre ich den Interrupt meines ATMEGA 8 , da der NIRQ auch durch andere ereignisse getriggert werden könnte.

Vor dem Senden der nächsten Sequenz lösche ich das Interrupt Flag meines ATMEGA 8 und starte eine neue Übertragung.

stevensen
15.07.2007, 15:12
Hallo Wkrug,
danke für die Antworten. Ich habe nochmal ein paar Fragen wenn ich darf.
Den Umstand mit dem Hc6 habe ich noch nicht verstanden. Das ist doch das Commando,welches sagt, daß das was anschliessend gesendet wird als Daten zu nehmen ist bis nSEL wieder High wird? Kann ich Hc6 noch über SPI schicken oder muss ich es auch schon bitweise schicken ? Könntest Du mir eine Hex-Datei für den Sender schicken der die Preamble und ein paar Daten sendet? Für nen Mega 8 mit 8 Mhz. Dann könnte ich testen ob mein Empfänger die syncs erkennt,danach könnte ich dann wieder am Sender weitermachen.

wkrug
18.10.2007, 18:57
Probleme bei Initialisierung des RFM 01 Funkmod.
Der Fehler lag vermutlich bei meinem "wilden" Versuchsaufbau.
Entweder die Speisespannung lief zu langsam hoch, oder im Augenblick des Einschaltens waren dermassen viele Fehler auf dem SPI, das keine richtige Komunikation möglich war.
Nachdem der Empfänger auf einer Platine aufgebaut war, konnte der Fehler nicht mehr festgestellt werden.