Jump to content
43oh

MSP430f247 to nRF24L01+ Module SPI Problem


Recommended Posts

I want to use nRF24l01 RF wireless  modules with MSP 430f247 processor. There is a project done on MSP430G2553 with the same wireless module; https://github.com/spirilis/msprf24/wiki#library-usage

 

I want to use USCIB_0 part for communication interface.  I replaced output pins in the program.   When I debug the program step by step I have seen no signal at SPI line. Do you have any suggestion?   

 

 

Link to post
Share on other sites

Do you have the USCI set to SPI mode? Is there any SPI data? Is your SPI clock set to output? Do you have your pin selection set to SPI behaviour?

As far as I can see, your problem is not nRF related, purely MSP430. Unhook your nRF and use a logic analyzer to see what's going on.

I can go on guessing what's wrong, but you might share what you are doing, what you've done and where you're puzzled.

Link to post
Share on other sites

Yes,i have set the USCI_B0 to SPI mode, 

       P3SEL |= 0x0E;                            // P3.3,2,1 option select
       UCB0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    //3-pin, 8-bit SPI master
       UCB0CTL1 |= UCSSEL_2;                     // SMCLK
       UCB0BR0 = 0x02;                           // /2
       UCB0BR1 = 0;                              //
       UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

MSP430f247 pins to,

P3.1 - SIMO,

P3.2 - SOMI,

P3.3 - CLK,

P3.4 - CE,

P2.0 -IRQ,

I unhook my nRF module and watched SPI line with oscilloscope, there isn't any data and clock. After i started program with CCS debug, program not going the go forward code section. This is my code , what can i do?

//******************************Main code*******************
#include <msp430.h>
#include "msprf24.h"
#include "nrf_userconfig.h"
#include "stdint.h"

volatile unsigned int user;

void main()
{
    char addr[5];
    char buf[32];
    volatile unsigned int i;
    WDTCTL = WDTPW + WDTHOLD;//Disable Watchdog

    DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
      DCOCTL = CALDCO_1MHZ;
      for(i=2100;i>0;i--);                      // Wait for DCO to stabilize.

       P3SEL |= 0x0E;                            // P3.3,2,1 option select
       UCB0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    //3-pin, 8-bit SPI master
       UCB0CTL1 |= UCSSEL_2;                     // SMCLK
       UCB0BR0 = 0x02;                           // /2
       UCB0BR1 = 0;                              //
       UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
       IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt

    // Red, Green LED used for status
    P1DIR |= 0x41;
    P1OUT &= ~0x41;

    user = 0xFE;  // this is just used for testing, examined via debugger, it can be ignored

    /* Initial values for nRF24L01+ library config variables */
	rf_crc = RF24_EN_CRC | RF24_CRCO; // CRC enabled, 16-bit
    rf_addr_width      = 5;
    rf_speed_power     = RF24_SPEED_1MBPS | RF24_POWER_0DBM;
    rf_channel     = 120;

    msprf24_init();  // All RX pipes closed by default
    msprf24_set_pipe_packetsize(0, 32);
    msprf24_open_pipe(0, 1);  // Open pipe#0 with Enhanced ShockBurst enabled for receiving Auto-ACKs

    // Transmit to 'rad01' (0x72 0x61 0x64 0x30 0x31)
    msprf24_standby();
    user = msprf24_current_state();
    //addr[0] = 0xDE; addr[1] = 0xAD; addr[2] = 0xBE; addr[3] = 0xEF; addr[4] = 0x00;
    addr[0] = 0xE8; addr[1] = 0xE8; addr[2] = 0xF0; addr[3] = 0xF0; addr[4] = 0xE1;
    w_tx_addr(addr);
    w_rx_addr(0, addr);  // Pipe 0 receives auto-ack's, autoacks are sent back to the TX addr so the PTX node
                     // needs to listen to the TX addr on pipe#0 to receive them.

    while(1) {  //{
      //  __delay_cycles(8000);
    //    if(buf[0]=='0'){buf[0] = '1';buf[1] = '0';}
   //     else {buf[0] = '0';buf[1] = '1';}
    buf[0]=0x55;
        w_tx_payload(32, buf);
        msprf24_activate_tx();
		LPM4;

 msprf24_get_last_retransmits();

   }

}
 
/* msprf24.c
 * MSP430 library for interfacing with the nRF24L01+ RF transceiver by
 * Nordic Semiconductor.
 *
 * Serial interfaces supported:
 * 1. USI - developed on MSP430G2231
 * 2. USCI_A - developed on MSP430G2553
 * 3. USCI_B - developed on MSP430G2553
 * 4. USCI_A F5xxx - developed on MSP430F5172
 * 5. USCI_B F5xxx - developed on MSP430F5172
 *
 * MSP430-specific code inspired/derived from dkedr's nrf24 library posted on the 43oh forums:
 * http://www.43oh.com/forum/viewtopic.php?f=10&t=2572
 *
 *
 * Copyright (c) 2012, Eric Brundick <spirilis@linux.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any purpose
 * with or without fee is hereby granted, provided that the above copyright notice
 * and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
 * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <msp430.h>
#include "msprf24.h"
#include "msp430_spi.h"
#include "nRF24L01.h"
#include "nrf_userconfig.h"
/* ^ Provides nrfCSNport, nrfCSNportout, nrfCSNpin,
     nrfCEport, nrfCEportout, nrfCEpin,
     nrfIRQport, nrfIRQpin
     Also specify # clock cycles for 5ms, 10us and 130us sleeps.
 */
