Skocz do zawartości

Atmega8+rfm12b- budowa układu według forbotowskiego poradnika


nariox

Pomocna odpowiedź

Czy jakaś bratnia dusza zechciałaby mi pomóc w ustawieniu i odpaleniu modułów rfm12b z atmega8?

Posługuję się poradnikiem zamieszczonym na blogu, uart ruszył, test połączenia z rfm12b zdany,ale niestety nic nie moge odebrać. Nie wiem gdzie szukać przyczyny.

Układ uruchamiam na kwarcu zewnętrznym wprowadziłem niewielkie zmiany w stosunku do oryginalnych bibliotek, żeby uruchomić UART i to w zasadzie tyle- Czy wielkość anteny ma duże znaczenie? Układy składam na płytkach stykowych, Antene uciąłem drut około 165mm.

Moduły na 868 w wersji smd(dolutowalem goldpiny) .Poniżej zamieszam dokładne kody w C dla nadajnika i Odbiornika.

Odbiornik:

/*
* slave_rfm12b_v2.c
*
* Created: 2016-02-02 18:09:29
*  Author: nari0x
*/ 


/*
* main.c
*
*  Created on: 19-02-2014
*      Author: Piotr Rzeszut
*  
* Description: Przykład komunikacji z modułem RFM12B
*/
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <avr/interrupt.h>

#include "RFM12B.h"
#include "uart.h"

char bufor[65];


int main(void){
_delay_ms(500);

Rfm_spi_init();//inicjalizacja magistrali SPI

Rfm_init();//wstępna konfiguracja układu RFM12B

DDRC |= (1<<PC5);        //dodałem te dwie linijki żeby wiedzieć kiedy program wykona się do końca- na końcu gasi diodę
PORTC |= (1<<PC5);



DDRB &= ~((1<<PB0)|(1<<PB1));//konfiguruję piny PB0-1 jako wejście
PORTB |= (1<<PB0)|(1<<PB1);//i włączam podciąganie

uint8_t data;

while(1){

	//sprawdzam przyciski i ustawiam odpowiednie bity w bajcie do nadania
	data = 0;
	if(!(PINB&(1<<PB0))){        // zmieniłem piny na których są przyciski, bo kolidowalo z obslugą spi
		data |= 1;

	}	
	if(!(PINB&(1<<PB1))){
		data |= 2;
	}
	if(data==0)continue;//jeśli nic nie wciśnięto to rozpoczynamy pętlę od początku

	//włączamy nadajnik
	Rfm_xmit(POWER|EN_TRANSMISSION|EN_SYNTH|EN_OSC|DIS_CLKO);
	//nadajemy 3 bajty synchronizacji (0xAA)
	//dwa pierwsze są już domyślnie umieszczone w buforze nadawczym po komendzie włączającej nadajnik
	Rfm_ready_wait();
	Rfm_xmit(TX_WRITE|0xAA);
	//następnie kolejny bajt synchrnoizacji (0x2D)
	Rfm_ready_wait();
	Rfm_xmit(TX_WRITE|0x2D);
	Rfm_ready_wait();
	//oraz definiowalny bajt synchronizacji (czyli nasz adres)
	Rfm_xmit(TX_WRITE|0xD4);
	Rfm_ready_wait();
	Rfm_xmit(TX_WRITE|data);
	Rfm_ready_wait();
	//oraz pusty bajt - konieczny by poprawnie zakończyć trnasmisję
	Rfm_xmit(TX_WRITE|0xAA);
	Rfm_ready_wait();
	//następnie czekamy na zakończenie transmisji
	uint16_t status;
	do 
	{
		status=Rfm_xmit(STATUS_READ);
	} while (!(status&M_TX_READY));
	//i wyłączamy nadajnik
	Rfm_xmit(POWER|DIS_CLKO);
	_delay_ms(100);
	PORTC &= ~(1<<PC5);

}

return 0;
}

zmodyfikowany RFM12b.c:

/*
* RFM12B.c
*
*  Created on: 19-02-2014
*      Author: Piotr Rzeszut
*  
* Description: Funkcje do obsługi układu RFM12B z poziomu procesora AVR
*/
#include "RFM12B.h"

