Jump to content
Forum sending old emails Read more... ×
SamuelVergeiner

MSP430F5529 and RFM12b used together

Recommended Posts

Hello, 

I hope this is the right forum to post in, I'm a new user here... So, I have been trying to get the RFM12b module to work with my MSP430F5529. The connections are as follows for transmission:

VDD --> 3.3V

GND--> GND

SDO-->P6.5

nIRQ-->P3.4

nSEL-->P3.3

SCK-->P1.6

SDI-->P6.6

 

Now, I have the following code, in which I only configure the module and try to read its status register:

 

#include "main.h"

void WriteCMD(unsigned int CMD);
void Write1();
void Write0();
int check_status();

void main()
{
  //init ports
  P6DIR |= BIT5; //set SDO as output on P6.5
  P3DIR &= ~BIT4; //set nIRQ as input on P3.4
  P3REN |= BIT4;
  P3DIR |= BIT3; //set nSEL as output on P3.3
  P1DIR |= BIT6; //set SCK as output on P1.6
  P6DIR &= ~BIT6; //set SDI as input on P6.6
  P6REN &= ~BIT6;

  //init rfm12b
  WriteCMD(0x80D8);//enable register,433MHz,12.5pF
  WriteCMD(0x82D8);//enable receive,!PA
  WriteCMD(0xA640);//
  WriteCMD(0xC647);//
  WriteCMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
  WriteCMD(0xC2AC);
  WriteCMD(0XCC77);//
  WriteCMD(0xCA80);
  WriteCMD(0xCA83);//FIFO8,SYNC,
  WriteCMD(0xC49B);
  WriteCMD(0x9850);//!mp,9810=30kHz,MAX OUT
  WriteCMD(0xE000);//NOT USE
  WriteCMD(0xC800);//NOT USE
  WriteCMD(0xC000);//1.0MHz,2.2V
  
  
 //statusregister auslesen
  int cnt = 16;
  int result = 0;
  int temp = 0;
  P3OUT &= ~BIT3; //set nSEL low
  P6OUT &= ~BIT5; //set SDO low
  while(cnt--)
  {
    __delay_cycles(10);
    temp = P6IN;
    temp = temp <<2;
    result |= temp; 
    result = result <<1;
    P1OUT |= BIT6; // set SCK high
    __delay_cycles(10);
    __no_operation();
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
    P3OUT |= BIT3; //set nSEL high;
  }
  
  __no_operation();
  while(1)
  {
    __no_operation();
    result= result-1;
    result = result+1;
  }
}

void WriteCMD( unsigned int CMD )
{
 unsigned char n=16;
 P1OUT &= ~ BIT6; //set SCK low
 P3OUT &= ~BIT3; //set nSEL low, selecting the rfm12b
 __delay_cycles(10);
 while(n--)
 {
 if(CMD&0x8000)
 {
   Write1();
 }
 else
 {
   Write0();
 }
 CMD=CMD<<1;
 }
 P1OUT &= ~ BIT6; //set SCK low
 P3OUT |= BIT3; //set nSEL high, deselecting the rfm12b
 __delay_cycles(10);

void Write0 (void)
{
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
    P6OUT &= ~BIT5; //set SDO low
    __delay_cycles(10);
    P1OUT |= BIT6; //set SCK high, rfm now reads SDO
    __delay_cycles(10);
        P1OUT &= ~BIT6; //set SCK low
}

void Write1(void)
{
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
    P6OUT |= BIT5; //set SDO high
    __delay_cycles(10);
    P1OUT |= BIT6; //set SCK high, rfm now reads SDO
    __delay_cycles(10);
        P1OUT &= ~BIT6; //set SCK low
}
 

Now, the status register should read "0x4000",  but I always get "0xFFF8" and this makes me nervous. I have also tried simply connecting two modules and sending data between the two with a bit different programms, but that also didn't yield any results. 

 

Can anyone here help me? I've been to the 10th site of Google search results and haven't found anything that could help me. I got my instructions from the following site: https://gobotronics.wordpress.com/2010/10/07/rfm12-programming/.

 

Thanks in advance!

Share this post


Link to post
Share on other sites

I think I have spotted at least three mistakes when reading back the result:

1 . You shift the contents of P6IN the wrong way and do not mask the unwanted bits before or'ing with the result (assuming MSB is sent first).

2. You shift the result after adding a new bit, the shift should be done before adding it.

3. You deselect the device after reading the first bit (MSB) of the result. Move setting nSel high out of the loop.

result <<= 1;
result |= (P6IN >> 6) & 0x01;

The code above migth work for reading the result. However, why not use one of the USCI modules for SPI instead of bitbanging? From a quick glance at the datasheet it seems you can use a fairly high data rate.

Share this post


Link to post
Share on other sites

Thank you for your answer. First things first, I am a student at a technical school in Austria and this is part of a project for class. My problem is that our teacher does not really want to help us if we have problems. He always tells us to "google ourself". Now, that I have struggled so long, I thought that my only way to ever getting this thing to run is by asking in a forum, and here we are. (And by the way, I have to use bitbanging because my teacher wants me to.)

 

So, I have implemented your code, with a slight change, so I can analyse it better. Now, my result is always 0x0000. Shouldn't I be getting "0x4000"? All the connections are soldered properly and my program seems to do what it should, but I simply do not get the right value. What else can I do?

 

My code is exactly the same except this passage:

 

/statusregister auslesen
  int cnt = 16;
  int result = 0;
  int temp = 0;
  P3OUT &= ~BIT3; //set nSEL low
  P6OUT &= ~BIT5; //set SDO low
  while(cnt--)
  {
    result <<=1;
    temp = P6IN;
    temp >>=6;
    temp &= 0x01;
    result |= temp;
    P1OUT |= BIT6; // set SCK high
    __delay_cycles(10);
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
  }
 P3OUT |= BIT3; //set nSEL high;
  
  __no_operation();
  while(1)
  {
    __no_operation();
    result= result-1;
    result = result+1;
  }
}

 

