RFM70 met 18f45k22 in mikroC

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • huub8
  • Registratie: Maart 2009
  • Laatst online: 28-06-2021
Ik heb een tijd geleden eens 2 rfm70 modules gekocht in de hoop deze te kunnen gebruiken, echter lukte dat mij toen niet door gebrek aan ervaring. Nu dat ik weer een stuk meer weet leek het mij een goed idee het opnieuw te proberen, ik heb de code van voti omgeschreven naar geldige code voor de mikroC compiler, maar het werkt nog niet helemaal. Het test programmatje laat namelijk alleen de transieve led knipperen, de recieve led niet (dus of er wordt niet echt iets verstuurd, of wat er wordt verstuurd wordt niet goed ontvangen, of een combinatie).

De originele code is hier te vinden:
http://www.voti.nl/rfm70/

De code bestaat uit drie bestanden:
rfm70.h
rfm70.c
rfm70-config.h
rfm.c (het bestand waar de "main" code/test code in staat)

Ik denk dat het het makkelijkst is om voor het overzicht niet alles hierop te zetten, dus hier volgt de originele code van voti voor het testen, en mijn code. Ik denk dat de fout hier goed in kan zitten, maar ik kan hem niet vinden:

originele:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "rfm70.h"
#include "rfm70-config.h"

#define GREEN_LED( x )      PIN_COPY( PORTD, 0, !(x) )
#define RED_LED( x )        PIN_COPY( PORTD, 1, !(x) )

#define GREEN_LED_OUT()         TRISD0=0;
#define RED_LED_OUT()           TRISD1=0;


void main( void ){

    unsigned char n = 0;
    unsigned char transmit_led = 0;
    unsigned char receive_led = 0;
    unsigned char len, i, chksum, pipe;
    unsigned char rx_buf[ RFM70_MAX_PACKET_LEN ];
    const unsigned char tx_buf[17]={
       0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
       0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x78};

    ANSEL = 0;
    ANSELH = 0;

    TRISD = 0;
    TRISE = 0;
    TRISA2 = 0;
    PIN_SET( PORTA, 2 );
    PORT_SET( PORTE, 4 );
    PORT_SET( PORTD, 0xFF );
    
    ANSEL = 0;
    ANSELH = 0;
    WPUB = 0;   

    RED_LED_OUT();
    GREEN_LED_OUT();
    
    rfm70_init();

    while(1){
        wait_ms( 2 );

        RED_LED( transmit_led > 0 );
        if( transmit_led > 0 ){ transmit_led--; }

        GREEN_LED( receive_led > 0 );
        if( receive_led > 0 ){ receive_led--; }
       
        if( ++n > 250 ){
           rfm70_mode_transmit();
           rfm70_transmit_message_once( tx_buf, 17 ); 
           WAIT_US( 100 );      
           rfm70_mode_receive(); 
           transmit_led = 20;   
           n = 0;   
        }

        if( rfm70_receive( &pipe, &rx_buf, &len )){
           chksum = 0;
           for(i=0;i<16;i++){
              chksum +=rx_buf[i]; 
           }

           if(chksum==rx_buf[16]&&rx_buf[0]==0x30){
              receive_led = 20;
           }    
           rfm70_register_write( RFM70_CMD_FLUSH_RX,0 );
        }
    }
}


mijn code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "rfm70.h"
#include "rfm70.c"
#include "rfm70-config.h"

sbit GREEN_LED at LATD0_bit; // #define GREEN_LED( x ) PIN_COPY( PORTD, 0, !(x) )
sbit RED_LED at LATD1_bit;   // #define RED_LED( x )  PIN_COPY( PORTD, 1, !(x) )

#define GREEN_LED_OUT TRISD0_bit = 0; // #define GREEN_LED_OUT()  RISD0=0;
#define RED_LED_OUT TRISD1_bit = 0;   // #define RED_LED_OUT()  TRISD1=0;


void main(){

    unsigned char n = 0;
    unsigned char transmit_led = 0;
    unsigned char receive_led = 0;
    unsigned char len, i, chksum, pipe;
    unsigned char rx_buf[ RFM70_MAX_PACKET_LEN ];
    const unsigned char tx_buf[17]={
       0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
       0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x78};

    /*ANSEL = 0;
    ANSELH = 0;*/
    ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
    ANSELB  = 0;                       // Configure pins as digital
    C1ON_bit = 0;                      // Disable comparators
    C2ON_bit = 0;
    ANSELC = 0;                      // Configure AN pins as digital
    SLRCON = 0;                      // Set output slew rate on all ports at standard rate


    TRISD = 0;
    TRISE = 0;
    TRISA.B2 = 0;
    PORTA.B2 = 1; // PIN_SET( PORTA, 2 );
    PORTE = 4; // PORT_SET( PORTE, 4 );
    PORTD = 0xFF; // PORT_SET( PORTD, 0xFF );


    WPUB = 0;

    RED_LED_OUT;
    GREEN_LED_OUT;

    rfm70_init();

    while(1){
        delay_ms( 2 );

        RED_LED = transmit_led; // RED_LED( transmit_led > 0 );
        if( transmit_led > 0 ){ transmit_led--; }

        GREEN_LED = receive_led;  // GREEN_LED( receive_led > 0 );
        if( receive_led > 0 ){ receive_led--; }

        if( ++n > 250 ){
           rfm70_mode_transmit();
           rfm70_transmit_message_once( tx_buf, 17 );
           delay_us( 100 );
           rfm70_mode_receive();
           transmit_led = 20;
           n = 0;
        }

        if( rfm70_receive( &pipe, &rx_buf, &len )){
           chksum = 0;
           for(i=0;i<16;i++){
              chksum +=rx_buf[i];
           }

           if(chksum==rx_buf[16]&&rx_buf[0]==0x30){
              receive_led = 20;
           }
           rfm70_register_write( RFM70_CMD_FLUSH_RX,0 );
        }
    }
}

