Hoebi1
07.12.2013, 19:38
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:
#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:
#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
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:
#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:
#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