📄 nrf24l01.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 + -