Please help me, I am beginning to loose my mind on this... 

Share this post


Link to post
Share on other sites
On 25/1/2018 at 12:07 PM, SamuelVergeiner said:

From doc rfm12b are:
SDI, SCK and nSEL output from f5529
and SDO and nIRQ input to f5529

 Your init:


 P6DIR | = BIT5; // set SDO as output on P6.5
 P6DIR & = ~ BIT6; // set SDI as input on P6.6

is wrong

In your reading routine, you must have SCK high before reading input eg.


 P1OUT | = BIT6; // set SCK high
 __delay_cycles (10);
 temp = p6in;
 P1OUT & = ~ BIT6; // set SCK low
 __delay_cycles (10);

 Hope it helps!
 

 

Opera Snapshot_2018-01-29_160258_www.hoperf.com.png

Share this post


Link to post
Share on other sites

I have implemented your changes in my program, but it does not work after all. Thank you for pointing me to this error - I must have confused the modules in- and outputs with the controller's. I do not know what else I could try. My teacher didn't even want to look at my program. He just kept saying that the internet is my friend.

 

My program now looks like this:

#include "main.h"
#include <stdint.h>

void WriteCMD(unsigned int CMD);
void Write1();
void Write0();
int check_status();

void main()
{
  //WDTCTL = WDTPW + WDTHOLD;  // stop watchdog timer to prevent time out reset
  //init ports
  P6DIR &= ~BIT5; //set SDO as input on P6.5
  P6REN &= ~BIT5;
  P3DIR &= ~BIT4; //set nIRQ as input on P3.4
  P3REN &= ~BIT4;
  P3REN |= BIT4;
  P3DIR |= BIT3; //set nSEL as output on P3.3
  P1DIR |= BIT6; //set SCK as output on P1.6
  P6DIR |= BIT6; //set SDI as output on P6.6
  

  //init rfm12b
  WriteCMD(0x80D8);//enable register,433MHz,12.5pF
  WriteCMD(0x82D8);//enable receive,!PA
  WriteCMD(0xA640);//
  WriteCMD(0xC647);//
  WriteCMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
  WriteCMD(0xC2AC);
  WriteCMD(0XCC77);//
  WriteCMD(0xCA80);
  WriteCMD(0xCA83);//FIFO8,SYNC,
  WriteCMD(0xC49B);
  WriteCMD(0x9850);//!mp,9810=30kHz,MAX OUT
  WriteCMD(0xE000);//NOT USE
  WriteCMD(0xC800);//NOT USE
  WriteCMD(0xC000);//1.0MHz,2.2V
  
  
 //statusregister auslesen
  int cnt = 16;
  int result = 0;
  int temp = 0;
  P3OUT &= ~BIT3; //set nSEL low
  P6OUT &= ~BIT6; //set SDI low
  while(cnt--)
  {
    result <<=1;
    P1OUT |= BIT6; // set SCK high
    __delay_cycles(10);
    temp = P6IN;
    temp >>=4;
    temp &= 0x01;
    result |= temp;
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
  }
 P3OUT |= BIT3; //set nSEL high;
  
  __no_operation();
  while(1)
  {
    __no_operation();
    result= result-1;
    result = result+1;
  }
}