/* Private library variables */
uint8_t rf_feature;  // Used to track which features have been enabled

/* CE (Chip Enable/RF transceiver activate signal) and CSN (SPI chip-select) operations. */
#define CSN_EN nrfCSNportout &= ~nrfCSNpin
#define CSN_DIS nrfCSNportout |= nrfCSNpin
#define CE_EN nrfCEportout |= nrfCEpin
#define CE_DIS nrfCEportout &= ~nrfCEpin



/* SPI drivers now supplied by msp430_spi.c */




/* Basic I/O to the device. */
uint8_t r_reg(uint8_t addr)
{
	uint16_t i;

	CSN_EN;
	i = spi_transfer16(RF24_NOP | ((addr & RF24_REGISTER_MASK) << 8));
	rf_status = (uint8_t) ((i & 0xFF00) >> 8);
	CSN_DIS;
	return (uint8_t) (i & 0x00FF);
}

void w_reg(uint8_t addr, uint8_t data)
{
	uint16_t i;
	CSN_EN;
	i = spi_transfer16( (data & 0x00FF) | (((addr & RF24_REGISTER_MASK) | RF24_W_REGISTER) << 8) );
	rf_status = (uint8_t) ((i & 0xFF00) >> 8);
	CSN_DIS;
}

void w_tx_addr(uint8_t *addr)
{
	int i;

	CSN_EN;
	rf_status = spi_transfer(RF24_TX_ADDR | RF24_W_REGISTER);
	for (i=rf_addr_width-1; i>=0; i--) {
		spi_transfer(addr[i]);
	}
	CSN_DIS;
}

void w_rx_addr(uint8_t pipe, uint8_t *addr)
{
	int i;

	if (pipe > 5)
		return;  // Only 6 pipes available
	CSN_EN;
	rf_status = spi_transfer((RF24_RX_ADDR_P0 + pipe) | RF24_W_REGISTER);
	if (pipe > 1) {  // Pipes 2-5 differ from pipe1's addr only in the LSB.
		spi_transfer(addr[rf_addr_width-1]);
	} else {
		for (i=rf_addr_width-1; i>=0; i--) {
			spi_transfer(addr[i]);
		}
	}
	CSN_DIS;
}

void w_tx_payload(uint8_t len, uint8_t *data)
{
	uint16_t i=0;
	CSN_EN;
	if (len % 2) {  // Odd payload size?  Make it even by stuffing the command in a 16-bit xfer
		// Borrowing 'i' to extract STATUS...
		i = spi_transfer16( (RF24_W_TX_PAYLOAD << 8) | (0x00FF & data[0]) );
		rf_status = (i & 0xFF00) >> 8;
		i = 1;
	} else {
		rf_status = spi_transfer(RF24_W_TX_PAYLOAD);
	}
	for (; i < len; i+=2) {
		// SPI transfers MSB first
		spi_transfer16( (data[i] << 8) | (0x00FF & data[i+1]) );
	}
	CSN_DIS;
}

void w_tx_payload_noack(uint8_t len, uint8_t *data)
{
	uint16_t i=0;

	if ( !(rf_feature & RF24_EN_DYN_ACK) )  // DYN ACK must be enabled to allow NOACK packets
		return;
	CSN_EN;
	if (len % 2) {
		// Borrowing 'i' to extract STATUS...
		i = spi_transfer16( (RF24_W_TX_PAYLOAD_NOACK << 8) | (0x00FF & data[0]) );
		rf_status = (i & 0xFF00) >> 8;
		i = 1;
	} else {
		rf_status = spi_transfer(RF24_W_TX_PAYLOAD_NOACK);
	}
	for (; i < len; i+=2) {
		// SPI transfers MSB first
		spi_transfer16( (data[i] << 8) | (0x00FF & data[i+1]) );
	}
	CSN_DIS;
}

uint8_t r_rx_peek_payload_size()
{
	uint16_t i;

	CSN_EN;
	i = spi_transfer16(RF24_NOP | (RF24_R_RX_PL_WID << 8));
	rf_status = (uint8_t) ((i & 0xFF00) >> 8);
	CSN_DIS;
	return (uint8_t) (i & 0x00FF);
}

uint8_t r_rx_payload(uint8_t len, uint8_t *data)
{
	uint16_t i=0,j;
	CSN_EN;
	if (len % 2) {
		// Borrowing 'i' to extract STATUS...
		i = spi_transfer16((RF24_R_RX_PAYLOAD << 8) | RF24_NOP);
		rf_status = (i & 0xFF00) >> 8;
		data[0] = i & 0x00FF;
		i = 1;
	} else {
		rf_status = spi_transfer(RF24_R_RX_PAYLOAD);
	}
	for (; i < len; i+=2) {
		j = spi_transfer16(0xFFFF);
		// SPI transfers MSB first
		data[i] = (j & 0xFF00) >> 8;
		data[i+1] = (j & 0x00FF);
	}
	CSN_DIS;
	// The RX pipe this data belongs to is stored in STATUS
	return ((rf_status & 0x0E) >> 1);
}

void flush_tx()
{
	CSN_EN;
	rf_status = spi_transfer(RF24_FLUSH_TX);
	CSN_DIS;
}

