-         

Ergebnis 1 bis 2 von 2

Thema: Funkmodul RFM12 + ATMEGA32

  1. #1

    Funkmodul RFM12 + ATMEGA32

    Anzeige

    Liebe Roboternetz Community,

    ich arbeite seit Tagen an einer Funkübertragung mittels RFM12 zwischen zwei ATMEGA32. Die Anforderungen sind nicht so besonders...ich möchte nur alle paar Sekunden 8 byte senden (in den untenstehenden Programmen jeweils nur 1 Datenbyte pro Sekunde). Leider bringe ich nichts zustande ...habe mich bei der Programmierung sehr an die ausgezeichnete Doku zum RN-Mikrofunk V1.7 gehalten (jedoch mit Hardware SPI).
    Ich bin mir sehr bewusst, dass meine Arbeit eher unschön und amateurmäßig ist...habe sehr wenig Erfahrung mit AVR und generell µC. Ich würde euch aber trotzdem bitten, meine Programme anzusehen und mir Fehlerquellen zu verraten. Einen Hardwarefehler schließe ich aus, da ich schon mehrmals kontrolliert habe. Ich freue mich schon auf eure Antworten!

    Hier zuerst mal der Sender:

    Code:
    #define F_CPU 16000000UL									// Taktfrequenz des µC definieren
    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    volatile int Data_H;
    volatile int Data_L;
    volatile int i = 0;
    
    void SPI_MasterInit(void)
    {
    	                                                                                                       /* Set SS, MOSI and SCK output, all others input */
    	DDRB = (1<<DDB4)|(1<<DDB5)|(1<<DDB7);
    	                                                                                                       /* Enable SPI, Master, set clock rate fck/16 */
    	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
    	return;
    }
    
    void SPI_MasterTransmit(unsigned int Data)
    {
    	Data_H = ((Data >>8) & 0x00FF);
    	Data_L = Data & 0x00FF;
    
    	PORTB &= ~(1<<PB4);						//nSel auf Low ziehen
    	SPDR = Data_H;							/* Start transmission */
    	while(!(SPSR & (1<<SPIF)));
    									        /* Wait for transmission complete */
    	PORTB |= (1<<PB4);						//nSEL auf High
    	_delay_ms(10);
    	PORTB &= ~(1<<PB4);
    	SPDR = Data_L;							/* Start transmission */
    	while(!(SPSR & (1<<SPIF)));				        /* Wait for transmission complete */
    	PORTB |=(1<<PB4);
    	_delay_ms(10);
    	return;
    }
    
    
    int main(void)
    {
     
    		//------------------------------------µC - Initialisierung ----------------------------------------------------------------------
    		// AD - Wandler:
    		
    		PORTB &= ~(1<<PB0);
    		
    		ADMUX |= 0x00;																// Sind die Mux4...0 -Bits = 0, so wird der Port ADC0 ausgewählt
    		ADMUX |= (1<<REFS0) | (1<<ADLAR);												// Referenzspannung ist AVCC
    		
    		ADCSRA = 0x00;
    		ADCSRA |= (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);									// Prescaler für Samplerate auf 128
    		ADCSRA |= (1<<ADEN);															// ADC einschalten
    		
    		
    		
    		// TIMER 0:
    		
    		TCCR0 = (1<<WGM01) | (1<<CS02) | (1<<CS00);										// CTC Mode im Timer und Prescaler auf 16MHz/1024
    		OCR0 = 0x1F;																// Timer - Intervall
    		
    		TIMSK |= (1<<OCIE0);															// Compare Match Interrupt aktivieren
    		sei();																		// Interrupts generell aktivieren
    		
    		
    		// RFM12 Funkmodul:
    
    		SPI_MasterInit();
    		
    		SPI_MasterTransmit(0x80D7);														//Enable: 433 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo //// D7!!!!
    		SPI_MasterTransmit(0x82D9);														//Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer
    																						//Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin
    		SPI_MasterTransmit(0xA67C);														//Frequenz 434,15 Mhz
    		SPI_MasterTransmit(0xC623);														//Baudrate 9600kBps
    		SPI_MasterTransmit(0x90C0);														//LNA Gain=MAX; Pin=nInt; RX Bandwidth=67 khz; VDI=Fast; DRSSI=-103 dB
    		SPI_MasterTransmit(0xC2AC);														//Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow
    		SPI_MasterTransmit(0xCA80);														//FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset; Sensitivity=High
    																						//Disable:FIFO Fill Enabled
    		SPI_MasterTransmit(0xC483);														//Enable: AFC Mode; AFC; Frequency Offset Register
    																						//Disable: High Accuracy; Strobe
    		SPI_MasterTransmit(0x9820);														//Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz
    		SPI_MasterTransmit(0xE000);														//WakeUp timer = 0ms
    		SPI_MasterTransmit(0xC800);														//Duty Cycle = Infinity % OFF
    		SPI_MasterTransmit(0xC000);														//Low Battery = 2,2V; Clock Pin = 1Mhz
    		SPI_MasterTransmit(0xCED4);														//Synchron Pattern
    		SPI_MasterTransmit(0xCC57);														//PLL Settings
    		SPI_MasterTransmit(0x0000);														//Status lesen, nirqs zurückstellen
    		_delay_ms(200);																	//200ms warten
    		 
    		
    		
    		
    	while(1)
    	{
    		if(i==61)																		// 61 für Sekundentakt (1s/(256*16Mhz/1024))
    		{
    			i = 0;																		// Zähler zurücksetzen
    			//ADCSRA |= (1<<ADSC);														// Starten der Umwandlung
    			//while(ADCSRA & (1<<ADSC));													// Warten bis ADSC wieder 0 wird (µC ist fertig mit der AD - Wandlung)
    			//PORTB = ADCH;																// Ausgabe des Higher-Bytes am Port B    
    			
    			
    			// Daten übertragen
    			
    			SPI_MasterTransmit(0x8238);													// Sender, Synthesizer Quarzoszillator
    			SPI_MasterTransmit(0xB8AA);
    			SPI_MasterTransmit(0xB8AA);
    			SPI_MasterTransmit(0xB8AA);													//1010 zum synchronisieren mit dem Empfänger
    			SPI_MasterTransmit(0xB82D);													//Synchronbyte
    			SPI_MasterTransmit(0xB8D4);													//Synchronbyte
    			
    			SPI_MasterTransmit(0xB801);													//DATEN (01 nur TEST)
    			SPI_MasterTransmit(0xB8AA);
    			SPI_MasterTransmit(0xB8AA);													//1010 zum synchronisieren mit dem Empfänger
    			SPI_MasterTransmit(0x8208);													//Sender abschalten	
    			
    			
    		}
    	}
    }
    
    ISR(TIMER0_COMP_vect)																	// Interrupt des Timer0
    {
    	i++;
    }

    Und hier der Empfänger:
    Code:
    #define F_CPU 16000000UL															// Taktfrequenz des µC definieren
    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile int Data_H;
    volatile int Data_L;
    
    void SPI_MasterInit(void)
    {
    	                                                                               // Set SS, MOSI and SCK output, all others input ----> MISO muss input sein!
    	DDRB = (1<<DDB4)|(1<<DDB5)|(1<<DDB7);
    	                                                                               /* Enable SPI, Master, set clock rate fck/16 */
    	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
    	return;
    }
    
    void SPI_MasterTransmit(unsigned int Data)
    {
    	Data_H = ((Data >>8) & 0x00FF);
    	Data_L = Data & 0x00FF;
    
    	PORTB &= ~(1<<PB4);						//nSel auf Low ziehen
    	SPDR = Data_H;                                                   /* Start transmission */
    	while(!(SPSR & (1<<SPIF)));
    	                                                                        /* Wait for transmission complete */
    	PORTB |= (1<<PB4);						//nSEL auf High
    	_delay_ms(5);
    	PORTB &= ~(1<<PB4);
    	SPDR = Data_L;                                                   /* Start transmission */
    	while(!(SPSR & (1<<SPIF)));                                  /* Wait for transmission complete */
    	PORTB |=(1<<PB4);
    	_delay_ms(5);
    	return;
    }
    
    void RFM12_init(void)
    {
    	// RFM12 Funkmodul:
    	
    	SPI_MasterTransmit(0x80D7);														//Enable: 433 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo
    	SPI_MasterTransmit(0x82D9);														//Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer
    	                                                                                                                                                //Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin
    	SPI_MasterTransmit(0xA67C);														//Frequenz 434,15 Mhz
    	SPI_MasterTransmit(0xC623);														//Baudrate 9600kBps
    	SPI_MasterTransmit(0x90C0);														//LNA Gain=MAX; Pin=nInt; RX Bandwidth=67 khz; VDI=Fast; DRSSI=-103 dB
    	SPI_MasterTransmit(0xC2AC);													//Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow
    	SPI_MasterTransmit(0xCA80);														//FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset; Sensitivity=High
    	                                                                                                                                                //Disable:FIFO Fill Enabled
    	SPI_MasterTransmit(0xC483);														//Enable: AFC Mode; AFC; Frequency Offset Register
    	                                                                                                                                                //Disable: High Accuracy; Strobe
    	SPI_MasterTransmit(0x9820);														//Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz
    	SPI_MasterTransmit(0xE000);														//WakeUp timer = 0ms
    	SPI_MasterTransmit(0xC800);														//Duty Cycle = Infinity % OFF
    	SPI_MasterTransmit(0xC000);														//Low Battery = 2,2V; Clock Pin = 1Mhz
    	SPI_MasterTransmit(0xCED4);														//Synchron Pattern
    	SPI_MasterTransmit(0xCC57);														//PLL Settings
    	
    	
    	SPI_MasterTransmit(0x82C8);														//Empfänger aktivieren
    	SPI_MasterTransmit(0xCA83);														//FIFO einschalten
    	_delay_ms(200);
    	SPI_MasterTransmit(0x0000);														//Status zurückstellen
    	return;
    }
    
    
    int main(void)
    {
    	//-----------------------------------------RFM 12------------------------------------------------------
    	
    	SPI_MasterInit();																//SPI als Master konfigurieren
    	RFM12_init();																	//RFM 12 initialisieren
    	
    	_delay_ms(200);																	//200ms Warten
    	
    	// USART - Serielle Schnittstelle
    
    	UCSRB |= (1<<TXEN);																// USART - Transmitter einschalten
    
    	// - Baudrate  auf 2400bps einstellen
    	UBRRH = 0x01;																	// UBRRH mit Baudrate für 2400bps (Bits 8 - 11) -416
    	UBRRL = 0xA0;																	// UBRRL mit Baudrate für 2400bps (Bits 0 - 7)
    	
    	
    	
    	PORTB &= ~(1<<PB4);																//nSel auf 0 -> RFM12 wird selektiert
    	_delay_us(100);																	//100µs warten
    	
    	while(1)
    	{
    		if(PB6 == 1)
    		{
    			SPI_MasterTransmit(0xb000);
    			while (!(UCSRA & (1<<UDRE)))												// Warten bis die Daten des letzten Vorganges fertig verarbeitet sind
    			{
    				
    			}
    			UDR = SPDR;																	// Daten übertragen 
                                                               //HIER VERMUTE ICH EINEN FEHLER...WIE LESE ICH DEN FIFO RICHTIG AUS? 
    			
    		}
    	}
    }

    VIELEN DANK und Liebe Grüsse,
    Stefan

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    01.01.2014
    Beiträge
    7
    Hallo Stefan,

    Ich bin mir ziemlich sicher, dass dies nicht dein Problem auslöst, aber mir ist in deinem Sender-Programm-Auszug folgendes aufgefallen. Du verwendest für die Variable i um festzustellen, ob eine gewisse Zeitspanne vergangen ist. In der Hauptschleife des Programms fragst du dann unter Verwendung des == Operators ab, ob diese Variable einen gewissen Wert (in dem gezeigten Codebeispiel den Wert 61) beträgt. Da du die Variable i in der Hauptschleife liest, aber im Interrupt beschreibst könnte es beim Auslesen zu einer sogenannten Race-Condition kommen. Dadurch kann ein falscher Wert ausgelesen und im worst case der Fall i = 61 überhaupt nicht oder erst verspätet eintreten. Um die Race-Condition zu verhinden gibt es zwei Möglichkeiten:

    1) Temporäres Abschalten der Interrupts beim Auslesen der Variable i (Am Besten)
    Code:
    while(1)
    {
      cli(); // disable interrupts
      int const tmp_i = i;
      sei(); // enable interrupts
    
      if(tmp_i==61)
      { 
      // ... do stuff
    Dadurch wird die Race-Condition verhindert.

    2) Den >= Operator verwenden (Besser als nichts)
    Code:
    while(1) {
    
      if(i>=61)
      { 
      // ... do stuff
    Damit werden die Effekte der Race-Condition vermindert. Dennoch sollte man Variante 1 bevorzugen.

    Im Empfänger-Programm ist mir aufgefallen, dass du die nSEL-Leitung vor der Hauptschleife auf '0' setzt.
    Code:
    	// - Baudrate  auf 2400bps einstellen
    	UBRRH = 0x01;																	// UBRRH mit Baudrate für 2400bps (Bits 8 - 11) -416
    	UBRRL = 0xA0;																	// UBRRL mit Baudrate für 2400bps (Bits 0 - 7)
    	
    	
    	
    	PORTB &= ~(1<<PB4);																//nSel auf 0 -> RFM12 wird selektiert
    	_delay_us(100);																	//100µs warten
    	
    	while(1)
    Die nSEL Leitung ist beim RFM12b meines Wissens nach aber kein Eingang, mit dem der RFM12b an sich ein- bzw. ausgeschalten wird sondern dient zur Aus/Anwahl des RFM12b während der SPI-Kommunikation mit dem RFM12B. Notwendig wird dies z.B. in einem System, in dem mehrere SPI-Slaves mit dem Microcontroller verbunden sind. Die Auswahl, mit welchem SPI-Slave der Mikrocontroller-SPI-Master kommunizieren will, erfolgt dann über das Setzen der "nSEL"-Leitung des jeweiligen SPI-Slave.

    Und beim weiteren Analysieren des Empfängers ist mir noch aufgefallen, dass du nur dann versuchst, etwas aus dem RFM12b auszulesen, wenn die Bedingung PB6 == 1 erfüllt ist. Abgesehen davon, dass ich den Sinn der Bedingung nicht verstehe (Denn PB6 = MISO = Eingang der SPI-Schnittstelle am SPI-Master und sollte daher mit SDO des RFM12b verbunden sein - Wie soll die Abfrage ob dieser Pin = 1 ist damit zusammenhängen, ob ein Byte empfangen wurde?) sehe ich noch ein ganz anderes Problem: PB6 ist in der Datei iom32.h so definiert:
    Code:
    #define PB6     6
    Damit übersetzt sich
    Code:
    if(PB6 == 1)
    zu
    Code:
    if(6 == 1)
    Diese Bedingung kann niemals wahr sein, daher wird der zugehörige Code nie ausgeführt und keine Daten über die serielle Schnittstelle versendet. Wenn du wirklich abfragen willst, ob am Pin 6 von PORTB der Wert 1 anliegt so funktioniert das so:
    Code:
    if(PINB & (1<<PB6))
    Hoffe, dir damit weitergeholfen zu haben. Viel Erfolg

Ähnliche Themen

  1. RFM12 Funkmodul Baudrate einstellen
    Von stfan1409 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 11.12.2011, 20:38
  2. RFM12 Funkmodul für IO Übertragung?
    Von Powell im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 15.04.2011, 18:49
  3. Frage zu Funkmodul RFM12
    Von Henry im Forum Elektronik
    Antworten: 6
    Letzter Beitrag: 18.02.2010, 23:35
  4. Funkmodul RFM12
    Von Thomas$ im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 31
    Letzter Beitrag: 31.07.2009, 11:55
  5. RFM12 Funkmodul mit ADUC831
    Von max_racing im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 0
    Letzter Beitrag: 29.10.2007, 18:47

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •