⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nrf24l01.c

📁 MSP acquires data and sends through USB to PC. Check the link for PC capture software and project d
💻 C
字号:
/*
 * File:        nrf24l01.c
 * Purpose:     nRF24L01 handler functions
 * Author:      Peter Ivanov, Olimex Ltd.
 * Modified by:
 * Created:     2007-10-14 11:29:32
 * Last modify: 2007-10-21 11:50:26 ivanovp {Time-stamp}
 * Copyright:   (C) Peter Ivanov, 2007
 * Licence:     GPL
 */
/**
 * \file nrf24l01.c
 * \brief nRF24L01 handler functions. This is for MOD-NRF24Lx (MOD-NRF24LR or MOD-NRF24LS) extension board. 
 * You should connect P3.0 to CSN, P3.1 to MOSI, P3.2 to MISO, P3.3 to CLK and P1.6 to CE using the EXT connector 
 * of MSP430-449STK2.
 * \author Peter Ivanov, Olimex Ltd.
 */

#include <msp430xG461x.h>
#include "nrf24l01.h"
#include "time.h"
#include "lcd.h"

#define CSN_TIME      2
#define CE_HIGH_TIME  10000

/// Receive the packets with following address
unsigned char RX_ADDRESS_P0[5]  = {5,6,7,8,9};
/// Receive the packets with following address
unsigned char RX_ADDRESS_P1[5]  = {0,1,2,3,4};
/// Transmit packets with following address
unsigned char TX_ADDRESS[5]     = {5,6,7,8,9};
unsigned char ADDRESS[5];

unsigned char status;

/**
 * Software delay.
 *
 * @param a Number of loop.
 */
void Delay (unsigned long a)
{ 
    while (--a != 0); 
}

/**
 * Internally used function to switch /CS line to high.
 */
inline void CSN_HIGH (void)
{
    P8OUT |= BIT3; // P8.3 HIGH
}

/**
 * Internally used function to switch /CS line to low.
 */
void CSN_LOW (void)
{ 
    Delay (CSN_TIME);
    P8OUT &= ~BIT3; // P8.3 LOW
}

/**
 * Internal function to enable chip nRF24L01 (switch chip enable line to high).
 */
void CE_HIGH(void)
{ 
    P8OUT |= BIT4; // P8.4 HIGH
    Delay (CE_HIGH_TIME); 
}

/**
 * Internally used function to disable chip nRF24L01 (switch chip enable line to low).
 */
inline void CE_LOW(void)
{
    P8OUT &= ~BIT4; // P8.4 LOW
}

/**
 * Internally used function to transmit and receive a byte via SPI channel.
 *
 * @param data One byte to send.
 * @return Received byte.
 */
unsigned char SPI_SendByte(unsigned char data)
{
    while ((IFG2 & UCA0TXIFG) == 0);    // wait while not ready / for RX
    UCA0TXBUF = data;                   // write
    while ((IFG2 & UCA0RXIFG) == 0);    // wait for RX buffer (full)
    return (UCA0RXBUF);
}

/**
 * Internally used function to send command to the chip NRF24L01 via SPI.
 *
 * @param cmd Command to send. Example: R_REGISTER
 * @param addr Address to send. Example: RX_ADDR_P0
 * @param data_byte Data byte to send. This data byte will not be sent in some cases! Check source code!
 * @return Status.
 */
unsigned char SPI_Send_command_with_ADDR (unsigned char cmd, unsigned char addr, unsigned char data_byte)
{
    unsigned char temp,command = 0;
    int j, k;
    command = (cmd << 5) | addr;
    CSN_LOW();
    if (cmd == R_REGISTER)
    {
        if (addr == RX_ADDR_P0 || addr == RX_ADDR_P1 || addr == TX_ADDR)
        {

            status = SPI_SendByte(command);
            for (k = 0; k < 5; k++)
            {
                ADDRESS[k] = SPI_SendByte(NRF_NOP);
            }
            CSN_HIGH();
            return status;
        }
        else
        {
            status = SPI_SendByte(command);
            temp = SPI_SendByte(NRF_NOP);
            CSN_HIGH();
            return temp;
        }
    }
    if (cmd == W_REGISTER)
    {
        if (addr == RX_ADDR_P0)
        {
            status = SPI_SendByte(command);
            for (j = 0; j < 5; j++)
            {
                temp = RX_ADDRESS_P0[j];
                SPI_SendByte(temp);
            }
            CSN_HIGH();
            return status;
        }

        if (addr == RX_ADDR_P1)
        {
            status = SPI_SendByte(command);
            for (j = 0; j < 5;j++)
            {
                temp = RX_ADDRESS_P1[j];
                SPI_SendByte(temp);
            }
            CSN_HIGH();
            return status;
        }

        if (addr == TX_ADDR)
        {
            status = SPI_SendByte(command);
            for (j = 0; j < 5;j++)
            {
                temp = TX_ADDRESS[j];
                SPI_SendByte(temp);
            }
            CSN_HIGH();
            return status;
        }
        else
        {
            temp = SPI_SendByte(command);
            SPI_SendByte(data_byte);
            CSN_HIGH();
            return temp;
        }
    }

    return 1;
}

unsigned char SPI_Send_command_without_ADDR (unsigned char cmd, unsigned char data_byte)
{
    unsigned char temp = 0;
    CSN_LOW();
    if (cmd == R_RX_PAYLOAD)
    {
        status = SPI_SendByte(cmd);
        temp = SPI_SendByte(NRF_NOP);
        CSN_HIGH();
        return temp;
    }
    if (cmd == W_TX_PAYLOAD)
    {
        status = SPI_SendByte(cmd);
        SPI_SendByte(data_byte);
        CSN_HIGH();
        return status;
    }
    status = SPI_SendByte(cmd);
    CSN_HIGH();
    return status;

}

// Setting for nRF chip
void NRF_init (void)
{
    ////////////////////////////
    // Initialize SPI interface
    ////////////////////////////
    // master mode, data valid on rising edge, msb first
    UCA0CTL0 = UCCKPH + UCMST + UCMSB + UCSYNC;

    // clock -> SMCLK
    UCA0CTL1 = UCSSEL1;

    // Baud Rate
    UCA0BR0 = 0x02;
    UCA0BR1 = 0x00;
    
    //UCA0MCTL = 0x00;

    P7SEL |= BIT1 | BIT2 | BIT3;    // P7.1-3 SPI option select
    P7DIR |= BIT1 | BIT3;           // P7.1 (MOSI) and P7.3 (CLK) are outputs
    P7DIR &= ~BIT2;                 // P7.2 (MISO) is input
    P8DIR |= BIT3 | BIT4;           // P8.3 (#CS) and P8.4 (CE) are outputs
    P8DIR &= ~BIT5;                 // P8.5 (IRQ) is input

    // Disable CS
    CSN_HIGH();

    ///////////////////////////
    // Configure chip nRF24L01
    ///////////////////////////

    // Discard transmission
    CE_LOW();

    //Write CONFIG register (addres - 0x00)
    //00001010 - CRC enable, power-up, RX
    status = SPI_Send_command_with_ADDR(W_REGISTER, CONFIG_REG_ADDR, 0x0B);
    //Write RX_ADDR_P0 register -> Set receive address data Pipe0 -> address in RX_ADDRESS_P0 array
    status = SPI_Send_command_with_ADDR(W_REGISTER, RX_ADDR_P0, NRF_NOP);
    //Write RX_ADDR_P1 register -> Set receive address data Pipe1 -> address in RX_ADDRESS_P1 array
    status = SPI_Send_command_with_ADDR(W_REGISTER, RX_ADDR_P1, NRF_NOP);
    //Write TX_ADDR register -> Transmit address. Used for a PTX device only. Address in TX_ADDRESS array
    status = SPI_Send_command_with_ADDR(W_REGISTER, TX_ADDR, NRF_NOP);
    //Write RX_PW_P0 register -> Set number of bytes in RX payload in data pipe0 -> 1 byte
    status = SPI_Send_command_with_ADDR(W_REGISTER, RX_PW_P0, 1);
    //Write RX_PW_P1 register -> Set number of bytes in RX payload in data pipe1 -> 1 byte
    status = SPI_Send_command_with_ADDR(W_REGISTER, RX_PW_P1, 1);
    NRF_prepareForReceive ();
}

