/* ======================================================================== * NRF24L01 硬件 SPI 实现 (STC8H 内置 SPI) * P1.3=MISO, P1.4=MOSI, P1.5=SCLK, P5.4=CSN(GPIO) * P1.7=IRQ, P1.6=CE, * ======================================================================== */ uint8_t SPI_ReadWrite(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(); }