Ik heb een tweetal RFM70's gekocht, maar ik heb nog nooit met SPI gewerkt. Ik heb mij dus ingelezen over de werking van SPI, en snap dit redelijk maar de precieze zaken die verijst zijn voor de communicatie tussen twee pics (16f690) zijn mij nog niet bekend.

Het doel:

Simpelweg wat gegevens kunnen sturen van de ene 16f690 naar de andere 16f690 met behulp van twee RFM70's.

De gegevens die van nut kunnen zijn:
Datasheet RFM70
Datasheet 16f690
Handige informatie van voti

Het probleem is nu dat ik dit alles graag in mikroc zou programeren, daar zit al een spi library bij.

Voor versturen dacht ik het volgende te moeten doen:
Een hoog signaal op de CE pin
CSN moet aangestuurd worden worden maar hoe weet ik niet
SCK wordt geregeld door de library net als MOSI en MISO
Hoe ik IRQ moet gebruiken is mij ook nog niet duidelijk

Daarnaast word in de datasheet over een aantal andere instellingen gesproken maar ik weet niet in hoeverre mikroc dit al regelt.

Het zou dus heel fijn zijn als iemand mij op weg weet te helpen.

Edit:
Ik vond dit:
An RFM70 module must be used with a microcontroller that initializes and operates the module. By itself the module can not be used as a 'wireless wire', although such a mode could be implemented in the microcontroller. The interface between the RFM70 and the microcontroller is a standard 4-PIN SPI interface (MISO, MOSI, CLCK, CSN) plus a CE (Chip Enable) pin. The module also provides an IRQ pin that could be used to speed up the detection of certain events within the module. The library does not used this pin. The SPI input pins are 5V-tolerant, so provided that the high level as output by the module is accpetable to the microcontroller no glue circuitry is needed to interface to a microcontroller that runs from 5 Volt. (Except for course for a regulator that provides the 3.3 Volt to power the RFM70.

Betekend dat dat ik de IRQ pin helemaal niet hoef aan te sluiten?

[Bericht gewijzigd door huub8 op (27%)]

De RF module moet vanuit de PIC chip geconfigureerd worden door over SPI commanando's te sturen; zie de VOTI code. Ik heb geen ervaring met RFM70, maar wel veel met de RFM12 gewerkt - juiste configuratie komt nogal krap om de zaak aan het werk te krijgen.

Als je IRQ niet gebruikt, dan moet de ontvangstkant steeds "pollen" of er nieuwe input - je moet dat op tijd doen om geen data te verliezen. Voordeel van gebruik IRQ is dat de RF module 'aan de bel trekt' wanneer een character ontvangen is.

Zou je een voorbeeld kunnen geven van hoe je zo'n instelling vanuit mikroc kunt sturen naar de RFM70?

Ik probeer de c library van de voti website in mikroc te krijgen, maar mikroc zegt (terecht) dat hij rfm70-config.h niet kan vinden, welke wel word genoemd in rfm70.c. Dit bestand zit wel bij de toegepaste c library, hoe moet ik dit oplossen? Gewoon die van toegepaste c library overnemen? Want dan moet ik ook weer een heleboel bestanden meenemen waar daarin weer naar wordt verwezen.

Het is dus deze regel die problemen veroozaakt:
#include "rfm70-config.h"

In de code kan ik enkel dit vinden:


//! The two main files in this libary, rfm70.h and rfm70.c,
//! are target independent. 
//! However, rfm70.c included by a file that must be provided
//! by the user. 
//! This file must provide macro's for initializing and accessing the
//! I/O pins that connect to the RFM70 module, and for
//! delays of a specified number of milliseconds and microseconds.
//! A template for this file is provided.
//!
//! \par Files
//! - rfm70.h
//! - rfm70.c
//! - rfm70-config.h

Maar hier kom ik niet echt uit, bedoelen ze dat er een template voor de config file te vinden is? Want die kan ik dan nergens vinden

op de website staat verder dit:

The library must be adapted (ported, or whathever you call it) to the platform (chip, board, compiler) you want to use it on. For some platforms a port is provided, if your platform doe snot match one of the provided platforms read the instructions in the manual. Very briefly: for C you must provide an rfm70-config.h file that declares macro's that initialize and access the I/O pins, and for delaying a specified number of microseconds and milliseconds.

[Bericht gewijzigd door Henry S. op (1%)]

De file rfm70-config.h vind ik in de Voti voorbeelden:


//
// Hi-Tech Lite include file for DB038 board with 16F887:
// using an (external) RFM70 transciever
//
// Loosely based on the example application provided by HopeRF
//
//
// $Id: rfm70-config.h,v 1.1 2011/12/24 13:47:23 Wouter Exp $
//
// (c) Wouter van Ooijen - wouter@voti.nl
//
// Copying and distribution of this file, with or without modification,
// are permitted in any medium without royalty provided the copyright
// notice and this notice are preserved.  This file is offered as-is,
// without any warranty.
//

#ifndef _DB038_RFM70_H_
#define _DB038_RFM70_H_

#include "db038.h"

#define RFM70_SCK( x )   PIN_COPY( PORTC, 0, (x) ) 
#define RFM70_MOSI( x )  PIN_COPY( PORTC, 1, (x) )
#define RFM70_MISO       ( RC2 )
#define RFM70_CSN( x )   PIN_COPY( PORTC, 3, (x) )
#define RFM70_CE( x )    PIN_COPY( PORTC, 4, (x) )

#define RFM70_PIN_DIRECTION { \
   TRISC0 = 0; \
   TRISC1 = 0; \
   TRISC2 = 1; \
   TRISC3 = 0; \
   TRISC4 = 0; \
}