/**
 * Send one byte to the air via chip nRF24L01.
 * Addresses are hardcoded:
 * @see RX_ADDRESS_P0 RX_ADDRESS_P1 TX_ADDRESS
 *
 * @param byte The data byte to send.
 */
void NRF_send (uint8_t byte)
{
    uint8_t status_temp;

    // Chip enable low
    CE_LOW();

    // Setting for TX device
    // Write CONFIG register -> 00001010 - CRC enable, power-up, TX
    status = SPI_Send_command_with_ADDR (W_REGISTER,CONFIG_REG_ADDR, 0x0A);

    // Send payload - send any data
    status = SPI_Send_command_without_ADDR (W_TX_PAYLOAD, byte);

    // Pulse for CE -> starts the transmission.
    CE_HIGH();
    CE_LOW();

    // Read STATUS register
    status = SPI_Send_command_without_ADDR(NRF_NOP, NRF_NOP);

    // if exceed number of transmision packets
    if ((status & MAX_RT) != 0) 
    {

        // Clear MAX_RT bit in status register
        status_temp = SPI_Send_command_with_ADDR(W_REGISTER, STATUS_ADDR, (status|MAX_RT));

        // No communication event here
        LCD_printf ("MAX_RT\n");

        // Flush TX FIFO (in TX mode)
        status_temp = SPI_Send_command_without_ADDR(FLUSH_TX, NRF_NOP); // XXX test code
    }

    // If packet sent on TX
    if ((status & TX_DS) != 0) 
    {
        // Clear TX_DS bit in status register
        status_temp = SPI_Send_command_with_ADDR(W_REGISTER, STATUS_ADDR, (status|TX_DS));

        // Your code here
        //LCD_printf ("TX_DS\n");
    }

    // If TX full
    if ((status & TX_FULL) != 0)
    {
        // Flush TX FIFO (in TX mode)
        status_temp = SPI_Send_command_without_ADDR(FLUSH_TX, NRF_NOP);

        // Your code here
        // ...
        LCD_printf ("TX_FULL\n");
    }

}

/**
 * After sending a byte you may set the device to RX mode.
 */
void NRF_prepareForReceive ()
{
    // Setting for RX device
    //Write CONFIG register -> 00001010 - CRC enable, power-up, RX
    status = SPI_Send_command_with_ADDR(W_REGISTER,CONFIG_REG_ADDR, 0x0B);
}

/**
 * Receive one byte from the air via chip nRF24L01. 
 * Addresses are hardcoded:
 * @see RX_ADDRESS_P0 RX_ADDRESS_P1 TX_ADDRESS
 *
 * @param byte The data byte to receive.
 * @return TRUE: if byte succesfully received.
 *         FALSE: if no input data.
 */
bool_t NRF_receive (uint8_t *const byte)
{
    uint8_t payload;
    uint8_t status_temp;

    CE_HIGH ();
    if (IRQ ()) // check interrupt line of nRF24L01...
    {
        // Read STATUS status register
        status = SPI_Send_command_without_ADDR(NRF_NOP, NRF_NOP);

        // Set high when new data arrives RX FIFO
        if ((status & RX_DR) != 0)
        {
            // Chip enable low
            CE_LOW();

            //Read payload data
            payload = SPI_Send_command_without_ADDR(R_RX_PAYLOAD, NRF_NOP);

            // Clear RX_DR bit in status register
            status_temp = SPI_Send_command_with_ADDR(W_REGISTER, STATUS_ADDR, (status|RX_DR));

            *byte = payload;

            // Flush RX FIFO
            status_temp = SPI_Send_command_without_ADDR(FLUSH_RX, NRF_NOP); // XXX test code
            return TRUE;
        }
    }
    return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -