312 lines
9.3 KiB
C
312 lines
9.3 KiB
C
/* ========================================================================
|
|
* 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();
|
|
}
|