#define RFM70_WAIT_US( x ) WAIT_US( x )
#define RFM70_WAIT_MS( x ) wait_ms( x )

#include "rfm70.h"

#endif

Hier worden de in jouw specifieke toepassing gebruikte I/O pinnen voor de besturing van de RFM70 gedefinieerd - dus iedere keer dat het C programma statement "RFM70_SCK(1)" gebruikt, moet dat vertaald worden in het "1" zetten van de PIC poort die met de clock input van de RFM70 is verbonden. Die vertaling wordt dus in deze .h file gemaakt; je moet dus de .h file aanpassen voor jouw configuratie en compiler.

Verder worden de timing functies die in het RFM70 programma worden gebruikt gelinked naar de timing functies die jij in jouw programma ergens hebt gedefinieerd.

Allemaal tamelijk basic, maar niet gemakkelijk uit te leggen.

[Bericht gewijzigd door Henry S. op (0%)]

Die configfile moet je dus zelf maken, je kunt die van voti overnemen een aanpassen, dan opslaan als rfm70-config.h in je projectmap.

In die configfile geef je de gebruikte pinnen aan, en 2 delayfuncties.

Je gebruikt dan niet de SPI lib's van microC, maar de SPI implementatie van de RFM70 libs. Niet erg, als het maar werkt.

Je kunt ook met de datasheet van de module in de hand zelf SPI communicatie met het ding opzetten, en b.v. het statusgregister lezen (NOP sturen en kijken wat er terugkomt).

