291 lines
7.2 KiB
C
291 lines
7.2 KiB
C
#include "rf.h"
|
||
|
||
#include "../App/config.h"
|
||
#include "intrins.h"
|
||
|
||
// ATR5179 射频开关控制脚
|
||
sbit RF_TX = P2^0; // V1 控制端 (1: 选通天线到 TX 路径)
|
||
sbit RF_RX = P3^7; // V2 控制端 (1: 选通天线到 RX 路径)
|
||
|
||
// 射频数据与控制引脚
|
||
sbit RF_TX_DAT = P3^6; // LT4455 数据输入 (DIN)
|
||
sbit RF_RX_DATA = P2^1; // LR690L 数据输出 (DATA)
|
||
sbit SHUT = P2^2; // LR690L 休眠脚 (0:工作, 1:休眠)
|
||
|
||
// External functions defined in main.c
|
||
extern void Delay_us(u16 us);
|
||
extern void Delay_ms(u16 ms);
|
||
extern u16 GetTimer0_Safe(void);
|
||
extern void Uart_SendString(char *s);
|
||
extern void Uart_SendHex4(u8 val);
|
||
extern void Uart_SendHex8(u8 val);
|
||
extern void Uart_SendHex16(u16 val);
|
||
extern void Uart_SendHex20(u32 val);
|
||
extern void Uart_SendByte(u8 dat);
|
||
|
||
void RF_Init(void)
|
||
{
|
||
// P2.0 (RF_TX) 和 P2.2 (SHUT) 配置为推挽输出,P2.1 (RF_RX_DATA) 配置为双向口/输入
|
||
P2M1 &= ~((1 << 0) | (1 << 1) | (1 << 2));
|
||
P2M0 &= ~(1 << 1);
|
||
P2M0 |= ((1 << 0) | (1 << 2));
|
||
|
||
// P3.6 (RF_TX_DAT), P3.7 (RF_RX) 配置为推挽输出
|
||
P3M1 &= ~((1 << 6) | (1 << 7));
|
||
P3M0 |= ((1 << 6) | (1 << 7));
|
||
|
||
RF_TX = 0;
|
||
SHUT = 1; // 默认关闭接收芯片
|
||
RF_RX = 0;
|
||
RF_TX_DAT = 0;
|
||
}
|
||
|
||
void RF_SetMode(u8 mode)
|
||
{
|
||
if (mode == 0) // Sleep/Idle
|
||
{
|
||
SHUT = 1; // LR690L Sleep
|
||
RF_RX = 0; // 断开接收天线
|
||
RF_TX = 0; // 断开发射天线
|
||
}
|
||
else if (mode == 1) // Rx Mode
|
||
{
|
||
SHUT = 0; // LR690L 工作
|
||
RF_RX = 1; // 天线切至接收端
|
||
RF_TX = 0;
|
||
}
|
||
else if (mode == 2) // Tx Mode
|
||
{
|
||
SHUT = 1; // LR690L 睡眠
|
||
RF_RX = 0;
|
||
RF_TX = 1; // 天线切至发射端
|
||
}
|
||
}
|
||
|
||
void EV1527_TxFrame(u32 addr, u8 dat)
|
||
{
|
||
u8 i;
|
||
|
||
// 1. 同步脉冲: 1T 高电平 + 31T 低电平
|
||
RF_TX_DAT = 1;
|
||
Delay_us(320);
|
||
RF_TX_DAT = 0;
|
||
Delay_us(9920);
|
||
|
||
// 2. 20位地址码 (MSB first)
|
||
for (i = 0; i < 20; i++)
|
||
{
|
||
if ((addr >> (19 - i)) & 1)
|
||
{
|
||
// 逻辑 1: 3T 高电平 + 1T 低电平
|
||
RF_TX_DAT = 1;
|
||
Delay_us(960);
|
||
RF_TX_DAT = 0;
|
||
Delay_us(320);
|
||
}
|
||
else
|
||
{
|
||
// 逻辑 0: 1T 高电平 + 3T 低电平
|
||
RF_TX_DAT = 1;
|
||
Delay_us(320);
|
||
RF_TX_DAT = 0;
|
||
Delay_us(960);
|
||
}
|
||
}
|
||
|
||
// 3. 4位数据码 (MSB first)
|
||
for (i = 0; i < 4; i++)
|
||
{
|
||
if ((dat >> (3 - i)) & 1)
|
||
{
|
||
// 逻辑 1: 3T 高电平 + 1T 低电平
|
||
RF_TX_DAT = 1;
|
||
Delay_us(960);
|
||
RF_TX_DAT = 0;
|
||
Delay_us(320);
|
||
}
|
||
else
|
||
{
|
||
// 逻辑 0: 1T 高电平 + 3T 低电平
|
||
RF_TX_DAT = 1;
|
||
Delay_us(320);
|
||
RF_TX_DAT = 0;
|
||
Delay_us(960);
|
||
}
|
||
}
|
||
}
|
||
|
||
void EV1527_Transmit(u32 addr, u8 dat)
|
||
{
|
||
u8 r;
|
||
for (r = 0; r < 25; r++) // 增加到 25 帧(约 340ms)
|
||
{
|
||
EV1527_TxFrame(addr, dat);
|
||
}
|
||
}
|
||
|
||
u16 GetPulseDuration(u8 state, u16 timeout_us)
|
||
{
|
||
u16 timeout_ticks = (u16)((u32)timeout_us * (MAIN_Fosc / 1000000UL) / 12UL);
|
||
TL0 = 0;
|
||
TH0 = 0;
|
||
TR0 = 1; // 启动定时器0
|
||
while (RF_RX_DATA == state)
|
||
{
|
||
if (GetTimer0_Safe() > timeout_ticks)
|
||
{
|
||
TR0 = 0;
|
||
return 0; // 超时
|
||
}
|
||
}
|
||
TR0 = 0;
|
||
return (u16)((u32)GetTimer0_Safe() * 12UL / (MAIN_Fosc / 1000000UL)); // 返回微秒数
|
||
}
|
||
|
||
bit EV1527_Decode(u32 *out_addr, u8 *out_data)
|
||
{
|
||
u16 high_time, low_time;
|
||
u8 i;
|
||
u32 addr = 0;
|
||
u8 dat = 0;
|
||
u16 T;
|
||
u16 idata raw_h[24];
|
||
u16 idata raw_l[24];
|
||
|
||
// 1. 同步头捕获: 必须是低电平状态之后变高电平开始
|
||
if (RF_RX_DATA == 0)
|
||
{
|
||
u16 wait_cnt = 0;
|
||
while (RF_RX_DATA == 0)
|
||
{
|
||
Delay_us(10);
|
||
wait_cnt++;
|
||
if (wait_cnt > 3000) // 30ms 超时
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 测量同步头高电平时间 (放宽至 2500us)
|
||
high_time = GetPulseDuration(1, 2500);
|
||
if (high_time < 50 || high_time > 2500)
|
||
return 0;
|
||
|
||
// 测量同步头低电平时间 (放宽至 60000us)
|
||
low_time = GetPulseDuration(0, 60000);
|
||
if (low_time < 1500 || low_time > 60000)
|
||
return 0;
|
||
|
||
// 计算高低电平时间之比。对于标准 EV1527,低电平是高电平的 31 倍。
|
||
// 放宽比例范围为 15 到 48,以应对各种不同的遥控器电阻。
|
||
{
|
||
u32 ratio = (u32)low_time / high_time;
|
||
if (ratio < 15 || ratio > 48)
|
||
return 0;
|
||
}
|
||
|
||
// 估算基准脉冲周期 T = low_time / 31
|
||
T = low_time / 31;
|
||
if (T == 0) T = 1;
|
||
|
||
// 2. 连续抓取 24 个数据脉冲
|
||
for (i = 0; i < 24; i++)
|
||
{
|
||
u16 wait_cnt = 0;
|
||
// 等待下一个数据脉冲的上升沿 (如果当前是低电平,等待它变高)
|
||
while (RF_RX_DATA == 0)
|
||
{
|
||
Delay_us(5);
|
||
wait_cnt++;
|
||
if (wait_cnt > 1000) // 5ms 超时
|
||
{
|
||
return 0; // 解码失败
|
||
}
|
||
}
|
||
|
||
// 测量高电平持续时间和低电平持续时间
|
||
raw_h[i] = GetPulseDuration(1, 5000);
|
||
if (raw_h[i] == 0) return 0;
|
||
|
||
raw_l[i] = GetPulseDuration(0, 5000);
|
||
if (raw_l[i] == 0) return 0;
|
||
}
|
||
|
||
// 3. 将抓到的全部 24 位脉冲数据无条件输出到串口 (缩短输出信息以防止阻塞接收)
|
||
Uart_SendString("Captured: Sync H=");
|
||
Uart_SendHex16(high_time);
|
||
Uart_SendString("us, L=");
|
||
Uart_SendHex16(low_time);
|
||
Uart_SendString("us, T=");
|
||
Uart_SendHex16(T);
|
||
Uart_SendString("us\r\n");
|
||
|
||
// 4. 组合成 24 位地址与数据,使用自适应阈值:如果高电平时间比低电平时间长,判定为 1,反之为 0
|
||
for (i = 0; i < 24; i++)
|
||
{
|
||
if (raw_h[i] > raw_l[i])
|
||
{
|
||
if (i < 20) addr = (addr << 1) | 1;
|
||
else dat = (dat << 1) | 1;
|
||
}
|
||
else
|
||
{
|
||
if (i < 20) addr = (addr << 1);
|
||
else dat = (dat << 1);
|
||
}
|
||
}
|
||
|
||
*out_addr = addr;
|
||
*out_data = dat;
|
||
|
||
// 串口打印解码结果方便现场调试
|
||
Uart_SendString("Decoded ADDR: 0x");
|
||
Uart_SendHex20(addr);
|
||
Uart_SendString(", DATA: 0x");
|
||
Uart_SendHex4(dat);
|
||
Uart_SendString("\r\n");
|
||
|
||
return 1;
|
||
}
|
||
|
||
void Loopback_Test(void)
|
||
{
|
||
u16 match_count = 0;
|
||
u16 i;
|
||
|
||
SHUT = 0; // 使能接收芯片
|
||
RF_RX = 1; // 选通天线到接收端
|
||
RF_TX = 0; // 发送侧断开
|
||
Delay_ms(100);
|
||
|
||
Uart_SendString("Starting RF Loopback Self-Test...\r\n");
|
||
|
||
for (i = 0; i < 100; i++)
|
||
{
|
||
RF_TX_DAT = 1;
|
||
Delay_us(500);
|
||
if (RF_RX_DATA == 1) match_count++;
|
||
|
||
RF_TX_DAT = 0;
|
||
Delay_us(500);
|
||
if (RF_RX_DATA == 0) match_count++;
|
||
}
|
||
|
||
Uart_SendString("Loopback Match Count: ");
|
||
Uart_SendHex16(match_count);
|
||
Uart_SendString("/200\r\n");
|
||
|
||
if (match_count > 150)
|
||
{
|
||
Uart_SendString("Result: PASS! Transmitter is emitting RF, and Receiver is picking it up!\r\n");
|
||
}
|
||
else
|
||
{
|
||
Uart_SendString("Result: FAIL! No RF signal detected. Check hardware.\r\n");
|
||
}
|
||
|
||
SHUT = 1;
|
||
RF_RX = 0;
|
||
}
|
||
|
||
// Touched to align with doc updates V3
|