void flush_rx()
{
	CSN_EN;
	rf_status = spi_transfer(RF24_FLUSH_RX);
	CSN_DIS;
}

void tx_reuse_lastpayload()
{
	CSN_EN;
	rf_status = spi_transfer(RF24_REUSE_TX_PL);
	CSN_DIS;
}

inline void pulse_ce()
{
	CE_EN;
	__delay_cycles(DELAY_CYCLES_15US);
	CE_DIS;
}

/* Used to manually ACK with a payload.  Must have RF24_EN_ACK_PAY enabled; this is not enabled by default
 * with msprf24_init() FYI.
 * When RF24_EN_ACK_PAY is enabled on the PTX side, ALL transmissions must be manually ACK'd by the receiver this way.
 * The receiver (PRX) side needs to have RF24_EN_ACK_PAY enabled too, or else it will automatically ACK with a zero-byte packet.
 *
 * If you have this enabled on the PTX but not the PRX, the transmission will go through and the PRX will receive/notify about
 * the RX payload, but the PTX will ignore the zero-byte autoack from the PRX and perform its retransmit sequence, erroring
 * out with MAX_RT (RF24_IRQ_TXFAILED) after (RF24_SETUP_RETR >> RF24_ARC) retransmissions.
 * When this occurs, the PRX will still only notify its microcontroller of the payload once (the PID field in the packet uniquely
 * identifies it so the PRX knows it's the same packet being retransmitted) but it's obviously wasting on-air time (and power).
 */
void w_ack_payload(uint8_t pipe, uint8_t len, uint8_t *data)
{
	uint16_t i=0;
	CSN_EN;

	if (pipe > 5)
		return;
	if ( !(rf_feature & RF24_EN_ACK_PAY) )  // ACK payloads must be enabled...
		return;

	if (len % 2) {
		// Borrowing 'i' to extract STATUS...
		i = spi_transfer16( ((RF24_W_ACK_PAYLOAD | pipe) << 8) | (0x00FF & data[0]) );
		rf_status = (i & 0xFF00) >> 8;
		i = 1;
	} else {
		rf_status = spi_transfer(RF24_W_ACK_PAYLOAD | pipe);
	}
	for (; i < len; i+=2) {
		// SPI transfers MSB first
		spi_transfer16( (data[i] << 8) | (0x00FF & data[i+1]) );
	}
	CSN_DIS;
}






/* Configuration parameters used to set-up the RF configuration */
uint8_t rf_crc;
uint8_t rf_addr_width;
uint8_t rf_speed_power;
uint8_t rf_channel;
/* Status variable updated every time SPI I/O is performed */
uint8_t rf_status;
/* IRQ state is stored in here after msprf24_get_irq_reason(), RF24_IRQ_FLAGGED raised during
 * the IRQ port ISR--user application issuing LPMx sleep or polling should watch for this to
 * determine if the wakeup reason was due to nRF24 IRQ.
 */
volatile uint8_t rf_irq;





/* Library functions */
void msprf24_init()
{
	// Setup SPI
	spi_init();
	_EINT();  // Enable interrupts (set GIE in SR)

	// Setup IRQ
	#if nrfIRQport == 1
		P1DIR &= ~nrfIRQpin;  // IRQ line is input
		P1OUT |= nrfIRQpin;   // Pull-up resistor enabled
		P1REN |= nrfIRQpin;
		P1IES |= nrfIRQpin;   // Trigger on falling-edge
		P1IFG &= ~nrfIRQpin;  // Clear any outstanding IRQ
		P1IE |= nrfIRQpin;    // Enable IRQ interrupt
	#elif nrfIRQport == 2
		P2DIR &= ~nrfIRQpin;  // IRQ line is input
		P2OUT |= nrfIRQpin;   // Pull-up resistor enabled
		P2REN |= nrfIRQpin;
		P2IES |= nrfIRQpin;   // Trigger on falling-edge
		P2IFG &= ~nrfIRQpin;  // Clear any outstanding IRQ
		P2IE |= nrfIRQpin;    // Enable IRQ interrupt
	#elif nrfIRQport == 3
		P3DIR &= ~nrfIRQpin;  // IRQ line is input
		P3OUT |= nrfIRQpin;   // Pull-up resistor enabled
		P3REN |= nrfIRQpin;
		P3IES |= nrfIRQpin;   // Trigger on falling-edge
		P3IFG &= ~nrfIRQpin;  // Clear any outstanding IRQ
		P3IE |= nrfIRQpin;    // Enable IRQ interrupt
	#elif nrfIRQport == 2
		P4DIR &= ~nrfIRQpin;  // IRQ line is input
		P4OUT |= nrfIRQpin;   // Pull-up resistor enabled
		P4REN |= nrfIRQpin;
		P4IES |= nrfIRQpin;   // Trigger on falling-edge
		P4IFG &= ~nrfIRQpin;  // Clear any outstanding IRQ
		P4IE |= nrfIRQpin;    // Enable IRQ interrupt
	#endif

	// Setup CSN/CE ports
	#if nrfCSNport == 1
		P1DIR |= nrfCSNpin;
	#elif nrfCSNport == 2
		P2DIR |= nrfCSNpin;
	#elif port == 3
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 4
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 5
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 6
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 7
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 8
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == 9
		P3DIR |= nrfCSNpin;
	#elif nrfCSNport == J
		PJDIR |= nrfCSNpin;
	#endif
	CSN_DIS;

	#if nrfCEport == 1
		P1DIR |= nrfCEpin;
	#elif nrfCEport == 2
		P2DIR |= nrfCEpin;
	#elif nrfCEport == 3
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 4
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 5
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 6
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 7
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 8
		P3DIR |= nrfCEpin;
	#elif nrfCEport == 9
		P3DIR |= nrfCEpin;
	#elif nrfCEport == J
		PJDIR |= nrfCEpin;
	#endif
	CE_DIS;

	/* Straw-man spi_transfer with no Chip Select lines enabled; this is to workaround errata bug USI5
	 * on the MSP430G2452 and related (see http://www.ti.com/lit/er/slaz072/slaz072.pdf)
	 * Shouldn't hurt anything since we expect no CS lines enabled by the user during this function's execution.
	 */
//	spi_transfer(RF24_NOP); fatih


	// Wait 100ms for RF transceiver to initialize.
	uint8_t c = 20;
	for (; c; c--) {
		__delay_cycles(DELAY_CYCLES_5MS);
	}

	// Configure RF transceiver with current value of rf_* configuration variables
//	msprf24_irq_clear(RF24_IRQ_MASK);  // Forget any outstanding IRQs***********************************************Fatih
	msprf24_close_pipe_all();          /* Start off with no pipes enabled, let the user open as needed.  This also
					    * clears the DYNPD register.
					    */
	msprf24_set_retransmit_delay(2000);  // A default I chose
	msprf24_set_retransmit_count(15);    // A default I chose
	msprf24_set_speed_power();
	msprf24_set_channel();
	msprf24_set_address_width();
	rf_feature = 0x00;  // Initialize this so we're starting from a clean slate
	msprf24_enable_feature(RF24_EN_DPL);      // Dynamic payload size capability (set with msprf24_set_pipe_packetsize(x, 0))
	msprf24_enable_feature(RF24_EN_DYN_ACK);  // Ability to use w_tx_payload_noack()

	msprf24_powerdown();
	flush_tx();
	flush_rx();
}

