247 lines
6.5 KiB
C
247 lines
6.5 KiB
C
/**
|
|
* NRF24L01+ 驱动实现
|
|
*/
|
|
#include "nrf24l01.h"
|
|
#include <string.h>
|
|
|
|
/* 全局状态 */
|
|
uint8_t nrf_connected = 0;
|
|
uint8_t nrf_bind_phrase[7] = "LOVE";
|
|
uint8_t nrf_channel = 40;
|
|
uint8_t nrf_tx_addr[NRF_ADDR_WIDTH] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
|
|
|
|
/* ---- 低层 SPI 操作 ---- */
|
|
static void NRF_SPI_CS(uint8_t level) {
|
|
if (level) NRF_CSN_H(); else NRF_CSN_L();
|
|
}
|
|
|
|
static uint8_t NRF_SPI_Transfer(uint8_t dat) {
|
|
uint8_t rx;
|
|
HAL_SPI_TransmitReceive(&hspi1, &dat, &rx, 1, 10);
|
|
return rx;
|
|
}
|
|
|
|
uint8_t NRF24L01_ReadReg(uint8_t reg) {
|
|
uint8_t val;
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_R_REGISTER | reg);
|
|
val = NRF_SPI_Transfer(0xFF);
|
|
NRF_SPI_CS(1);
|
|
return val;
|
|
}
|
|
|
|
void NRF24L01_WriteReg(uint8_t reg, uint8_t value) {
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_W_REGISTER | reg);
|
|
NRF_SPI_Transfer(value);
|
|
NRF_SPI_CS(1);
|
|
}
|
|
|
|
void NRF24L01_ReadBuf(uint8_t reg, uint8_t *buf, uint8_t len) {
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_R_REGISTER | reg);
|
|
for (uint8_t i = 0; i < len; i++)
|
|
buf[i] = NRF_SPI_Transfer(0xFF);
|
|
NRF_SPI_CS(1);
|
|
}
|
|
|
|
void NRF24L01_WriteBuf(uint8_t reg, const uint8_t *buf, uint8_t len) {
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_W_REGISTER | reg);
|
|
for (uint8_t i = 0; i < len; i++)
|
|
NRF_SPI_Transfer(buf[i]);
|
|
NRF_SPI_CS(1);
|
|
}
|
|
|
|
/* ---- 初始化 ---- */
|
|
void NRF24L01_Init(void) {
|
|
NRF_CE_L();
|
|
NRF_CSN_H();
|
|
|
|
/* 上电延时 */
|
|
HAL_Delay(100);
|
|
|
|
/* 配置寄存器 */
|
|
NRF24L01_WriteReg(NRF_CONFIG, 0x0E); /* EN_CRC, CRC0, PWR_UP, PTX */
|
|
NRF24L01_WriteReg(NRF_EN_AA, 0x01); /* pipe0 auto ACK */
|
|
NRF24L01_WriteReg(NRF_EN_RXADDR, 0x01); /* pipe0 enable */
|
|
NRF24L01_WriteReg(NRF_SETUP_AW, 0x03); /* 5 bytes address */
|
|
NRF24L01_WriteReg(NRF_SETUP_RETR, 0x1A); /* 500us + 15 retries */
|
|
NRF24L01_WriteReg(NRF_RF_CH, nrf_channel);
|
|
NRF24L01_WriteReg(NRF_RF_SETUP, NRF_RATE_1M | NRF_PA_MAX);
|
|
NRF24L01_WriteReg(NRF_RX_PW_P0, 32); /* payload = 32 bytes */
|
|
NRF24L01_WriteReg(NRF_FIFO_STATUS, 0x11); /* clear FIFO */
|
|
|
|
/* 设置地址 */
|
|
NRF24L01_SetTXAddr(nrf_tx_addr);
|
|
NRF24L01_SetRXAddr(0, nrf_tx_addr);
|
|
|
|
/* 清空 FIFO */
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_FLUSH_TX);
|
|
NRF_SPI_CS(1);
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_FLUSH_RX);
|
|
NRF_SPI_CS(1);
|
|
|
|
/* 清除状态 */
|
|
NRF24L01_WriteReg(NRF_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT);
|
|
|
|
NRF_CE_L();
|
|
}
|
|
|
|
uint8_t NRF24L01_Check(void) {
|
|
uint8_t buf[5] = {0xA5, 0xA5, 0xA5, 0xA5, 0xA5};
|
|
uint8_t rx[5];
|
|
NRF24L01_WriteBuf(NRF_TX_ADDR, buf, 5);
|
|
NRF24L01_ReadBuf(NRF_TX_ADDR, rx, 5);
|
|
for (uint8_t i = 0; i < 5; i++)
|
|
if (rx[i] != 0xA5) return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* ---- 配置 ---- */
|
|
void NRF24L01_SetChannel(uint8_t ch) {
|
|
if (ch > NRF_MAX_CHANNEL) ch = NRF_MAX_CHANNEL;
|
|
nrf_channel = ch;
|
|
NRF24L01_WriteReg(NRF_RF_CH, ch);
|
|
}
|
|
|
|
void NRF24L01_SetRate(uint8_t rate) {
|
|
uint8_t rf = NRF24L01_ReadReg(NRF_RF_SETUP);
|
|
rf &= ~0x28;
|
|
rf |= (rate & 0x28);
|
|
NRF24L01_WriteReg(NRF_RF_SETUP, rf);
|
|
}
|
|
|
|
void NRF24L01_SetPower(uint8_t power) {
|
|
uint8_t rf = NRF24L01_ReadReg(NRF_RF_SETUP);
|
|
rf &= ~0x06;
|
|
rf |= (power & 0x06);
|
|
NRF24L01_WriteReg(NRF_RF_SETUP, rf);
|
|
}
|
|
|
|
void NRF24L01_SetTXAddr(const uint8_t *addr) {
|
|
memcpy(nrf_tx_addr, addr, NRF_ADDR_WIDTH);
|
|
NRF24L01_WriteBuf(NRF_TX_ADDR, addr, NRF_ADDR_WIDTH);
|
|
}
|
|
|
|
void NRF24L01_SetRXAddr(uint8_t pipe, const uint8_t *addr) {
|
|
if (pipe > 5) return;
|
|
if (pipe < 2) {
|
|
NRF24L01_WriteBuf(NRF_RX_ADDR_P0 + pipe, addr, NRF_ADDR_WIDTH);
|
|
} else {
|
|
NRF24L01_WriteReg(NRF_RX_ADDR_P0 + pipe, addr[0]);
|
|
}
|
|
}
|
|
|
|
/* ---- 模式切换 ---- */
|
|
void NRF24L01_TXMode(void) {
|
|
NRF_CE_L();
|
|
uint8_t cfg = NRF24L01_ReadReg(NRF_CONFIG);
|
|
cfg &= ~0x01; /* PRIM_RX = 0 -> TX */
|
|
NRF24L01_WriteReg(NRF_CONFIG, cfg);
|
|
NRF_CE_H();
|
|
}
|
|
|
|
void NRF24L01_RXMode(void) {
|
|
NRF_CE_L();
|
|
uint8_t cfg = NRF24L01_ReadReg(NRF_CONFIG);
|
|
cfg |= 0x01; /* PRIM_RX = 1 -> RX */
|
|
NRF24L01_WriteReg(NRF_CONFIG, cfg);
|
|
NRF_CE_H();
|
|
}
|
|
|
|
/* ---- 发送/接收 ---- */
|
|
uint8_t NRF24L01_TxPacket(const uint8_t *data, uint8_t len) {
|
|
uint8_t status;
|
|
|
|
NRF_CE_L();
|
|
|
|
/* 清 TX FIFO */
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_FLUSH_TX);
|
|
NRF_SPI_CS(1);
|
|
|
|
/* 写 payload */
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_W_TX_PAYLOAD);
|
|
for (uint8_t i = 0; i < len && i < 32; i++)
|
|
NRF_SPI_Transfer(data[i]);
|
|
NRF_SPI_CS(1);
|
|
|
|
/* 发射 */
|
|
NRF_CE_H();
|
|
HAL_Delay(1);
|
|
NRF_CE_L();
|
|
|
|
/* 等待完成 */
|
|
uint32_t timeout = 10000;
|
|
while (timeout--) {
|
|
status = NRF24L01_ReadReg(NRF_STATUS);
|
|
if (status & (NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT)) break;
|
|
}
|
|
|
|
/* 清除状态 */
|
|
NRF24L01_WriteReg(NRF_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT);
|
|
|
|
if (status & NRF_STATUS_TX_DS) {
|
|
nrf_connected = 1;
|
|
return 1; /* 发送成功 */
|
|
}
|
|
nrf_connected = 0;
|
|
return 0; /* 发送失败 */
|
|
}
|
|
|
|
uint8_t NRF24L01_RxPacket(uint8_t *data) {
|
|
uint8_t status = NRF24L01_ReadReg(NRF_STATUS);
|
|
if (!(status & NRF_STATUS_RX_DR)) return 0;
|
|
|
|
/* 读 payload */
|
|
NRF_SPI_CS(0);
|
|
NRF_SPI_Transfer(NRF_CMD_R_RX_PAYLOAD);
|
|
for (uint8_t i = 0; i < 32; i++)
|
|
data[i] = NRF_SPI_Transfer(0xFF);
|
|
NRF_SPI_CS(1);
|
|
|
|
/* 清除 RX_DR */
|
|
NRF24L01_WriteReg(NRF_STATUS, NRF_STATUS_RX_DR);
|
|
|
|
return 1;
|
|
}
|
|
|
|
uint8_t NRF24L01_IsDataReady(void) {
|
|
uint8_t status = NRF24L01_ReadReg(NRF_STATUS);
|
|
return (status & NRF_STATUS_RX_DR) ? 1 : 0;
|
|
}
|
|
|
|
/* ---- 对频 ---- */
|
|
void NRF24L01_BindMode(void) {
|
|
/* 进入接收模式,监听对频请求 */
|
|
NRF_CE_L();
|
|
NRF24L01_WriteReg(NRF_CONFIG, 0x0F); /* PRX, PWR_UP, CRC */
|
|
NRF24L01_WriteReg(NRF_EN_RXADDR, 0x01);
|
|
NRF24L01_WriteReg(NRF_RX_PW_P0, 32);
|
|
NRF24L01_WriteBuf(NRF_RX_ADDR_P0, nrf_tx_addr, NRF_ADDR_WIDTH);
|
|
NRF24L01_WriteReg(NRF_STATUS, 0x70);
|
|
NRF_CE_H();
|
|
}
|
|
|
|
uint8_t NRF24L01_BindScan(uint8_t *found_addr) {
|
|
/* 扫描所有通道寻找对频设备 */
|
|
for (uint8_t ch = 0; ch <= NRF_MAX_CHANNEL; ch++) {
|
|
NRF24L01_SetChannel(ch);
|
|
HAL_Delay(2);
|
|
if (NRF24L01_RxPacket(found_addr)) {
|
|
/* 验证对频短语 */
|
|
if (memcmp(found_addr, nrf_bind_phrase, strlen((char*)nrf_bind_phrase)) == 0) {
|
|
/* 对频成功,记录地址 */
|
|
memcpy(nrf_tx_addr, found_addr + 6, NRF_ADDR_WIDTH);
|
|
nrf_connected = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|