Acties:
  • 0 Henk 'm!

  • huub8
  • Registratie: Maart 2009
  • Laatst online: 28-06-2021
niemand?

Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 13:39

Sprite_tm

Semi-Chinees

Ik denk eerlijk gezegd dat niemand hier zin heeft om een stuk code wat je hier neerplempt met feitelijk alleen de melding 'werkt niet' te gaan debuggen. Wat heb je zelf al geprobeerd? Is je communicatie met de chip bijvoorbeeld wel werkend; kan je bijvoorbeeld de registserset uitlezen en krijg je daaruit ook wat je verwacht? Zonee, is je SPI-interface wel goed? Zoja, schrijf je er daadwerkelijk heen wat je schrijft? Etc, enz.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 10-10 11:30

Infant

It's a floating Dino!

Zo, de datasheet is even een 1:1 kopie van de nRF24L01 niet te zuinig.

Als hij toevallig ook echt hetzelfde is, kan ik misschien helpen.

Bij mij kwam het switchen tussen receive en send redelijk nauw qua timing. Je moest er minimaal 200us wachten.

Sommige pakket lengtes kreeg ik gewoon no way over, omdat er gewoon teveel meuk in deze flat op 2.4GHz zit. De enige manier om stabiel iets de doen was naar het laatste kanaal te gaan, en de zendgrootte rond de 16 bytes te houden.

Je kunt beginnen met dus kleine pakketjes te versturen, die hebben meer kans.
Alle vormen van checksums uit doen, zodat je ook gewoon bogus data binnen krijgt...

And then work your way up from there....

Acties:
  • 0 Henk 'm!

  • huub8
  • Registratie: Maart 2009
  • Laatst online: 28-06-2021
oke, ik heb geprobeerd wat registers uit te lezen om te kijken of er iets van mogelijk zinnige data terug komt, dit blijkt niet echt het geval. bij de drie registers krijg ik 0x08 terug. Dit is de code:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "rfm70.h"
#include "rfm70.c"
#include "rfm70-config.h"

void main(){

   unsigned char n = 0;
   char returnvalue;
   unsigned char transmit_led = 0;
   unsigned char receive_led = 0;
   unsigned char len, i, chksum, pipe;
   unsigned char rx_buf[ RFM70_MAX_PACKET_LEN ];
   const unsigned char tx_buf[17]={
     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
     0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x78};

   ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
   ANSELB  = 0;                       // Configure pins as digital
   C1ON_bit = 0;                      // Disable comparators
   C2ON_bit = 0;
   ANSELC = 0;                      // Configure AN pins as digital
   SLRCON = 0;                      // Set output slew rate on all ports at standard rate

   WPUB = 0;

   UART1_Init(9600);               // Initialize UART module at 9600 bps
   Delay_ms(100);                  // Wait for UART module to stabilize
   
   returnvalue = rfm70_register_read( RFM70_REG_STATUS );
   UART1_Write(returnvalue);
   returnvalue = rfm70_register_read( RFM70_REG_CONFIG );
   UART1_Write(returnvalue);
   returnvalue = rfm70_register_read( RFM70_REG_RF_SETUP );
   UART1_Write(returnvalue);
   
   rfm70_init();
   delay_ms( 500 );

   returnvalue = rfm70_register_read( RFM70_REG_STATUS );
   UART1_Write(returnvalue);
   returnvalue = rfm70_register_read( RFM70_REG_CONFIG );
   UART1_Write(returnvalue);
   returnvalue = rfm70_register_read( RFM70_REG_RF_SETUP );
   UART1_Write(returnvalue);

}


hij leest dus eerst voor de init van de rfm70, dan krijg ik netjes 0x00 terug voor alle drie, maar daarna 0x08, terwijl ik toch tenminste verschillende waardes verwachte. Ik heb de verbindingen nog eens nagelopen, die kloppen volgens mij:

#define RFM70_SCK( x ) PORTC.b3 = x;
#define RFM70_MOSI( x ) PORTC.b5 = x;
#define RFM70_MISO PORTC.b4;
#define RFM70_CSN( x ) PORTC.b0 = x;
#define RFM70_CE( x ) PORTC.b1 = x;