void msprf24_enable_feature(uint8_t feature)
{
	if ( (rf_feature & feature) != feature ) {
		rf_feature |= feature;
		rf_feature &= 0x07;  // Only bits 0, 1, 2 allowed to be set
		w_reg(RF24_FEATURE, rf_feature);
	}
}

void msprf24_disable_feature(uint8_t feature)
{
	if ( (rf_feature & feature) == feature ) {
		rf_feature &= ~feature;
		w_reg(RF24_FEATURE, rf_feature);
	}
}

void msprf24_close_pipe(uint8_t pipeid)
{
	uint8_t rxen, enaa;

	if (pipeid > 5)
		return;

	rxen = r_reg(RF24_EN_RXADDR);
	enaa = r_reg(RF24_EN_AA);

	rxen &= ~(1 << pipeid);
	enaa &= ~(1 << pipeid);

	w_reg(RF24_EN_RXADDR, rxen);
	w_reg(RF24_EN_AA, enaa);
}

void msprf24_close_pipe_all()
{
	w_reg(RF24_EN_RXADDR, 0x00);
	w_reg(RF24_EN_AA, 0x00);
	w_reg(RF24_DYNPD, 0x00);
}

void msprf24_open_pipe(uint8_t pipeid, uint8_t autoack)
{
	uint8_t rxen, enaa;

	if (pipeid > 5)
		return;

	rxen = r_reg(RF24_EN_RXADDR);
	enaa = r_reg(RF24_EN_AA);

	if (autoack)
		enaa |= (1 << pipeid);
	else
		enaa &= ~(1 << pipeid);
	rxen |= (1 << pipeid);
	w_reg(RF24_EN_RXADDR, rxen);
	w_reg(RF24_EN_AA, enaa);
}

uint8_t msprf24_pipe_isopen(uint8_t pipeid)
{
	uint8_t rxen;

	if (pipeid > 5)
		return 0;

	rxen = r_reg(RF24_EN_RXADDR);

	return ( (1<<pipeid) == (rxen & (1<<pipeid)) );
}

void msprf24_set_pipe_packetsize(uint8_t pipe, uint8_t size)
{
	uint8_t dynpdcfg;

	if (pipe > 5)
		return;

	dynpdcfg = r_reg(RF24_DYNPD);
	if (size < 1) {
		if ( !(rf_feature & RF24_EN_DPL) )  // Cannot set dynamic payload if EN_DPL is disabled.
			return;
		if (!( (1<<pipe) & dynpdcfg )) {
			// DYNPD not enabled for this pipe, enable it
			dynpdcfg |= 1 << pipe;
		}
	} else {
		dynpdcfg &= ~(1 << pipe);  // Ensure DynPD is disabled for this pipe
		if (size > 32)
			size = 32;
		w_reg(RF24_RX_PW_P0 + pipe, size);
	}
	w_reg(RF24_DYNPD, dynpdcfg);
}

void msprf24_set_retransmit_delay(uint16_t us)
{
	uint8_t c;

	// using 'c' to evaluate current RF speed
	c = rf_speed_power & RF24_SPEED_MASK;
	if (us > 4000)
		us = 4000;
	if (us < 1500 && c == RF24_SPEED_250KBPS)
		us = 1500;
	if (us < 500)
		us = 500;

	// using 'c' to save current value of ARC (auto-retrans-count) since we're not changing that here
	c = r_reg(RF24_SETUP_RETR) & 0x0F;
	us = (us-250) / 250;
	us <<= 4;
	w_reg(RF24_SETUP_RETR, c | (us & 0xF0));
}