Trouwens: 5V tolerant I/O moet je met een korreltje zout nemen. De voeding blijft dan geen 3v3 namelijk. Dus het is het beste je hele systeem op 3,3V te laten draaien (Of op z'n minst een weerstandje op te nemen in MOSI en clk, of een weerstandsdeler).

Oke, ik denk dat ik het dan allemaal wel snap, maar betekend dit dan ook dat ik de spi softwarematig doe, en dus willekeurige pinnen kan gebruiken of niet?

Ja, je kunt by de softwarematige SPI sturen
willekeurige pinnen gebruiken. De SPI is dan wel veel langzamer.
Ik heb het ding aan de gang onder JAL en daar kan ik de SPI-mode kiezen. Met de hardware interface van een 16F877 moet ik dan mode 0 kiezen.
Nog een tip: De init van voti zet het zendvermogen op de hoogste stand (+10dB)
Meestal overstuur je hiermee je ontvanger en reageert hij niet.

Je kunt ook de lib van critacrof gebruiken (Al is die voor AVR, hij valt aan te passen). Die is kleiner (kan ook wat minder, maar het noodzakelijke werkt goed), en de SPI implementatie heeft een apparte file. Dus daar kun je vrij makkelijk hardware SPI van maken. (Is het oorspronkelijk ook, maar dan op een Atmega AVR. Ik heb het aangepast voor een attiny2313, die geen echte SPI hardware heeft maar alleen een USI)

Nu weet ik niet het grote verschil tussen de RFM 70 en de RFM 12 maar hier staat een project in mikroC met de RFM 12 miss dat dit je op weg kan helpen

http://www.libstock.com/projects/view/166/application-project-on-rfm12…

Ik denk dat ik het eerst toch maar gewoon met die van voti probeer, aangezien ik daar nu al verder mee ben. Ik heb al wat zaken aangepast, maar ik kwam een paar fouten tegen die ik niet goed kan oplossen:

ik kwam meerdere keren dit tegen:
418 307 Illegal typecast '' '' rfm70.c

vanwege dit soort regels:
(void)rfm70_SPI_RW( reg ); // select register
Ik heb daar gewoon void weggelaten, wat in eerste instantie niet uitmaakte maar nadat ik het programma opnieuw opstarte compleerde hij hierdoor opeens wel.

Nu zit ik nog met een paar fouten:

470 373 Const expression expected rfm70.c
door
unsigned char st = 0x80 & rfm70_register_read( RFM70_REG_STATUS );

509 382 Illegal pointer conversion to double rfm70.c
door
rfm70_buffer_write( i,WriteArr, 4 );
(het komt door de WriteArr)

734 315 Invalid expression rfm70.c
door
unsigned char val = rfm70_register_read( RFM70_REG_RF_SETUP );

Hoe kan ik dit oplossen?

Edit: een paar zaken al opgelost, die zijn doorstreept, zie volgende post voor toelichting van de ene fout die hier boven nog staat

De fout treed dus op in dit stukje code:

   for( i = 0; i <= 8; i++ ){ //reverse!
      for( j = 0; j < 4; j++ ){
         WriteArr[ j ]=( Bank1_Reg0_13[ i ]>>(8*(j) ) )&0xff;
      }  
      rfm70_buffer_write( i,WriteArr, 4 );
   }

En komt door de WriteArr in rfm70_buffer_write( i,WriteArr, 4 );

Dat is dus blijkbaar een pointer, een * voor WriteArr zetten verhelpt de fout maar leverd deze warning op:

510 1508 Implicit conversion of int to ptr rfm70.c

Maar dan was het dus eigenlijk toch een int, en geen pointer lijkt mij, dus ik weet niet of dit de juiste oplossing is en of het dan wel goed gaat in de rest van de code.

Edit:

Ik krijg nu ook deze foutmelding:
0 359 Unresolved extern 'PORTC_SHADOW' rfm.c
door deze aanroep
rfm70_init();

Het lijkt mij dat dit door de code uit het db038 bestand komt (dit bestand is al door mij aangepast trouwens, en er wordt dus naar gelinked in de config file):

//
// Hi-Tech Lite include file for DB038 board with 16F887:
// basic functions
//
// $Id: db038.h,v 1.1 2011/12/24 13:47:19 Wouter Exp $
//
// (c) Wouter van Ooijen - wouter@voti.nl
//
// Copying and distribution of this file, with or without modification,
// are permitted in any medium without royalty provided the copyright
// notice and this notice are preserved.  This file is offered as-is,
// without any warranty.
// 



#define MHZ *1000L            // number of kHz in a MHz
#define KHZ *1                // number of kHz in a kHz
#define XTAL_FREQ ( 20 MHZ )  // we run at 20 MHz



   #define rom 

   #define WAIT_US( x ) _delay( x * ( XTAL_FREQ / ( 4 MHZ )))
   void wait_ms( unsigned int x );

   extern unsigned char PORTA_SHADOW;
   extern unsigned char PORTB_SHADOW;
   extern unsigned char PORTC_SHADOW;
   extern unsigned char PORTD_SHADOW;
   extern unsigned char PORTE_SHADOW;

   #define PORTA_FLUSH { PORTA = PORTA_SHADOW; }
   #define PORTB_FLUSH { PORTB = PORTB_SHADOW; }
   #define PORTC_FLUSH { PORTC = PORTC_SHADOW; }
   #define PORTD_FLUSH { PORTD = PORTD_SHADOW; }
   #define PORTE_FLUSH { PORTE = PORTE_SHADOW; }

   #define PIN_SET( port, b ) do { \
      port##_SHADOW |= ( 1 << (b) ); \
      port = port##_SHADOW; \
   } while(0)

   #define PIN_CLEAR( port, b ) do { \
      port##_SHADOW &= ( 0xFF ^ ( 1 << (b) )); \
      port = port##_SHADOW; \
   } while(0)

   #define PIN_COPY( port, b, v ) do { \
      if( v ){  \
   	     PIN_SET( port, (b) ); \
      } else { \
        PIN_CLEAR( port, (b) ); } \
   } while(0)
   	
   #define PORT_SET( port, v ) do { \
      port##_SHADOW = ( (v) ); \
      port = port##_SHADOW; \
   } while(0)   