Ik zou niet weten wat ik nu na moet kijken, kunnen jullie mij misschien een tip geven?
(ik heb de beschikking over een digitale scope en een debugger trouwens)

EDIT:

Ik denk dat ik een soort bug heb gevonden, dit werkt namelijk niet:
RFM70_MOSI( value & 0x80 );

als nu namelijk value 255 is, dan wordt mosi toch niet hoog, terwijl dit wel gewoon werkt:

RFM70_MOSI(1);

EDIT 2:

Ik kan nu succesvol RFM70_REG_CONFIG uitlezen, de enige fout was volgens bug van hierboven, kan iemand trouwens bevestigen dat dit een bug is?

[ Voor 6% gewijzigd door huub8 op 21-08-2012 18:59 ]


Acties:
  • 0 Henk 'm!

  • huub8
  • Registratie: Maart 2009
  • Laatst online: 28-06-2021
Ik zit nu met een vreemd probleem, ik heb twee 18f45k22 chips waarvan de een wel de juiste waardes voor de registers kan uitlezen en de andere alleen maar 000 terug geeft, ik heb de "defecte" chip al gereset, blank gemaakt en opnieuw de code erop gezet en geverifieerd wat hij wel allemaal doet. Is deze chip dan toch kapot?

Acties:
  • 0 Henk 'm!

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 10-10 11:30

Infant

It's a floating Dino!

Nou, als de ene het wel doet, en de andere niet....

Dus, je kunt nu zinnige waarden uit de registers halen?

C:
1
2
3
4
#define RFM70_MOSI( x ) PORTC.b5 = x;
//...
RFM70_MOSI( value & 0x80 );
RFM70_MOSI(1);


Wanneer roep je de RFM70_MOSI() macro aan dan?

Ik gok dat PORTC.b5 een pin moet voorstellen, of een bit in een register?

Ik beperk het aantal macro's meestal tot een absoluut minimum. De code wordt anders compleet onleesbaar, voor je het week ben je een compleet eigen taal aan het schijven in macro's (dat kan).

Acties:
  • 0 Henk 'm!

  • huub8
  • Registratie: Maart 2009
  • Laatst online: 28-06-2021
Dit was de functie:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unsigned char rfm70_SPI_RW( unsigned char value ){
   unsigned char i;
   for( i =0 ; i < 8; i++ ){
      RFM70_WAIT_US( 1 );
      RFM70_MOSI( value & 0x80  );      
      value = (value << 1);    // shift next bit into MSB..
      
      RFM70_WAIT_US( 1 );
      RFM70_SCK( 1 );          
      value |= RFM70_MISO;     // capture current MISO bit
      
      RFM70_WAIT_US( 1 );
      RFM70_SCK( 0 );
      RFM70_WAIT_US( 1 );
  }
  return value;
}


Het is dus lijkt mij de bedoeling dat als je 255 doorgeeft aan deze functie blijk elke klokslag de mosi hoog moet zijn, maar dit is niet het geval (als ik een extra variabele maak en daar eerst de waarde van value & 0x80 in zet dan kan ik die extra variabele ook niet meer uitlezen tijdens het debuggen (wat heel vreemd is, alsof hij niet weet wat hij er mee moet)).

Ik heb er nu deze code van gemaakt, die eigenlijk precies hetzelfde doet maar gewoon de laatste bit selecteerd in plaats van de rest van de bits 0 te maken:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned char rfm70_SPI_RW( unsigned char value ){
   char i;
   for( i =0 ; i < 8; i++ ){
      delay_us( 1 );
      RFM70_MOSI(value.b7);
      value = (value << 1);    // shift next bit into MSB..
      
      delay_us( 1 );
      RFM70_SCK( 1 );          
      value |= RFM70_MISO;     // capture current MISO bit
      
      delay_us( 1 );
      RFM70_SCK( 0 );
      delay_us( 1 );
  }
  
  return value;
}


ik ben er dus vrij zeker van dat het een bug is.

PORTC.b5 is inderdaad een pin, de macro's zaten al in de voti code, vandaar (normaal gebruik ik die eigenlijk ook niet veel).

Maar hoe dan ook werkt nu perfect, ik heb de "defecte" 18f45k22 even door een 18f4520 (met licht aangepaste code) vervangen die nu constant (met een delay van 200us) 16 bytes verstuurd, en een 18f45k22 die constant kijkt of hij iets heeft ontvangen in de vorm van de data die ik probeer te versturen en dit werkt perfect.

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 10-10 11:30

Infant

It's a floating Dino!

Mooi dat het werkt.

Ik denk dat als je overal in je code rfm70_SPI_RW met een fixed waarde van 255 aanroept, en niet met een variabele of iets anders, dat de compiler gewoon netjes doet wat hij moet doen, en de & 0x80 er uit optimaliseerd.

Want ja, 0xFF & 0x80 = 0x80... so why bother.
Pagina: 1