Files
stc32g128k/Drivers/rf.c
2026-07-15 15:57:37 +08:00

289 lines
7.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}