#define INPUT 1
#define OUTPUT 0

#define  PORTA_DIRECTION TRISA
#define  PORTB_DIRECTION TRISB
#define  PORTC_DIRECTION TRISC
#define  PORTD_DIRECTION TRISD
#define  PORTE_DIRECTION TRISE

#define PIN_DIRECTION( port, pin, d ) do { \
  if( (d) == INPUT ){  \
      port##_DIRECTION |= ( 1 << (pin) ); \
   } else { \
      port##_DIRECTION &= ( 0xFF ^ ( 1 << (pin) )); \
   } \
} while(0)

#define PORT_DIRECTION( port, d ) do { \
    if( (d) == INPUT ){  \
      port##_DIRECTION = 0xFF; \
   } else { \
      port##_DIRECTION = 0x00; } \
} while(0)

void disable_analog_functions( void );

Ik zit niet zo in PIC C...

Je pointer ding: Die functie wil een adres hebben. Dus je kan 'm de naam van een array voeren (dat is een pointer naar het 0e element), of &ArrayNaam[0], dat doet hetzelfde. Dus geen *VariabeleNaam, want dan gaat het fout.

Pointers samengevat:
[code=C]
uint8_t pietje; // is een variabele op een bepaald adres, zeg 800.
Pietje = 16; // pietje heeft nu de waarde 16.
uint8_t* hierwoontpietje; // hierwoontpietje is een pointer, nog ongeinitialiseerd.
hierwoontpietje = &pietje; // hierwoontpietje wijst nu naar het adres van pietje, ofwel 800.
uint8_t waarde = *hierwoontpietje; // waarde wordt nu de waarde van pietje, ofwel 16.

// en fout:
hierwoontpietje = 802; //(laat de pointer naar adres 802 wijzen)
waarde = *pietje; //(stopt de inhoud van adres 16 in de variabele waarde)
[/code]

Oke, maar als ik dit doe:

rfm70_buffer_write( i,&WriteArr[0], 4 );

Geeft hij de foutmelding:

510 384 Illegal pointer conversion rfm70.c

Net als wanneer ik dit doe:

rfm70_buffer_write( i,WriteArr, 4 );

Alleen als ik dit doe geeft hij geen foutmelding:

rfm70_buffer_write( i,*WriteArr, 4 );

Maar wel weer een warning, namelijk deze:

510 1508 Implicit conversion of int to ptr rfm70.c

Maar jij zegt dat die laatste dus niet de juiste manier is, of begrijp ik het verkeerd?

Overigens zit ik dus ook nog met de 0 359 Unresolved extern 'PORTC_SHADOW' rfm.c fout