void msprf24_set_retransmit_count(uint8_t count)
{
	uint8_t c;

	c = r_reg(RF24_SETUP_RETR) & 0xF0;
	w_reg(RF24_SETUP_RETR, c | (count & 0x0F));
}

uint8_t msprf24_get_last_retransmits()
{
	return r_reg(RF24_OBSERVE_TX) & 0x0F;
}

uint8_t msprf24_get_lostpackets()
{
	return (r_reg(RF24_OBSERVE_TX) >> 4) & 0x0F;
}

inline uint8_t _msprf24_crc_mask()
{
	return (rf_crc & 0x0C);
}

inline uint8_t _msprf24_irq_mask()
{
	return ~(RF24_MASK_RX_DR | RF24_MASK_TX_DS | RF24_MASK_MAX_RT);
}

uint8_t msprf24_is_alive()
{
	uint8_t aw;

	aw = r_reg(RF24_SETUP_AW);
	return((aw & 0xFC) == 0x00 && (aw & 0x03) != 0x00);
}

uint8_t msprf24_set_config(uint8_t cfgval)
{
	uint8_t previous_config;

	previous_config = r_reg(RF24_CONFIG);
	w_reg(RF24_CONFIG, (_msprf24_crc_mask() | cfgval) & _msprf24_irq_mask());
	return previous_config;
}

void msprf24_set_speed_power()
{
	if ( (rf_speed_power & RF24_SPEED_MASK) == RF24_SPEED_MASK )  // Speed setting RF_DR_LOW=1, RF_DR_HIGH=1 is reserved, clamp it to minimum
		rf_speed_power = (rf_speed_power & ~RF24_SPEED_MASK) | RF24_SPEED_MIN;
	w_reg(RF24_RF_SETUP, (rf_speed_power & 0x2F));
}

void msprf24_set_channel()
{
	if (rf_channel > 125)
		rf_channel = 0;
	w_reg(RF24_RF_CH, (rf_channel & 0x7F));
}

void msprf24_set_address_width()
{
	if (rf_addr_width < 3 || rf_addr_width > 5)
		return;
	w_reg(RF24_SETUP_AW, ((rf_addr_width-2) & 0x03));
}

uint8_t msprf24_current_state()
{
	uint8_t config;

	if (!msprf24_is_alive())               // Can't read/detect a valid value from SETUP_AW? (typically SPI or device fault)
		return RF24_STATE_NOTPRESENT;
	config = r_reg(RF24_CONFIG);
	if ( (config & RF24_PWR_UP) == 0x00 )  // PWR_UP=0?
		return RF24_STATE_POWERDOWN;
	if ( !(nrfCEportout & nrfCEpin) )      // PWR_UP=1 && CE=0?
		return RF24_STATE_STANDBY_I;
	if ( !(config & RF24_PRIM_RX) ) {      // PWR_UP=1 && CE=1 && PRIM_RX=0?
		if ( (r_reg(RF24_FIFO_STATUS) & RF24_TX_EMPTY) )  // TX FIFO empty?
			return RF24_STATE_STANDBY_II;
		return RF24_STATE_PTX; // If TX FIFO is not empty, we are in PTX (active transmit) mode.
	}
	if ( r_reg(RF24_RF_SETUP) & 0x90 )     // Testing CONT_WAVE or PLL_LOCK?
		return RF24_STATE_TEST;
	return RF24_STATE_PRX;                 // PWR_UP=1, PRIM_RX=1, CE=1 -- Must be PRX
}

// Power down device, 0.9uA power draw
void msprf24_powerdown()
{
	CE_DIS;
	msprf24_set_config(0);  // PWR_UP=0
}

// Enable Standby-I, 26uA power draw
void msprf24_standby()
{
	uint8_t state = msprf24_current_state();
	if (state == RF24_STATE_NOTPRESENT || state == RF24_STATE_STANDBY_I)
		return;
	CE_DIS;
	msprf24_set_config(RF24_PWR_UP);  // PWR_UP=1, PRIM_RX=0
	if (state == RF24_STATE_POWERDOWN) {  // If we're powering up from deep powerdown...
		//CE_EN;  // This is a workaround for SI24R1 chips, though it seems to screw things up so disabled for now til I can obtain an SI24R1 for testing.
		__delay_cycles(DELAY_CYCLES_5MS);  // Then wait 5ms for the crystal oscillator to spin up.
		//CE_DIS;
	}
}

// Enable PRX mode
void msprf24_activate_rx()
{
	msprf24_standby();
	// Purge any existing RX FIFO or RX interrupts
	flush_rx();
	w_reg(RF24_STATUS, RF24_RX_DR);

	// Enable PRIM_RX
	msprf24_set_config(RF24_PWR_UP | RF24_PRIM_RX);
	CE_EN;
	// 130uS required for PLL lock to stabilize, app can go do other things and wait
	// for incoming I/O.
}

// Enable Standby-II / PTX mode
/* Standby-II is enabled if the TX FIFO is empty, otherwise the chip enters PTX
 *     mode to send the TX FIFO buffer contents until it's all done, at which point
 *     the chip falls back to Standby-II again.
 */
