docs: 为所有代码源文件添加详细中文注释,并在设计文档中纠正GPIO物理引脚映射表

This commit is contained in:
Antigravity IDE
2026-07-16 17:52:52 +08:00
parent afd59d28ee
commit 731115e09a
26 changed files with 32803 additions and 53495 deletions

View File

@@ -1,18 +1,17 @@
#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 路径)
// 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:休眠)
// 射频芯片数据与电源控制引脚定义
sbit RF_TX_DAT = P3^6; // LT4455 发射调制数据输入引脚 (DIN)
sbit RF_RX_DATA = P2^1; // LR690L 接收解调数据输出引脚 (DATA),连接单片机中断管脚
sbit SHUT = P2^2; // LR690L 芯片休眠控制引脚 (1:休眠0:工作)
// External functions defined in main.c
// 声明外部延时及串口打印函数 (在 system.c 中定义)
extern void Delay_us(u16 us);
extern void Delay_ms(u16 ms);
extern u16 GetTimer0_Safe(void);
@@ -23,61 +22,80 @@ extern void Uart_SendHex16(u16 val);
extern void Uart_SendHex20(u32 val);
extern void Uart_SendByte(u8 dat);
/**
* @brief 初始化无线射频芯片相关的 GPIO 引脚方向与初始状态
*/
void RF_Init(void)
{
// P2.0 (RF_TX) 和 P2.2 (SHUT) 配置为推挽输出P2.1 (RF_RX_DATA) 配置为双向口/输入
// 1. 配置 P2.0 (RF_TX) 和 P2.2 (SHUT) 为推挽输出模式 (M1=0, M0=1)
// 配置 P2.1 (RF_RX_DATA) 为准双向口/输入模式 (M1=0, M0=0)
P2M1 &= ~((1 << 0) | (1 << 1) | (1 << 2));
P2M0 &= ~(1 << 1);
P2M0 |= ((1 << 0) | (1 << 2));
// P3.6 (RF_TX_DAT), P3.7 (RF_RX) 配置为推挽输出
// 2. 配置 P3.6 (RF_TX_DAT) P3.7 (RF_RX) 为推挽输出模式 (M1=0, M0=1)
P3M1 &= ~((1 << 6) | (1 << 7));
P3M0 |= ((1 << 6) | (1 << 7));
RF_TX = 0;
SHUT = 1; // 默认关闭接收芯片
RF_RX = 0;
RF_TX_DAT = 0;
// 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) // Sleep/Idle
if (mode == 0) // ====== 模式 0: 休眠隔离模式 (Sleep/Idle) ======
{
SHUT = 1; // LR690L Sleep
RF_RX = 0; // 断开接收天线
RF_TX = 0; // 断开发射天线
SHUT = 1; // 强制拉高 SHUT 引脚,使 LR690L 彻底进入低功耗待机
RF_RX = 0; // 关闭接收天线开关,防止外界电磁杂波串入接收电路
RF_TX = 0; // 关闭发射天线开关
}
else if (mode == 1) // Rx Mode
else if (mode == 1) // ====== 模式 1: 射频接收模式 (Rx Mode) ======
{
SHUT = 0; // LR690L 工作
RF_RX = 1; // 天线切至接收端
RF_TX = 0;
SHUT = 0; // 拉低 SHUT启动并使能 LR690L 接收解调芯片工作
RF_RX = 1; // 选通天线切换开关到 RX 路径,连通物理接收天线
RF_TX = 0; // 断开 TX 发射路径,防止回环烧毁前端
}
else if (mode == 2) // Tx Mode
else if (mode == 2) // ====== 模式 2: 射频发射模式 (Tx Mode) ======
{
SHUT = 1; // LR690L 睡眠
RF_RX = 0;
RF_TX = 1; // 天线切发射
SHUT = 1; // 关闭 LR690L 接收芯片,避免发射大功率波形串入接收机
RF_RX = 0; // 断开接收路径天线
RF_TX = 1; // 选通天线切换开关至 TX 路径,连通物理天线进行发射
}
}
/**
* @brief 按 EV1527 载波规范单次调制发送一帧 24 位无线射频数据
* @param addr 20 位的发射地址编码
* @param dat 4 位的命令状态码
* @details EV1527 是常见的无线编码格式:
* - 一个基本脉冲周期设为 T ≈ 320us。
* - 同步头脉冲: 1T 高电平 (320us) + 31T 低电平 (9920us)。
* - 数据位 '1' (逻辑1) 编码: 3T 高电平 (960us) + 1T 低电平 (320us)。
* - 数据位 '0' (逻辑0) 编码: 1T 高电平 (320us) + 3T 低电平 (960us)。
*/
void EV1527_TxFrame(u32 addr, u8 dat)
{
u8 i;
// 1. 同步脉冲: 1T 高电平 + 31T 低电平
// ====== 1. 发送同步引导脉冲 ======
RF_TX_DAT = 1;
Delay_us(320);
Delay_us(320); // 1T 高电平
RF_TX_DAT = 0;
Delay_us(9920);
Delay_us(9920); // 31T 低电平
// 2. 20位地址码 (MSB first)
// ====== 2. 依次调制发送 20 位物理地址码 (高位 MSB 优先发送) ======
for (i = 0; i < 20; i++)
{
if ((addr >> (19 - i)) & 1)
{
// 逻辑 1: 3T 高电平 + 1T 低电平
// 数据 bit 1: 3T + 1T
RF_TX_DAT = 1;
Delay_us(960);
RF_TX_DAT = 0;
@@ -85,7 +103,7 @@ void EV1527_TxFrame(u32 addr, u8 dat)
}
else
{
// 逻辑 0: 1T 高电平 + 3T 低电平
// 数据 bit 0: 1T + 3T
RF_TX_DAT = 1;
Delay_us(320);
RF_TX_DAT = 0;
@@ -93,12 +111,12 @@ void EV1527_TxFrame(u32 addr, u8 dat)
}
}
// 3. 4位数据码 (MSB first)
// ====== 3. 依次调制发送 4 位指令状态数据码 (高位 MSB 优先) ======
for (i = 0; i < 4; i++)
{
if ((dat >> (3 - i)) & 1)
{
// 逻辑 1: 3T 高电平 + 1T 低电平
// 数据 bit 1: 3T + 1T
RF_TX_DAT = 1;
Delay_us(960);
RF_TX_DAT = 0;
@@ -106,7 +124,7 @@ void EV1527_TxFrame(u32 addr, u8 dat)
}
else
{
// 逻辑 0: 1T 高电平 + 3T 低电平
// 数据 bit 0: 1T + 3T
RF_TX_DAT = 1;
Delay_us(320);
RF_TX_DAT = 0;
@@ -115,33 +133,62 @@ void EV1527_TxFrame(u32 addr, u8 dat)
}
}
/**
* @brief 循环发射多帧无线 EV1527 信号以保证数据通信的完整性
* @param addr 20位源地址
* @param dat 4位命令码
*/
void EV1527_Transmit(u32 addr, u8 dat)
{
u8 r;
for (r = 0; r < 25; r++) // 增加到 25 帧(约 340ms
// 循环发射 25 次相同的射频帧 (累计耗时约 340 毫秒),抵御外界瞬间同频杂波干扰
for (r = 0; r < 25; r++)
{
EV1527_TxFrame(addr, dat);
}
}
/**
* @brief 使用定时器 0 (Timer0) 高精度的测量引脚指定电平状态的持续宽度时间
* @param state 待测电平状态 (1-测量高电平持续宽度, 0-测量低电平持续宽度)
* @param timeout_us 最大等待超时微秒数上限,超时自动退出防锁死
* @return u16 最终测量的实际电平持续微秒数。若发生超时则直接返回 0。
*/
u16 GetPulseDuration(u8 state, u16 timeout_us)
{
// 根据系统晶振频率计算在 12T 模式下目标超时的 Timer0 Tick 数值上限
u16 timeout_ticks = (u16)((u32)timeout_us * (MAIN_Fosc / 1000000UL) / 12UL);
TL0 = 0;
TL0 = 0; // 定时器 0 计数值清零
TH0 = 0;
TR0 = 1; // 启动定时器0
TR0 = 1; // 启动定时器 0 硬件计数
// 轮询引脚:只要电平仍旧等于目标待测状态,就继续保持循环
while (RF_RX_DATA == state)
{
// 软件防卡死判定:如果当前计数值超过了设定的最大允许超时 Tick 值
if (GetTimer0_Safe() > timeout_ticks)
{
TR0 = 0;
return 0; // 超时
TR0 = 0; // 关断定时器
return 0; // 判定超时,返回 0
}
}
TR0 = 0;
return (u16)((u32)GetTimer0_Safe() * 12UL / (MAIN_Fosc / 1000000UL)); // 返回微秒数
TR0 = 0; // 关断定时器
// 将最终读取的 Timer0 硬件 Tick 数值,重新换算成微秒数返回 (1 Tick = 12 / 24MHz = 0.5us)
return (u16)((u32)GetTimer0_Safe() * 12UL / (MAIN_Fosc / 1000000UL));
}
/**
* @brief 软件自适应解码接收一帧无线 EV1527 信号
* @param out_addr 解码成功后,用于回传物理地址高 20 位的指针
* @param out_data 解码成功后,用于回传指令数据低 4 位的指针
* @return bit 1-解码成功且校验通过0-捕获失败或脉冲畸变
* @note 核心算法:
* 1. 等待并寻找合法的同步引导头脉冲 (1T高电平 + 31T低电平其中低/高比率约为 31本程序允许比率在 15~48 内变化以抗物理畸变)。
* 2. 依据捕获的同步低电平宽度估算基准周期 T = low_time / 31。
* 3. 随后依次高精度捕获 24 个数据位的高电平和低电平时间。
* 4. 自适应决策:对于每个 bit如果其高电平时间 raw_h > 低电平时间 raw_l则判定该位为 1否则判定该位为 0。
*/
bit EV1527_Decode(u32 *out_addr, u8 *out_data)
{
u16 high_time, low_time;
@@ -149,68 +196,97 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
u32 addr = 0;
u8 dat = 0;
u16 T;
u16 idata raw_h[24];
u16 idata raw_l[24];
u16 idata raw_h[24]; // 高电平时间寄存数组 (置于 idata 区)
u16 idata raw_l[24]; // 低电平时间寄存数组
// 1. 同步头捕获: 必须是低电平状态之后变高电平开始
if (RF_RX_DATA == 0)
// ====== 1. 同步头引导脉冲捕获 (定位上升沿) ======
{
u16 wait_cnt = 0;
while (RF_RX_DATA == 0)
// 如果当前射频解调输出是高电平,等待其变低
while (RF_RX_DATA == 1)
{
Delay_us(10);
Delay_us(5);
wait_cnt++;
if (wait_cnt > 3000) // 30ms 超时
if (wait_cnt > 2000) // 10 毫秒超时保护
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;
// 等待下一个数据脉冲的上升沿 (如果当前是低电平,等待它变高)
// 当引脚维持在低电平后,阻塞等待它跳变为高电平(捕获到同步引导信号的上升沿)
wait_cnt = 0;
while (RF_RX_DATA == 0)
{
Delay_us(5);
wait_cnt++;
if (wait_cnt > 1000) // 5ms 超时
if (wait_cnt > 4000) // 20 毫秒超时保护
return 0;
}
}
// 捕获引导头高电平时间 (放宽测量阈值上限至 2500 微秒)
high_time = GetPulseDuration(1, 2500);
if (high_time < 50 || high_time > 2500) {
if (high_time > 10) { // 剔除高频毛刺噪声,防止调试串口满载
Uart_SendString("Sync H Err: ");
Uart_SendHex16(high_time);
Uart_SendString("us\r\n");
}
return 0;
}
// 捕获引导头后续的 31T 低电平时间 (设定上限 60 毫秒)
low_time = GetPulseDuration(0, 60000);
if (low_time < 1500 || low_time > 60000) {
Uart_SendString("Sync L Err H=");
Uart_SendHex16(high_time);
Uart_SendString(" L=");
Uart_SendHex16(low_time);
Uart_SendString("us\r\n");
return 0;
}
// 计算低电平与高电平的比值,以检验是否满足 EV1527 的 31:1 特征
{
u32 ratio = (u32)low_time / high_time;
if (ratio < 15 || ratio > 48) { // 允许 50% 左右的空气无线传输畸变误差
Uart_SendString("Sync Ratio Err H=");
Uart_SendHex16(high_time);
Uart_SendString(" L=");
Uart_SendHex16(low_time);
Uart_SendString(" R=");
Uart_SendHex16((u16)ratio);
Uart_SendString("\r\n");
return 0;
}
}
// 自适应估算出基准脉冲时值 T
T = low_time / 31;
if (T == 0) T = 1; // 零安全防护
// ====== 2. 依次采集接下来的 24 个数据 bit 脉冲 ======
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; // 解码失败
return 0; // 捕获失败
}
}
// 测量高电平持续时间和低电平持续时间
// 精密测算本位的高电平与低电平宽度
raw_h[i] = GetPulseDuration(1, 5000);
if (raw_h[i] == 0) return 0;
if (raw_h[i] == 0) return 0; // 超时错误直接退出
raw_l[i] = GetPulseDuration(0, 5000);
if (raw_l[i] == 0) return 0;
}
// 3. 将抓到的全部 24 位脉冲数据无条件输出到串口 (缩短输出信息以防止阻塞接收)
// ====== 3. 串口输出捕获的时序参数 ======
Uart_SendString("Captured: Sync H=");
Uart_SendHex16(high_time);
Uart_SendString("us, L=");
@@ -219,13 +295,16 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
Uart_SendHex16(T);
Uart_SendString("us\r\n");
// 4. 组合成 24 位地址数据,使用自适应阈值:如果高电平时间比低电平时间长,判定为 1反之为 0
// ====== 4. 自适应决策:组合成地址数据位 ======
for (i = 0; i < 24; i++)
{
// 比较本位高低电平持续宽度:
// 如果高电平大于低电平,说明宽脉冲在高,判定该位为 1 (3T高+1T低)。
// 否则高电平短,判定为 0 (1T高+3T低)。
if (raw_h[i] > raw_l[i])
{
if (i < 20) addr = (addr << 1) | 1;
else dat = (dat << 1) | 1;
if (i < 20) addr = (addr << 1) | 1; // 高 20 位写入物理地址
else dat = (dat << 1) | 1; // 低 4 位写入状态码
}
else
{
@@ -237,28 +316,33 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
*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;
return 1; // 成功解析
}
/**
* @brief 软硬件环路自检回环测试
* @details 将发射引脚置位并同时采样接收引脚,用于测试收发芯片控制连通性。
*/
void Loopback_Test(void)
{
u16 match_count = 0;
u16 i;
SHUT = 0; // 使能接收芯片
RF_RX = 1; // 选通天线到接收端
RF_TX = 0; // 发送侧断开
SHUT = 0; // 强行开启接收芯片供电
RF_RX = 1; // 选通天线到 RX
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;
@@ -283,6 +367,62 @@ void Loopback_Test(void)
Uart_SendString("Result: FAIL! No RF signal detected. Check hardware.\r\n");
}
SHUT = 1;
RF_RX = 0;
SHUT = 1; // 关闭接收芯片
RF_RX = 0; // 断开接收通道
}
/**
* @brief 统计接收引脚在 5 秒内的电平翻转次数,用以评估物理噪声污染度或管脚短路
*/
void RF_Test_Pin(void)
{
u8 i;
u16 j;
u16 transitions = 0;
bit last_state = RF_RX_DATA;
Uart_SendString("=== RF RX Pin Data Test Start (5 seconds) ===\r\n");
Uart_SendString("SHUT pin state: ");
Uart_SendByte(SHUT ? '1' : '0');
Uart_SendString("\r\n");
// 强制设为接收模式
RF_SetMode(1);
Delay_ms(100);
Uart_SendString("SHUT pin state (after RF_SetMode(1)): ");
Uart_SendByte(SHUT ? '1' : '0');
Uart_SendString("\r\n");
Uart_SendString("Please trigger your 433MHz transmitter now...\r\n");
// 连续进行 5 秒的高频电平抖动采样
for (i = 0; i < 5; i++)
{
transitions = 0;
// 1秒循环
for (j = 0; j < 1000; j++)
{
u8 k;
// 每次内循环进行 5 次采样,每次间隔 200us
for (k = 0; k < 5; k++)
{
bit current_state = RF_RX_DATA;
if (current_state != last_state)
{
transitions++; // 统计电平边沿翻转次数
last_state = current_state;
}
Delay_us(200);
}
}
// 输出本秒的电平跳转总数,若非发射期该数值很大,表明空中有丰富噪声噪底跳变,属接收机正常表现
Uart_SendString("Sampling... Transitions in last 1s: ");
Uart_SendHex16(transitions);
Uart_SendString(", current pin value: ");
Uart_SendByte(RF_RX_DATA ? '1' : '0');
Uart_SendString("\r\n");
}
Uart_SendString("=== RF Pin Test End ===\r\n");
}