void Rfm_spi_init(void){
SPI_DDR |= (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_SS);//konfiguracja kierunku i podcigania linii SPI
SPI_PORT |= (1<<SPI_MISO);
//do poprawnej pracy modułu SPI w procesorze linia SS musi być ustawiona jako wyjście

SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);//SPI w trybie master z podziałem zegara przez 64 


CS_PORT |= (1<<CS_RFM);//dezaktywacja układu RFM12B
CS_DDR |= (1<<CS_RFM);//konfiguracja kierunku linii CS
}

uint16_t Rfm_xmit(uint16_t data){
//na początek rodzielamy dane na 2 bajty
uint8_t msb, lsb;
lsb = data;
msb = data>>8;
CS_PORT &= ~(1<<CS_RFM);//aktywujemy linię CS układu
//teraz wysyłamy 2 bajty jednocześnie odbierając 2 bajty z układu
SPDR = msb;
while(!(SPSR&(1<<7)));
msb = SPDR;
SPDR = lsb;
while(!(SPSR&(1<<7)));
lsb = SPDR;
//_delay_ms(1);
CS_PORT |= (1<<CS_RFM);//dezaktywujemy linię CS układu
//i zwracamy odebrane dane
return( (((uint16_t)msb)<<8)+((uint16_t)lsb) );
}

void Rfm_init(void){
Rfm_xmit(SW_RESET);//resetuję programowo układ RFM12B
_delay_ms(250);

//inicjalizacja RFM12B
//ustawienie pasma 868MHz, konfiguracja FIFO
Rfm_xmit(CONFIGURATION|EN_DATA_REG|EN_FIFO|BAND_868|CAP_12_0);
//włączenie oscylatora
Rfm_xmit(POWER|EN_OSC|DIS_CLKO);
//ustawienie pasma (musi być takie samo w nadajniku i odbiorniku)
//Dla naszego układu częstotliwość musi zawierać się w przedziale 860480000-879515000Hz i musi być podawana ze skokami 5000Hz
Rfm_xmit(FREQUENCY|RF12_FREQUENCY_CALC_868(868000000UL));
//ustawienie prędkości transmisji danych (musi być takia sama w nadajniku i odbiorniku)
Rfm_xmit(BAUD|BAUD_4800);
//ustawienie pasma 134kHz i parametrów odbiornika
Rfm_xmit(RECEIVER|P20_VDI|BW134|LNA_0|RSSI_103);
//ustawienie cyfroiwego filtra danych i opcji odzyskiwania zegara
Rfm_xmit(DATA_FILTER|AUTO_CR|DIGITAL_F|DQD_4);
//reset bufora FIFO, konfiguracja synchronizacji za pomocą 2 bajtów, ustawienie generowania przerwania FFIT po odebraniu 8 bitów
Rfm_xmit(FIFO_RST|FIFO_IT_8|FIFO_SYNC|HS_RST_DIS);


//konfiguracja kontrolera częstotliwości
Rfm_xmit(AFC|KEEP_RX|REST_OFF|EN_FOFFSET|EN_AFC);
//konfiguracja nadajnika i jego mocy (na ustawienie maksymalne)
Rfm_xmit(TRANSMITER|FSK_PHASE_0|FSK_DF_90K|OUT_P_0);
//konfiguracja pętli PLL
Rfm_xmit(PLL|PLL_DH_DIS|SEL_CLK_2_5|MAX_BAUD_256);

//wyłączenie timera wakeup
Rfm_xmit(WAKEUP_TIM|WUT_X_2_0|0);
//wyłączenie oszczędzania energii
Rfm_xmit(LOW_DC|LOW_DC_DIS);
//ustawienie monitora napięcia na 2,2V
Rfm_xmit(BOD_CLK|CLK_5_00|BOD_2_2);
}