void msprf24_activate_tx()
{
	msprf24_standby();
	// Cancel any outstanding TX interrupt
	w_reg(RF24_STATUS, RF24_TX_DS|RF24_MAX_RT);

	// Pulse CE for 10us to activate PTX
	pulse_ce();
}

/* Evaluate state of TX, RX FIFOs
 * Compare this with RF24_QUEUE_* #define's from msprf24.h
 */
uint8_t msprf24_queue_state()
{
	return r_reg(RF24_FIFO_STATUS);
}

/* Scan current channel for activity, produce an 8-bit integer indicating % of time
 * spent with RPD=1 (valid RF activity present) for a 133ms period.
 */
uint8_t msprf24_scan()
{
	int testcount = 1023;
	uint16_t rpdcount = 0;
	uint8_t last_state;

	last_state = msprf24_current_state();
	if (last_state != RF24_STATE_PRX)
		msprf24_activate_rx();
	for (; testcount > 0; testcount--) {
		if (r_reg(RF24_RPD))
			rpdcount++;
		__delay_cycles(DELAY_CYCLES_130US);
		flush_rx();
		w_reg(RF24_STATUS, RF24_RX_DR);  /* Flush any RX FIFO contents or RX IRQs that
						  * may have generated as a result of having PRX active.
						  */
	}
	if (last_state != RF24_STATE_PRX)
		msprf24_standby();  // If we weren't in RX mode before, leave it in Standby-I.
	return( (uint8_t) (rpdcount/4) );
}

// Check if there is pending RX fifo data
uint8_t msprf24_rx_pending()
{
	CSN_EN;
	rf_status = spi_transfer(RF24_NOP);
	CSN_DIS;

	if ((rf_status & 0x0E) < 0x0E)
		return 1;
	return 0;
}

// Get IRQ flag status
uint8_t msprf24_get_irq_reason()
{
	uint8_t rf_irq_old = rf_irq;

	//rf_irq &= ~RF24_IRQ_FLAGGED;  -- Removing in lieu of having this check determined at irq_clear() time
	CSN_EN;
	rf_status = spi_transfer(RF24_NOP);
	CSN_DIS;
	rf_irq = (rf_status & RF24_IRQ_MASK) | rf_irq_old;
	return rf_irq;
}

/* Clear IRQ flags */
void msprf24_irq_clear(uint8_t irqflag)
{
	uint8_t fifostat;

	rf_irq = 0x00;  // Clear IRQs; afterward analyze RX FIFO to see if we should re-set RX IRQ flag.
	CSN_EN;
	rf_status = spi_transfer(RF24_STATUS | RF24_W_REGISTER);
	spi_transfer(irqflag);
	CSN_DIS;

	// Per datasheet procedure, check FIFO_STATUS to see if there's more RX FIFO data to process.
	if (irqflag & RF24_IRQ_RX) {
		CSN_EN;
		rf_status = spi_transfer(RF24_FIFO_STATUS | RF24_R_REGISTER);
		fifostat = spi_transfer(RF24_NOP);
		CSN_DIS;
		if ( !(fifostat & RF24_RX_EMPTY) )
			rf_irq |= RF24_IRQ_RX | RF24_IRQ_FLAGGED;  // Signal to user that there is remaining data, even if it's not "new"
	}
}

/*      -       -       Interrupt vectors       -       -       */

