Files
stc32g128k/Drivers/rf.c

338 lines
9.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 "../App/rgb.h"
#include "intrins.h"
// ATR5179 射频前端天线开关控制引脚定义
sbit RF_TX = P2^0; // V1 控制端 (1: 选通天线到发射 TX 路径)
sbit RF_RX = P3^7; // V2 控制端 (1: 选通天线到接收 RX 路径)
// 射频芯片数据与电源控制引脚定义 (根据新版 PCB 引脚对调修正)
sbit RF_TX_DAT = P2^1; // LR690L 发射调制数据输入引脚 (DIN) - 物理连接 Pin 22 (P2.1)
sbit RF_RX_DATA = P3^6; // LR690L 接收解调数据输出引脚 (DATA) - 物理连接 Pin 19 (P3.6)
// 声明外部延时及串口打印函数 (在 system.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_SendHex32(u32 val);
extern void Uart_SendByte(u8 dat);
/**
* @brief 初始化无线射频芯片相关的 GPIO 引脚方向与状态
*/
void RF_Init(void)
{
// EAXFR = 1 允许访问扩展特殊功能寄存器 (XSFR)
EAXFR = 1;
// 1. 配置 P2.0 (RF_TX) 和 P2.1 (RF_TX_DAT) 为推挽输出模式 (M1=0, M0=1)
P2M1 &= ~((1 << 0) | (1 << 1));
P2M0 |= ((1 << 0) | (1 << 1));
// 2. 配置 P3.7 (RF_RX) 和 P3.5 (SHUT) 为推挽输出模式 (M1=0, M0=1)
// 配置 P3.6 (RF_RX_DATA) 为高阻输入模式 (M1=1, M0=0)以匹配接收解调输入
P3M1 &= ~((1 << 5) | (1 << 7));
P3M1 |= (1 << 6);
P3M0 &= ~(1 << 6);
P3M0 |= ((1 << 5) | (1 << 7));
// 3. 设置系统默认的初始电平
RF_TX = 0; // 断开发射天线通路
SHUT = 1; // 默认拉高 SHUT使 LR690L 处于休眠关闭状态
RF_RX = 0; // 断开接收天线通路
RF_TX_DAT = 0; // 调制发送数据线置低
}
/**
* @brief 配置无线射频收发系统的运行模式与天线切换
* @param mode 运行模式 (0-休眠隔离, 1-接收工作, 2-发射工作)
*/
void RF_SetMode(u8 mode)
{
if (mode == 0) // ====== 模式 0: 休眠隔离模式 (Sleep/Idle) ======
{
SHUT = 1; // 强制拉高 SHUT 引脚,使 LR690L 彻底进入低功耗待机
RF_RX = 0; // 关闭接收天线开关,防止外界电磁杂波串入接收电路
RF_TX = 0; // 关闭发射天线开关
}
else if (mode == 1) // ====== 模式 1: 接收工作模式 (RX Mode) ======
{
SHUT = 0; // 拉低 SHUT 使能 LR690L 芯片,开始解调接收
RF_TX = 0; // 关闭发射开关
RF_RX = 1; // 选通天线到 RX 接收路径,使能接收链路高频放大
}
else if (mode == 2) // ====== 模式 2: 发发射工作模式 (TX Mode) ======
{
SHUT = 1; // 接收机停机,防止发射强信号顶坏接收前端
RF_RX = 0; // 关闭接收开关
RF_TX = 1; // 选通天线到 TX 发射路径,使能天线发射
}
}
/**
* @brief 按照 EV1527 协议单次调制发送一帧 24 位射频数据 (Sync + 24bit Data)
*/
void EV1527_TxFrame(u32 addr, u8 dat)
{
u8 i;
u32 tx_val;
// 合并 20 位物理地址与 4 位数据码,构建完整 24 位载波包
tx_val = (addr << 4) | (dat & 0x0F);
// 1. 同步头发送:高电平持续 1T (约 350us),低电平持续 31T (约 10850us)
RF_TX_DAT = 1;
Delay_us(350);
RF_TX_DAT = 0;
Delay_us(10850);
// 2. 依次调制发送 24 位脉宽数据位
for (i = 0; i < 24; i++)
{
if (tx_val & (0x800000UL >> i))
{
// 数据 "1":高电平持续 3T (1050us),低电平持续 1T (350us)
RF_TX_DAT = 1;
Delay_us(1050);
RF_TX_DAT = 0;
Delay_us(350);
}
else
{
// 数据 "0":高电平持续 1T (350us),低电平持续 3T (1050us)
RF_TX_DAT = 1;
Delay_us(350);
RF_TX_DAT = 0;
Delay_us(1050);
}
}
}
/**
* @brief 连续多次发送 EV1527 射频帧,防止单帧丢失
*/
void EV1527_Transmit(u32 addr, u8 dat)
{
u8 i;
RF_SetMode(2); // 切换为发射状态,接通发射开关并隔离接收端
Delay_ms(5); // 稳定天线射频通路
// 循环发送 10 帧,确保接收端至少有 1 帧被无差错捕获
for (i = 0; i < 10; i++)
{
EV1527_TxFrame(addr, dat);
Delay_ms(10); // 帧间保护延时
}
RF_TX_DAT = 0; // 归零发送数据线
RF_SetMode(1); // 重新恢复为接收监听常态,以便监测反馈
}
/**
* @brief 获取特定电平引脚状态的持续微秒时间 (利用 Timer0 硬件测量)
*/
u16 GetPulseDuration(u8 state, u16 timeout_us)
{
u16 timeout_ticks;
// 强制关闭 Timer0 计数器,并将其计数值清零复位
TR0 = 0;
TMOD &= 0xF0; // 设置 Timer0 寄存器为模式 0 (16位自动重载)
TL0 = 0x00;
TH0 = 0x00;
// 换算 16 位定时器所需的最大 ticks 超时值 (在 1T 模式 24MHz 下1 Tick = 1 / 24M = 0.0416us)
// 但此系统 Timer0 默认配置为 12T 模式 (1 Tick = 12 / 24MHz = 0.5us)
timeout_ticks = (u16)((u32)timeout_us * (MAIN_Fosc / 1000000UL) / 12UL);
TR0 = 1; // 启动 Timer0 硬件计数器
// 根据要捕获的电平状态进行阻塞判断,直到电平发生翻转或计数超时
while (RF_RX_DATA == state)
{
if (GetTimer0_Safe() > timeout_ticks)
{
TR0 = 0;
return 0; // 判定超时,返回 0
}
}
TR0 = 0; // 关断定时器
return (u16)((u32)GetTimer0_Safe() * 12UL / (MAIN_Fosc / 1000000UL));
}
// 模拟射频信号全局变量定义
volatile u32 mock_rx_addr = 0;
volatile u8 mock_rx_data = 0;
volatile bit mock_rf_ready = 0;
/**
* @brief 阻塞式检测并解码一个合法的 EV1527 射频信号数据帧
*/
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];
// 检查模拟射频触发
if (mock_rf_ready) {
mock_rf_ready = 0;
*out_addr = mock_rx_addr;
*out_data = mock_rx_data;
return 1;
}
// ====== 1. 同步头引导脉冲捕获 ======
{
u16 wait_cnt = 0;
while (RF_RX_DATA == 1)
{
Delay_us(5);
wait_cnt++;
if (wait_cnt > 2000) // 10 毫秒超时保护
return 0;
}
wait_cnt = 0;
while (RF_RX_DATA == 0)
{
Delay_us(5);
wait_cnt++;
if (wait_cnt > 4000) // 20 毫秒超时保护
return 0;
}
}
// 捕获引导头高电平时间
high_time = GetPulseDuration(1, 2500);
if (high_time < 50 || high_time > 2500) {
return 0;
}
// 捕获引导头后续的 31T 低电平时间
low_time = GetPulseDuration(0, 60000);
if (low_time < 1500 || low_time > 60000) {
return 0;
}
// 同步引导脉冲的基准时间 T 计算 (引导脉冲高电平宽度即为 1T)
T = high_time;
if (T < 100 || T > 800) return 0; // 自适应范围限幅: 100us ~ 800us
// ====== 2. 依次解析 24 个数据位脉宽 ======
for (i = 0; i < 24; i++)
{
raw_h[i] = GetPulseDuration(1, 2000);
if (raw_h[i] == 0) return 0;
raw_l[i] = GetPulseDuration(0, 2000);
if (raw_l[i] == 0) return 0;
}
// ====== 3. 双端比值解调判定数据内容 ======
for (i = 0; i < 24; i++)
{
u16 total = raw_h[i] + raw_l[i];
if (total < T * 3 || total > T * 6) return 0; // 单个数据位周期必须在 3T~6T 之间
if (raw_h[i] > raw_l[i] * 2)
{
// 高电平明显长于低电平,代表逻辑 "1"
if (i < 20)
addr = (addr << 1) | 1;
else
dat = (dat << 1) | 1;
}
else if (raw_l[i] > raw_h[i] * 2)
{
// 低电平明显长于高电平,代表逻辑 "0"
if (i < 20)
addr = (addr << 1);
else
dat = (dat << 1);
}
else
{
return 0; // 电平脉冲比值不合规,判定数据帧畸变,解码作废
}
}
// 校验无误,输出解调数据
*out_addr = addr;
*out_data = dat;
return 1;
}
/**
* @brief RF 收发诊断测试功能 (支持发送与接收监听打印)
*/
void RF_DiagnosticMode(char choice)
{
if (choice == 't')
{
u8 i;
Uart_SendString("=== RF TX Test: Transmitting 20 test frames... ===\r\n");
// 开启发射模式并配置天线开关
RF_SetMode(2);
Delay_ms(5);
for (i = 0; i < 20; i++)
{
// 连续发送测试包,每次发送伴随马达短震及指示灯闪烁
MOTOR = 1;
RGB_Send(0, 150, 0, 0, 150, 0); // 绿光闪烁
EV1527_TxFrame(0x37A86UL, 0x01);
MOTOR = 0;
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(150); // 帧间隔
}
RF_TX_DAT = 0;
RF_SetMode(1); // 重新恢复接收模式
Uart_SendString("[RF] Transmit Done!\r\n");
}
else if (choice == 'r')
{
u16 wait_ms;
u32 rx_addr;
u8 rx_data;
Uart_SendString("=== RF RX Test: Listening for 5 seconds... ===\r\n");
RF_SetMode(1); // 配置进入接收模式并使能天线
Delay_ms(10);
// 5秒的非阻塞监听
for (wait_ms = 0; wait_ms < 5000; wait_ms++)
{
if (EV1527_Decode(&rx_addr, &rx_data))
{
Uart_SendString("[RF] Decoded successfully! Addr: 0x");
Uart_SendHex32(rx_addr);
Uart_SendString(", Cmd/Data: ");
Uart_SendHex8(rx_data);
Uart_SendString("\r\n");
// 收到信号后马达震动并亮青色灯提醒
MOTOR = 1;
RGB_Send(0, 150, 150, 0, 150, 150);
Delay_ms(100);
MOTOR = 0;
RGB_Send(0, 0, 0, 0, 0, 0);
}
Delay_ms(1);
}
Uart_SendString("=== RF RX Test End ===\r\n");
}
}