void WriteCMD( unsigned int CMD )
{
 unsigned char n=16;
 P1OUT &= ~ BIT6; //set SCK low
 P3OUT &= ~BIT3; //set nSEL low, selecting the rfm12b
 __delay_cycles(10);
 while(n--)
 {
 if(CMD&0x8000)
 {
   Write1();
 }
 else
 {
   Write0();
 }
 CMD=CMD<<1;
 }
 P1OUT &= ~ BIT6; //set SCK low
 P3OUT |= BIT3; //set nSEL high, deselecting the rfm12b
 __delay_cycles(10);

void Write0 (void)
{
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
    P6OUT &= ~BIT6; //set SDI low
    __delay_cycles(10);
    P1OUT |= BIT6; //set SCK high, rfm now reads SDO
    __delay_cycles(10);
        P1OUT &= ~BIT6; //set SCK low
}

void Write1(void)
{
    P1OUT &= ~BIT6; //set SCK low
    __delay_cycles(10);
    P6OUT |= BIT6; //set SDI high
    __delay_cycles(10);
    P1OUT |= BIT6; //set SCK high, rfm now reads SDO
    __delay_cycles(10);
        P1OUT &= ~BIT6; //set SCK low
}
 

And for clearence, the pins in my initiation (SDO, SDI, nIRQ, nSEL, SCK) are connected as in the attached picture. Meaning that the SDO port of the RFM12b is connected to P6.5 and is defined as an input for my controller. Now, that the initiation is correct, only the connections can be wrong. My program is right after all, isn't it?

 

I hope I am not getting on your nerves with my noobery, but I can't solve this problem on my own.

 

Looking forward to your reply! 

rfm12b-pins-300x160.png

Share this post


Link to post
Share on other sites

What your professor should have said is: "A logic analyzer is your best friend". :smile:

Seriously though, if you can borrow a logic analyzer to monitor what is happening on your communication lines that would allow you to see what is really happening.  It is very difficult to troubleshoot communication issues between devices without one since you can't tell if you have a hardware issue, a software issue or a combination of the two.  If you can't get a hold of a logic analyzer then a four channel memory scope, although not ideal, could help shed some light on the situation as well.

Share this post


Link to post
Share on other sites

Firstly, you have not stopped watchdog.

 

void main ()
{
   // WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer to prevent time out reset
   // init ports

Secondly, what bit do you read now and how many shift do you have?

  temp = p6in;
     temp >> = 4;

  
These are the most illuminated points now.

Keep on, at last it will success.

 

Share this post


Link to post
Share on other sites

The  line concerning watchdog was copied from a program we wrote with our teacher, haha. I bet, he doesn't even know how to code himself *face palm*. 

 

But, i googled it and the posts there say that the line "WDTCTL = WDTPW + WDTHOLD;" should stop watchdog. However, others say that "WDTCL = WDTPW | WDTHOLD;" Which one is the right one?

 

Secondly, I am reading P6.5 -  in the byte P6 the "x" (00x0000). So, I have to shift it four positions to the right in order for bit0 to be the value I want to read, if I understand this correctly. I do not have my MSP with me at the moment, but I will do some trial and error today and post my "results". 

Share this post


Link to post
Share on other sites

In logical circles, we normally use + and * for OR and AND, which in programming is also | and &.
So +, OR or | are the same.
So *, AND or & is the same.

Port P6 has 8 bits that we usually count bit 1 to bit 8, but
The processor counts from 0 to 7.

                 | --- P6.5 ~ SDO
                 |
BIT      7   6   5   4   3   2   1   0
         0   0   0   0   0   0   0   0
WEIGHT 128  64  32  16   8   4   2   1

 

Share this post


Link to post
Share on other sites

Yes, when you join the 10's system, it does not work.
But when using weighted values, it works.
  16 + 8 + 4 = 28 16 | 8 | 4 = 28
 

 

[edit]

The rules of calculation must be used on logic circles, not on normal account.
There were rules I learned in the 1970s.
2 + 1 + 1 = 3, not 4
If you take 1 + 1 = 1 because 1 becomes or with 1.
2 + 1 = 3 because 2 becomes or with 1.
Binary is 2 = 10 and 1 = 01, these or together give 3 = 11.
 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×