// RF transceiver IRQ handling
#if   nrfIRQport == 2
  #ifdef __GNUC__
  __attribute__((interrupt(PORT2_VECTOR)))
  void P2_IRQ (void) {
  #else
  #pragma vector = PORT2_VECTOR
  __interrupt void P2_IRQ (void) {
  #endif
	if(P2IFG & nrfIRQpin) {
		__bic_SR_register_on_exit(LPM4_bits);    // Wake up
		rf_irq |= RF24_IRQ_FLAGGED;
		P2IFG &= ~nrfIRQpin;   // Clear interrupt flag
	}
}

#elif nrfIRQport == 1
  #ifdef __GNUC__
  __attribute__((interrupt(PORT1_VECTOR)))
  void P1_IRQ (void) {
  #else
  #pragma vector = PORT1_VECTOR
  __interrupt void P1_IRQ (void) {
  #endif
	if(P1IFG & nrfIRQpin) {
		__bic_SR_register_on_exit(LPM4_bits);
		rf_irq |= RF24_IRQ_FLAGGED;
		P1IFG &= ~nrfIRQpin;
	}
}

#elif nrfIRQport == 3 && defined(P3IV_)
  #ifdef __GNUC__
  __attribute__((interrupt(PORT3_VECTOR)))
  void P3_IRQ (void) {
  #else
  #pragma vector = PORT3_VECTOR
  __interrupt void P3_IRQ (void) {
  #endif
	if (P3IFG & nrfIRQpin) {
		__bic_SR_register_on_exit(LPM4_bits);
		rf_irq |= RF24_IRQ_FLAGGED;
		P3IFG &= ~nrfIRQpin;
	}
}

#elif nrfIRQport == 4 && defined(P4IV_)
  #ifdef __GNUC__
  __attribute__((interrupt(PORT4_VECTOR)))
  void P4_IRQ (void) {
  #else
  #pragma vector = PORT4_VECTOR
  __interrupt void P4_IRQ (void) {
  #endif
	if (P4IFG & nrfIRQpin) {
		__bic_SR_register_on_exit(LPM4_bits);
		rf_irq |= RF24_IRQ_FLAGGED;
		P4IFG &= ~nrfIRQpin;
	}
}
#endif

/* msp430_spi.c
 * Library for performing SPI I/O on a wide range of MSP430 chips.
 *
 * Serial interfaces supported:
 * 1. USI - developed on MSP430G2231
 * 2. USCI_A - developed on MSP430G2553
 * 3. USCI_B - developed on MSP430G2553
 * 4. USCI_A F5xxx - developed on MSP430F5172, added F5529
 * 5. USCI_B F5xxx - developed on MSP430F5172, added F5529
 *
 * Copyright (c) 2013, Eric Brundick <spirilis@linux.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any purpose
 * with or without fee is hereby granted, provided that the above copyright notice
 * and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
 * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <msp430.h>
#include "msp430_spi.h"
#include "nrf_userconfig.h"



void spi_init()
{
	  P3SEL |= 0x0E;                            // P3.3,2,1 option select
	  UCB0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    //3-pin, 8-bit SPI master
	  UCB0CTL1 |= UCSSEL_2;                     // SMCLK
	  UCB0BR0 = 0x02;                           // /2
	  UCB0BR1 = 0;                              //
	  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
	  IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt
}

uint8_t spi_transfer(uint8_t inb)
{
	UCB0TXBUF = inb;
	while ( !(IFG2 & UCB0RXIFG) )  // Wait for RXIFG indicating remote byte received via SOMI
		;
	return UCB0RXBUF;
}

uint16_t spi_transfer16(uint16_t inw)
{
	uint16_t retw;
	uint8_t *retw8 = (uint8_t *)&retw, *inw8 = (uint8_t *)&inw;

	UCB0TXBUF = inw8[1];
	while ( !(IFG2 & UCB0RXIFG) );
	retw8[1] = UCB0RXBUF;
	UCB0TXBUF = inw8[0];
	while ( !(IFG2 & UCB0RXIFG) );
	retw8[0] = UCB0RXBUF;
	return retw;
}

uint16_t spi_transfer9(uint16_t inw)
{
	uint8_t p1dir_save, p1out_save, p1ren_save;
	uint16_t retw=0;

	/* Reconfigure I/O ports for bitbanging the MSB */
	p1ren_save = P1REN; p1out_save = P1OUT; p1dir_save = P1DIR;
	P1REN &= ~(BIT5 | BIT6 | BIT7);
	P1OUT &= ~(BIT5 | BIT6 | BIT7);
	P1DIR = (P1DIR & ~(BIT5 | BIT6 | BIT7)) | BIT5 | BIT7;
	P1SEL &= ~(BIT5 | BIT6 | BIT7);
	//P1SEL2 &= ~(BIT5 | BIT6 | BIT7);   Fatih

	// Perform single-bit transfer
	if (inw & 0x0100)
		P1OUT |= BIT7;
	P1OUT |= BIT5;
	if (P1IN & BIT4)
		retw |= 0x0100;
	P1OUT &= ~BIT5;

	// Restore port states and continue with 8-bit SPI
	P1SEL |= BIT5 | BIT6 | BIT7;
	//P1SEL2 |= BIT5 | BIT6 | BIT7; fatih
	P1DIR = p1dir_save;
	P1OUT = p1out_save;
	P1REN = p1ren_save;

	retw |= spi_transfer( (uint8_t)(inw & 0x00FF) );
	return retw;
}


/* nrf_userconfig.h
 * User configuration of nRF24L01+ connectivity parameters, e.g.
 * IRQ, CSN, CE pin assignments, Serial SPI driver type
 *
 *
 * Copyright (c) 2012, Eric Brundick <spirilis@linux.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any purpose
 * with or without fee is hereby granted, provided that the above copyright notice
 * and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
 * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _NRF_USERCONFIG_H
#define _NRF_USERCONFIG_H

/* CPU clock cycles for the specified amounts of time--accurate minimum delays
 * required for reliable operation of the nRF24L01+'s state machine.
 */
/* Settings for 1MHz MCLK.
#define DELAY_CYCLES_5MS       5000
#define DELAY_CYCLES_130US     130
#define DELAY_CYCLES_15US      15
 */

// Settings for 8MHz MCLK.
#define DELAY_CYCLES_5MS       40000
#define DELAY_CYCLES_130US     1040
#define DELAY_CYCLES_15US      120


/* Settings for 16MHz MCLK
#define DELAY_CYCLES_5MS       80000
#define DELAY_CYCLES_130US     2080
#define DELAY_CYCLES_15US      240
 */
/* Settings for 24MHz MCLK.
#define DELAY_CYCLES_5MS       120000
#define DELAY_CYCLES_130US     3120
#define DELAY_CYCLES_15US      360
 */

/* SPI port--Select which USCI port we're using.
 * Applies only to USCI devices.  USI users can keep these
 * commented out.
 */
//#define SPI_DRIVER_USCI_A 1
#define SPI_DRIVER_USCI_B 0


/* Operational pins -- IRQ, CE, CSN (SPI chip-select)
 */

/* IRQ */
#define nrfIRQport 2
#define nrfIRQpin BIT0

/* CSN SPI chip-select */
#define nrfCSNport 2
#define nrfCSNportout P2OUT
#define nrfCSNpin BIT5

/* CE Chip-Enable (used to put RF transceiver on-air for RX or TX) */
#define nrfCEport 3
#define nrfCEportout P3OUT
#define nrfCEpin BIT4

#endif

Link to post
Share on other sites

Are you seeing any activity on CE or CSN?  Have you tried debugging (not sure if you're using CCS or GCC)?

I did notice you're initializing SPI - but the library should actually be taking care of that for you as long as you're using the correct #define's.  It looks like you've modified the SPI library from what is up on github - any reason why you aren't just letting the defines take care of that?  

I've used that library on a F5529 as well as the G2553 without any issues at all.  

Link to post
Share on other sites

Yes, i saw CE , CSN and SCK pins. CE pin goes to logic level low- high - low , CSN pin goes to logic level high- low - high and SCK pin is high .

I tried debugging with Code Composer Studio. When i debugging code in function  "msprf24_init()" step "spi_transfer(uint8_t inb)" to run, restart to program.

I hope, if i modified the SPI library from what is up on github and #define's, it will work.What's wrong, i'm not understand. Can you share on a F5529 library?

Link to post
Share on other sites

I changed "sp?_init() "function to USCI_B's code. 

#endif

#if defined(__MSP430_HAS_USCI__) && defined(SPI_DRIVER_USCI_ && !defined(__MSP430_HAS_TB3__)
void spi_init()
{
	/* Configure ports on MSP430 device for USCI_B */
	P1SEL |= BIT5 | BIT6 | BIT7;
	P1SEL2 |= BIT5 | BIT6 | BIT7;

	/* USCI-B specific SPI setup */
	UCB0CTL1 |= UCSWRST;
	UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCMODE_0 | UCSYNC;  // SPI mode 0, master
	UCB0BR0 = 0x01;  // SPI clocked at same speed as SMCLK
	UCB0BR1 = 0x00;
	UCB0CTL1 = UCSSEL_2;  // Clock = SMCLK, clear UCSWRST and enables USCI_B module.
}

I replaced Pin Bits to MSP430f247 USCI_B0 pins.

/* Configure ports on MSP430 device for USCI_B */
		P3SEL |= BIT1 | BIT2 | BIT3;
		//P3SEL2 |= BIT1 | BIT2 | BIT3;

		/* USCI-B specific SPI setup */
		UCB0CTL1 |= UCSWRST;
		UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCMODE_0 | UCSYNC;  // SPI mode 0, master
		UCB0BR0 = 0x01;  // SPI clocked at same speed as SMCLK
		UCB0BR1 = 0x00;
		UCB0CTL1 = UCSSEL_2;  // Clock = SMCLK, clear UCSWRST and enables USCI_B module.

But P3SEL2 command don't work and not compling,so i erase this step. Finally i watched clock signals, Mosi, Miso , CE, CSN line in data.

Reciever module Arduino module with nRF module,so different library with it work.

Which parameter important for communication?

Link to post
Share on other sites

Hi Spirilis,

I'll communicate MSP430f247 with an Arduino leonardo board by nRF24L01 modules. I achieved Arduino to Arduino communication with nRF24l01+ module but, don't work when MSP430f247 transceiver .I use your share msprf24 project,but your " msp430_spi.c" library hasn't got for MSP430f247 USCI_B0 in serial interfaces supported. 

thank you for your reply.

 

   

Link to post
Share on other sites

So after your msp430_spi.c change, you now see logic transitions happening on the SPI lines and CE/CSN lines?  Or no?

 

Furthermore, be sure you understand the nRF24L01+ parameters on your Arduino sketch and make sure the msprf24 library parameters are modified to match them (e.g. channel, speed, whether Dynamic Payload is enabled, whether AutoACK is enabled, etc)

Link to post
Share on other sites

Yes, i saw SPI lines.

This imagine CE line,

 

zslqpc.png

 

This imagine CSN line,

 

znnfwg.png

 

This imagine SCK,

 

25f6hab.png

 

SMCLK running 8 MHZ ( we can calculate on SCK signals).

  WDTCTL = WDTHOLD | WDTPW;
    	DCOCTL = CALDCO_8MHZ;
    	BCSCTL1 = CALBC1_8MHZ;
    	BCSCTL2 = DIVS_1;  // SMCLK = DCOCLK/4    // DIVS_2 default
        BCSCTL3 = LFXT1S_2;  // ACLK = VLOCLK/1
        BCSCTL3 &= ~(XT2OF|LFXT1OF);

Link to post
Share on other sites

 

Yes, i saw SPI lines.

This imagine CE line,

 

256bo28.png

 

This imagine CSN line,

 

znnfwg.png

 

This imagine SCK,

 

2yx3uhu.png

 

SMCLK running 8 MHZ ( we can calculate on SCK signals).

  WDTCTL = WDTHOLD | WDTPW;
    	DCOCTL = CALDCO_8MHZ;
    	BCSCTL1 = CALBC1_8MHZ;
    	BCSCTL2 = DIVS_1;  // SMCLK = DCOCLK/4    // DIVS_2 default
        BCSCTL3 = LFXT1S_2;  // ACLK = VLOCLK/1
        BCSCTL3 &= ~(XT2OF|LFXT1OF);

Link to post
Share on other sites

Got it.  Chances are, the module is working, although it's hard to verify without a 2.4GHz spectrum analyzer ;-)  In either case, we should probably look at the module parameters.  What are you doing with the module, which node is receiving & which is transmitting, and what parameters are you using for both the Arduino and MSP430's respective nRF24L01+ libraries?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...