uint8_t Rfm_ready_wait(void){
uint8_t i=0;

CS_PORT &= ~(1<<CS_RFM);//załączam pin CS układu
_delay_us(10);//czekam nieco aby układ mógł zareagować

while(!((1<<SPI_MISO)&SPI_PIN)){//następnie co 1ms sprawdzam, czy układ jest wolny, tzn, czy wystawił na linii MISO 1.
	_delay_ms(5);
	if((++i)==200){
		return 1;//po ok. 200ms przerywam oczekiwanie i zwracam 1 - czyli sygnalizuję błąd
	}
}
return 0;//jeśli pętal zostanie przerwana z powodu wystąpienia stanu wysokiego na linii MISO to zwracam 0 - nie ma błędu
}

zmieniłem tylko wartosci w pętli ostatniej,gdzie doczytalem ze czasem sa problemy z tego powodu

RFM12b.h- zmienione zostały tylko definicje pinów pod które podpięty jest rfm12b

/*
/*
* RFM12B.h
*
*  Created on: 10-06-2013
*      Author: Piotr Rzeszut
*  
* Description: Funkcje do obsługi układu RFM12B z poziomu procesora AVR
*/
#ifndef RFM12B_H
#define RFM12B_H

#include <avr/io.h>
#include <util/delay.h>
#include "RFM12B_reg.h"

//definicje pinów IO, na których podłączona jest magistrala SPI
#define SPI_DDR DDRB
#define SPI_PORT PORTB
#define SPI_PIN PINB

#define SPI_SS PB2
#define SPI_MOSI PB3
#define SPI_MISO PB4
#define SPI_SCK PB5

//pin CS możemy wybrać dowolnie
#define CS_DDR DDRB
#define CS_PORT PORTB
#define CS_RFM PB2

void Rfm_spi_init(void);

uint16_t Rfm_xmit(uint16_t data);

void Rfm_init(void);

uint8_t Rfm_ready_wait(void);

#endif //RFM12B_H

W rf12b_reg.h nic nie zmienialem

Kod dla obiornika:


/*
* main.c
*
*  Created on: 19-02-2014
*      Author: Piotr Rzeszut
*  
* Description: Przykład komunikacji z modułem RFM12B
*/
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <avr/interrupt.h>

#include "RFM12B.h"
#include "uart.h"

char bufor[65];



//--------------------------------------------------------------------------------------------------------
//Kod dla układu MASTER
//--------------------------------------------------------------------------------------------------------
int main(void){

Rfm_spi_init();//inicjalizacja magistrali SPI
uart_init(9600);//inicjalizacja USART
sei();//włączamy przerwania do obsługi uart

uart_puts("\r\n\r\nRFM12B - RECEIVER\r\n");//wyświetlamy powitanie

Rfm_init();//inicjalizujemy układ RFM12B

Rfm_xmit(SYNC_PATTERN|0xD4);
//ustawiamy programowalny bajt synchronizacji na wartość 0xD4
//wykorzystamy tę funkcjonalność do adresowania wielu układów

//włączamy odbiornik
Rfm_xmit(POWER|EN_RX|EN_BASEBAND|EN_OSC|DIS_CLKO);
_delay_ms(5);

while(1){
	//para komend powodująca w efekcie działania reset synchronizacji odbiornika
	Rfm_xmit(FIFO_RST|FIFO_IT_8|HS_RST_DIS);
	Rfm_xmit(FIFO_RST|FIFO_IT_8|EN_AFT_SYNC|HS_RST_DIS);

	uint8_t timeout=Rfm_ready_wait();//oczekujemy na odebranie przez układ danych
	if(timeout){//i w zależności od tego czy układ odpowiedział
		//albo wyświetlamy informacje o braku odebranych danych
		uart_puts("NO INCOMING DATA\r\n");
	}else{
		//albo odbieramy dane z bufora
		uint8_t data=Rfm_xmit(FIFO_READ);
		//i wyświetlamy je
		sprintf(bufor,"INCOMING DATA:%d\r\n",data);
		uart_puts(bufor);
	}
}

return 0;
}

Inicjalizacja UART:

(uart.c)

