Files
ZhaTianRC/rx/NRF24.c
T
2026-06-27 14:44:10 +08:00

318 lines
9.5 KiB
C

/* ========================================================================
* NRF24L01 硬件 SPI 实现 (STC8H 内置 SPI)
* P1.3=MISO, P1.4=MOSI, P1.5=SCLK, P5.4=CSN(GPIO)
* ======================================================================== */
/* SPI 初始化: 主模式, 模式0, 6MHz @ 24MHz */
static void NRF_SPI_Init(void) {
SPCTL = SSIG | SPEN | MSTR; /* 0xD0: SSIG=1, SPEN=1, MSTR=1, CPOL=0, CPHA=0, fosc/4 */
SPSTAT = SPIF | WCOL; /* 清除标志 */
}
uint8_t NRF_SPI_TransferByte(uint8_t dat) {
SPDAT = dat;
/* 等待传输完成 */
while (!(SPSTAT & SPIF));
/* 清除 SPIF (读 SPSTAT 再读 SPDAT 自动清除, 但这里直接写1清除更可靠) */
SPSTAT = SPIF;
return SPDAT;
}
uint8_t NRF24L01_ReadReg(uint8_t reg) {
uint8_t val;
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_R_REGISTER | reg);
val = NRF_SPI_TransferByte(0xFF);
NRF_CSN = 1;
return val;
}
void NRF24L01_WriteReg(uint8_t reg, uint8_t value) {
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_W_REGISTER | reg);
NRF_SPI_TransferByte(value);
NRF_CSN = 1;
}
void NRF24L01_ReadBuf(uint8_t reg, uint8_t *buf, uint8_t len) {
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_R_REGISTER | reg);
for (uint8_t i = 0; i < len; i++)
buf[i] = NRF_SPI_TransferByte(0xFF);
NRF_CSN = 1;
}
void NRF24L01_WriteBuf(uint8_t reg, const uint8_t *buf, uint8_t len) {
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_W_REGISTER | reg);
for (uint8_t i = 0; i < len; i++)
NRF_SPI_TransferByte(buf[i]);
NRF_CSN = 1;
}
/* ========================================================================
* NRF24L01 初始化与操作
* ======================================================================== */
void NRF24L01_Init(void) {
NRF_CE = 0;
NRF_CSN = 1;
/* 初始化硬件 SPI */
NRF_SPI_Init();
/* 延时等待上电 */
for (volatile uint16_t d = 0; d < 5000; d++);
/* 配置寄存器 */
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字节地址 */
NRF24L01_WriteReg(NRF_SETUP_RETR, 0x1A); /* 500us + 15次重试 */
NRF24L01_WriteReg(NRF_RF_CH, rf_channel);
NRF24L01_WriteReg(NRF_RF_SETUP, NRF_RATE_1M | NRF_PA_MAX);
NRF24L01_WriteReg(NRF_RX_PW_P0, RF_PACKET_SIZE);
NRF24L01_WriteReg(NRF_DYNPD, 0x00); /* 关闭动态负载 */
NRF24L01_WriteReg(NRF_FEATURE, 0x00);
/* 设置地址 */
NRF24L01_WriteBuf(NRF_TX_ADDR, tx_addr, NRF_ADDR_WIDTH);
NRF24L01_WriteBuf(NRF_RX_ADDR_P0, tx_addr, NRF_ADDR_WIDTH);
/* 清空FIFO */
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_FLUSH_TX);
NRF_CSN = 1;
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_FLUSH_RX);
NRF_CSN = 1;
/* 清除状态 */
NRF24L01_WriteReg(NRF_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT);
NRF_CE = 0;
}
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;
rf_channel = ch;
NRF24L01_WriteReg(NRF_RF_CH, ch);
}
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_RXMode(void) {
NRF_CE = 0;
uint8_t cfg = NRF24L01_ReadReg(NRF_CONFIG);
cfg |= 0x01; /* PRIM_RX = 1 */
NRF24L01_WriteReg(NRF_CONFIG, cfg);
NRF_CE = 1;
}
void NRF24L01_TXMode(void) {
NRF_CE = 0;
uint8_t cfg = NRF24L01_ReadReg(NRF_CONFIG);
cfg &= ~0x01; /* PRIM_RX = 0 */
NRF24L01_WriteReg(NRF_CONFIG, cfg);
NRF_CE = 1;
}
uint8_t NRF24L01_IsDataReady(void) {
uint8_t status = NRF24L01_ReadReg(NRF_STATUS);
return (status & NRF_STATUS_RX_DR) ? 1 : 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_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_R_RX_PAYLOAD);
for (uint8_t i = 0; i < RF_PACKET_SIZE; i++)
data[i] = NRF_SPI_TransferByte(0xFF);
NRF_CSN = 1;
/* 清除 RX_DR */
NRF24L01_WriteReg(NRF_STATUS, NRF_STATUS_RX_DR);
return 1;
}
void NRF24L01_FlushRX(void) {
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_FLUSH_RX);
NRF_CSN = 1;
}
/* ========================================================================
* NRF24L01 对频
* ======================================================================== */
void NRF24L01_EnterBindMode(void) {
/* 进入接收模式, 监听对频请求 */
NRF_CE = 0;
NRF24L01_WriteReg(NRF_CONFIG, 0x0F); /* PRX, PWR_UP, CRC */
NRF24L01_WriteReg(NRF_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF_RX_PW_P0, RF_PACKET_SIZE);
NRF24L01_WriteBuf(NRF_RX_ADDR_P0, tx_addr, NRF_ADDR_WIDTH);
NRF24L01_WriteReg(NRF_STATUS, 0x70);
NRF_CE = 1;
}
void NRF_EnterBindMode(void) {
rx_state = RX_STATE_BINDING;
NRF24L01_EnterBindMode();
}
uint8_t NRF_DoBindScan(void) {
static uint8_t __xdata buf[RF_PACKET_SIZE];
/* 扫描所有通道 */
for (uint8_t ch = 0; ch <= NRF_MAX_CHANNEL; ch++) {
NRF24L01_SetChannel(ch);
for (volatile uint16_t d = 0; d < 500; d++); /* 延时 */
if (NRF24L01_RxPacket(buf)) {
/* 验证同步头 */
if (buf[0] != RF_SYNC_BYTE0 || buf[1] != RF_SYNC_BYTE1)
continue;
/* 验证对频短语 (6字节, 从偏移2开始) */
uint8_t match = 1;
for (uint8_t i = 0; i < RF_PHRASE_LEN; i++) {
if (buf[2 + i] != bind_phrase[i]) {
match = 0;
break;
}
}
if (!match) continue;
/* 对频成功! 从包中提取地址 (偏移8开始, 5字节) */
for (uint8_t i = 0; i < NRF_ADDR_WIDTH; i++) {
tx_addr[i] = buf[8 + i];
}
/* 保存配置到EEPROM */
EEPROM_SaveConfig();
/* 重新初始化NRF */
NRF24L01_Init();
NRF24L01_RXMode();
rx_state = RX_STATE_DISCONNECTED;
return 1;
}
}
return 0;
}
/* ========================================================================
* NRF24L01 数据包处理
* ======================================================================== */
void NRF_ProcessPacket(void) {
static uint8_t __xdata buf[RF_PACKET_SIZE];
if (!NRF24L01_RxPacket(buf))
return;
/* 验证同步头 */
if (buf[0] != RF_SYNC_BYTE0 || buf[1] != RF_SYNC_BYTE1)
return;
/* 验证对频短语 */
for (uint8_t i = 0; i < RF_PHRASE_LEN; i++) {
if (buf[2 + i] != bind_phrase[i])
return;
}
/* 验证校验和 (XOR) */
uint8_t checksum = 0;
for (uint8_t i = 0; i < RF_PACKET_SIZE - 1; i++)
checksum ^= buf[i];
if (checksum != buf[RF_PACKET_SIZE - 1])
return;
/* 提取通道数据 (8通道, 偏移8, 每通道2字节大端) */
for (uint8_t i = 0; i < CHANNEL_COUNT; i++) {
uint16_t raw = ((uint16_t)buf[8 + i * 2] << 8) | buf[8 + i * 2 + 1];
/* raw: 0~2000, 映射到 PWM_MIN~PWM_MAX (250~500) */
if (raw > 2000) raw = 2000;
pwm_ch[i] = (uint16_t)((uint32_t)raw * (PWM_MAX - PWM_MIN) / 2000 + PWM_MIN);
}
/* 更新 RSSI 估计: 从 NRF RPD 寄存器读取载波检测 */
if (NRF24L01_ReadReg(NRF_RPD) & 0x01) {
/* 有载波 = 信号强 */
if (telem_rssi < 100) telem_rssi += 5;
} else {
if (telem_rssi > 10) telem_rssi -= 1;
}
if (telem_rssi > 100) telem_rssi = 100;
/* 更新丢包率: 基于 lost_packet_cnt 估算 */
telem_packet_loss = 0; /* 收到包 = 当前不丢包, 累积值在外部计算 */
/* 更新状态 */
lost_packet_cnt = 0;
if (rx_state != RX_STATE_CONNECTED) {
rx_state = RX_STATE_CONNECTED;
}
}
/* ========================================================================
* NRF24L01 回传发送
* 包格式: 0xBB 0x44 + voltage(2B, mV) + rssi(1B) + loss(1B) + temp(2B)
* ======================================================================== */
static void NRF_SendTelemetry(void) {
static uint8_t __xdata tbuf[8];
tbuf[0] = 0xBB; /* sync0 */
tbuf[1] = 0x44; /* sync1 */
tbuf[2] = (uint8_t)(bat_voltage_mv >> 8); /* voltage high */
tbuf[3] = (uint8_t)(bat_voltage_mv & 0xFF); /* voltage low */
tbuf[4] = telem_rssi; /* RSSI */
tbuf[5] = telem_packet_loss; /* 丢包率 */
tbuf[6] = 0; /* temp high (未实现) */
tbuf[7] = 0; /* temp low */
/* 切到 TX 模式发送回传 */
NRF24L01_TXMode();
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_FLUSH_TX);
NRF_CSN = 1;
NRF_CSN = 0;
NRF_SPI_TransferByte(NRF_CMD_W_TX_PAYLOAD);
for (uint8_t i = 0; i < 8; i++)
NRF_SPI_TransferByte(tbuf[i]);
NRF_CSN = 1;
NRF_CE = 1;
for (volatile uint16_t d = 0; d < 100; d++);
NRF_CE = 0;
/* 切回 RX 模式 */
NRF24L01_RXMode();
NRF24L01_FlushRX();
}