[Bericht gewijzigd door Henry S. op (8%)]

Die WriteArr is wel een array?

Verder zul je vrees ik toch ff op iemand moeten wachten die wel PIC's in C programmeert, ik prog alleen AVR's in C (of asm, eventueel), en PIC's in PICBASIC.

Hoe zit die funcite rfm70_buffer_write in elkaar? Wat is daar de (prototype) defenitie van?

Die functie ziet er als volgt uit:

void rfm70_buffer_write( 
   char reg, 
   const unsigned char *pBuf, 
   unsigned char length 
){
   unsigned char i;
   if( reg < RFM70_CMD_WRITE_REG ){
      reg |= RFM70_CMD_WRITE_REG;      
   }  
   RFM70_CSN( 0 );                     // Set CSN low, init SPI tranaction
   rfm70_SPI_RW( reg );         // Select register to write tio write
   for( i = 0; i < length; i++ ){      // write all bytes in buffer(*pBuf)
      rfm70_SPI_RW( *pBuf++ );  // write one byte
   }   
   RFM70_CSN( 1 );                     // Set CSN high again
}

Ja, die moet inderdaad een adres als 2e argument krijgen. Dus een ArrayNaam of een &ArrayNaam[0]. (Waarbij ik de laatste persoonlijk duidelijker vind, omdat die & aangeeft dat je een adres doorgeeft en de [0] dat het een array is.)

Gooi anders even al je code in een zipje op het uploadarchief. (Vooral handig voor hen die wél beter in PIC C zitten.)

Dit soort warnings zijn heel specifiel voor bepaalde compilers - je zou je geluk eens kunnen proberen op het forum van jouw compiler leverancier. Ik gebruik altijd MicroChips C18 compiler en die doet ook vrij moeilijk als het om pointers gaat. Een array van de dagen in de week wordt bv als volgt gedeclareerd:
const rom char* days[7] = {"maandag ","dinsdag ","woensdag ","donderdag ","vrijdag ","zaterdag ","zondag "};
Je moet, om warnings te voorkomen, aan de compiler vertellen dat de array in het programma geheugen staat (=rom); dit is een vast geprogrammeerd array.
Een array in ram geheugen (dus te beschrijven) wordt dan gedeclareerd als:
const ram char* days[7];
Dit om aan te geven hoe lastig het kan worden. Dit soort zaken vind je door de documentatie van jouw compiler, en het relevante forum, heel goed te bestuderen. Je kan daarom ook zelden programma's van anderen een op een gebruiken - altijd fine tuning nodig naar jouw PIC chip, jouw hardware en jouw compiler.

Succes

Hoi Huub, ik ben benieuwd of je nog wat verder gekomen bent. Ik zit namelijk met hetzelfde probleem als jij van je post op 13maart. Ik heb het wel opgelost, maar dat levert weer een ander probleem op, ik ben dus niet tevreden over mijn oplossing. Ik ben benieuwd naar de jouwe.

Ik heb het nog even laten liggen want ik kwam er niet verder mee, maar ben wel van plan het binnenkort nog eens te proberen. Wat is jouw oplossing dan?

Mischien kun je iets leren van mijn project.
Het is geschreven in JAL, maar als je C kent dan is JAl wel te volgen. De ZIP file bevat ook een .doc file die heel wat over de werking van de RFM70 vertelt.
Ditectlink naar de zip file:

http://www.henkzelf.nl/PICprojects/RFM70_rel02.zip

Met vragen: wacht 14 dagen, ik ben eerst op vakantie.

Waar het probleem ligt in mikroC is dat de buffer_write functie wordt gedeclareerd met een pointer naar een const char. De aanroep wordt op verschillende plaatsen gedaan met een een gewone char. Ik heb de twee versies gemaakt van de functie, met en zonder const. Nu heb ik de aanroep van de functies aangepast en is dit geen probleem meer. Dit alleen niet de meest mooie oplossing natuurlijk. Maar nu heb ik weer een ander soortgelijk probleem. Misschien kunnen we mikroE eens om raad vragen.