/*
* uart.c
*
*  Created on: 23-05-2013
*      Author: Piotr Rzeszut
*  
* Description: Przykład obsługi UART z zastosowaniem przerwań i bufora kołowego
*/
#include "uart.h"

volatile char UART_RX_BUF[UART_BUFFER_SIZE];
volatile uint8_t uart_rx_h=0;
volatile uint8_t uart_rx_t=0;

volatile char UART_TX_BUF[UART_BUFFER_SIZE];
volatile uint8_t uart_tx_h=0;
volatile uint8_t uart_tx_t=0;

volatile uint8_t rx_overrun=0;

void uart_init(uint16_t baud){
//wyliczamy wartość rejestru UBRR
uint16_t ubrr_cal=F_CPU/16/baud-1;
//konfiguracja baud
UBRRH = (uint8_t)(ubrr_cal>>8);
UBRRL = (uint8_t)ubrr_cal;
//włączenie UART

UCSRC =(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
}

void uart_putc(char data){
uint8_t new_h=(uart_tx_h+1)&UART_BUFFER_MASK;
while(new_h==uart_tx_t);
UART_TX_BUF[new_h]=data;
uart_tx_h=new_h;
UCSRB |= (1<<UDRIE);
}

void uart_puts(char *string){
char c;
while((c=*string++))uart_putc(c);
}

void uart_putint(int number, uint8_t base){
char buffer[20];
itoa(number,buffer,base);
uart_puts(buffer);
}

char uart_getc(void){
if(uart_rx_t==uart_rx_h)return 0;
uart_rx_t=(uart_rx_t+1)&UART_BUFFER_MASK;
return UART_RX_BUF[uart_rx_t];
}

uint16_t uart_getint(void){
 char odebrany=0;
 uint16_t liczba=0;
 do{
 	odebrany=uart_getc();
   if(odebrany!=0){
     if(odebrany!='\r'){//filtrujemy znak zakończenia liczby
  	uart_putc(odebrany);
       liczba*=10;
       liczba+=odebrany-'0';
     }
   }
 }while(odebrany!='\r');//jeśli odebraliśmy znak zakończenia liczby to wychodzimy z pętli  
 return liczba;//zwracamy odebraną liczbę
}

ISR(USART_RXC_vect){
uint8_t new_h=(uart_rx_h+1)&UART_BUFFER_MASK;

if(new_h!=uart_rx_t){
	uart_rx_h=new_h;
	UART_RX_BUF[uart_rx_h]=UDR;
}else{
	rx_overrun=1;
	new_h=UDR;//odczytujemy bufor, żeby nie zawiesić systemu
}
}

ISR(USART_UDRE_vect){
if(uart_tx_t!=uart_tx_h){
	uart_tx_t=(uart_tx_t+1)&UART_BUFFER_MASK;
	UDR=UART_TX_BUF[uart_tx_t];
}else{
	UCSRB &= ~(1<<UDRIE);
}
}

RFM12b.c tak samo jak w przypadku nadajnika

w pozostałych nic nie mieszałem

Czy ktoś kto bawił się tymi kodami zechciałby mi pomóc? Hardware jest chyba dobrze zrobione,PIN NIRQ zostawiam niepodłączony,reszta jak na schemacie w poradniku.

https://forbot.pl/blog/artykuly/programowanie/rfm12b-2-koniec-ciszy-eterze-id1861

Posprawdzam jeszcze raz dziś wszystko wieczorem.

Osobie która mi pomoże odwdzięczę się poza forum;)) . Dość długo już przy tym dumam i nic;(

PS: posiadm też GB P.Mirosława ,jeżeli ktoś umiałby mi pomóc zrobić z tego identyczny program jak ten w poradniku , to nie wiem jak mu się odwdzięcze

Chciałbym zrobić po prostu gotowy program i potem sobie go spokojnie przeanalizować i zmodyfikować.

rfm12b_mega8.rar

Link do komentarza
Share on other sites

Z pomocą przyszedł Green Book,po krótkich modyfikacjach programów z książki udało się odpalić i skomunikować ze sobą dwa moduły.

Trudno mi na razie powiedzieć gdzie tkwi błąd.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.