STC单片机无线遥控器解码程序

一、系统概述

本程序针对常见的PT2262/PT2272编码格式无线遥控器进行解码,适用于STC89C52/STC12C5A60S2等系列单片机。

1.1 PT2262/PT2272编码格式

┌─────────────────────────────────────────────────────────────┐
│                    PT2262 编码帧格式                        │
├─────────────────────────────────────────────────────────────┤
│  同步码  │  地址码A0-A11  │  数据码D0-D3  │  同步码  │
│  (1位)   │    (12位)      │    (4位)      │  (1位)   │
└─────────────────────────────────────────────────────────────┘

脉冲宽度定义(典型值):
• 同步码:低电平4ms + 高电平124ms
• 数据位0:高电平0.5ms + 低电平0.5ms  
• 数据位1:高电平1.5ms + 低电平0.5ms

1.2 硬件连接

无线接收模块 → STC单片机
─────────────────────────
DATA引脚  → P3.2 (INT0外部中断)
VCC      → 5V电源
GND      → 电源地

二、完整代码实现

2.1 主程序代码

/**
 * @file main.c
 * @brief STC单片机无线遥控器解码程序
 * @author AI Assistant
 * @date 2024
 */

#include "reg52.h"
#include "intrins.h"

// 硬件定义
sbit RF_DATA = P3^2;    // 无线接收数据引脚 (INT0)
sbit LED = P1^0;        // 指示灯
sbit RELAY = P1^1;      // 继电器控制

// 解码参数定义
#define SYNC_LOW_MIN    3500    // 同步码低电平最小时间(us)
#define SYNC_LOW_MAX    4500    // 同步码低电平最大时间(us)
#define SYNC_HIGH_MIN   120000  // 同步码高电平最小时间(us)
#define SYNC_HIGH_MAX   130000  // 同步码高电平最大时间(us)

#define BIT0_HIGH_MIN   400     // 数据位0高电平最小时间(us)
#define BIT0_HIGH_MAX   600     // 数据位0高电平最大时间(us)
#define BIT1_HIGH_MIN   1400    // 数据位1高电平最小时间(us)
#define BIT1_HIGH_MAX   1600    // 数据位1高电平最大时间(us)

#define BIT_LOW_MIN     400     // 数据位低电平最小时间(us)
#define BIT_LOW_MAX     600     // 数据位低电平最大时间(us)

#define MAX_BITS        24      // 最大位数 (12地址+4数据+8校验)
#define TIMEOUT_US      500000 // 超时时间(us)

// 全局变量
unsigned long pulse_start_time = 0;
unsigned long pulse_end_time = 0;
unsigned long pulse_width = 0;
unsigned char bit_count = 0;
unsigned char decode_complete = 0;
unsigned char decode_error = 0;

// 解码结果
unsigned char address_high = 0;    // 地址高字节
unsigned char address_low = 0;     // 地址低字节  
unsigned char data_code = 0;       // 数据码
unsigned char decode_valid = 0;    // 解码有效标志

// 定时器0初始化(1us计数)
void Timer0_Init(void) {
    TMOD &= 0xF0;    // 清除T0控制位
    TMOD |= 0x01;    // 设置T0为模式1(16位定时器)
    TH0 = 0x00;      // 设置初始值
    TL0 = 0x00;
    ET0 = 1;         // 使能T0中断
    EA = 1;          // 使能总中断
    TR0 = 1;         // 启动T0
}

// 获取当前时间(us)
unsigned long Get_Time_Us(void) {
    unsigned long time_val;
    time_val = TH0;
    time_val = (time_val << 8) | TL0;
    return time_val;
}

// 延时函数
void Delay_Ms(unsigned int ms) {
    unsigned int i, j;
    for(i = ms; i > 0; i--)
        for(j = 110; j > 0; j--);
}

// 外部中断0初始化
void External_Int0_Init(void) {
    IT0 = 1;    // 设置INT0为下降沿触发
    EX0 = 1;    // 使能INT0中断
    EA = 1;     // 使能总中断
}

// 解码同步码
unsigned char Decode_Sync_Pulse(unsigned long high_width, unsigned long low_width) {
    // 检查同步码低电平
    if(low_width < SYNC_LOW_MIN || low_width > SYNC_LOW_MAX) {
        return 0;
    }
    
    // 检查同步码高电平
    if(high_width < SYNC_HIGH_MIN || high_width > SYNC_HIGH_MAX) {
        return 0;
    }
    
    return 1;    // 同步码有效
}

// 解码数据位
unsigned char Decode_Data_Bit(unsigned long high_width, unsigned long low_width) {
    unsigned char bit_value = 0xFF;    // 0xFF表示无效
    
    // 检查低电平宽度
    if(low_width < BIT_LOW_MIN || low_width > BIT_LOW_MAX) {
        return 0xFF;
    }
    
    // 检查高电平宽度,判断是0还是1
    if(high_width >= BIT0_HIGH_MIN && high_width <= BIT0_HIGH_MAX) {
        bit_value = 0;    // 数据位0
    }
    else if(high_width >= BIT1_HIGH_MIN && high_width <= BIT1_HIGH_MAX) {
        bit_value = 1;    // 数据位1
    }
    
    return bit_value;
}

// 外部中断0服务程序
void External_Int0_ISR(void) interrupt 0 {
    static unsigned char last_state = 1;
    unsigned char current_state;
    unsigned char bit_value;
    
    current_state = RF_DATA;
    
    if(last_state == 1 && current_state == 0) {    // 下降沿
        pulse_end_time = Get_Time_Us();
        
        if(pulse_start_time > 0) {
            pulse_width = pulse_end_time - pulse_start_time;
            
            if(decode_complete == 0 && decode_error == 0) {
                // 解码同步码
                if(bit_count == 0) {
                    if(Decode_Sync_Pulse(pulse_width, 0)) {
                        bit_count = 1;
                    }
                }
                // 解码数据位
                else if(bit_count <= MAX_BITS) {
                    bit_value = Decode_Data_Bit(pulse_width, 0);
                    
                    if(bit_value != 0xFF) {
                        // 存储解码结果
                        if(bit_count <= 12) {    // 地址位
                            if(bit_count <= 8) {
                                address_low >>= 1;
                                if(bit_value) address_low |= 0x80;
                            } else {
                                address_high >>= 1;
                                if(bit_value) address_high |= 0x80;
                            }
                        } else if(bit_count <= 16) {    // 数据位
                            data_code >>= 1;
                            if(bit_value) data_code |= 0x08;
                        }
                        
                        bit_count++;
                        
                        // 检查是否解码完成
                        if(bit_count > 16) {
                            decode_complete = 1;
                            decode_valid = 1;
                        }
                    } else {
                        decode_error = 1;    // 解码错误
                    }
                }
            }
        }
        
        pulse_start_time = pulse_end_time;
    }
    
    last_state = current_state;
}

// 定时器0中断服务程序
void Timer0_ISR(void) interrupt 1 {
    static unsigned long timeout_counter = 0;
    
    timeout_counter++;
    
    // 超时检测(约500ms)
    if(timeout_counter >= (TIMEOUT_US / 65536)) {
        if(decode_complete == 0 && bit_count > 0) {
            decode_error = 1;    // 解码超时
        }
        timeout_counter = 0;
    }
    
    // 重装初值
    TH0 = 0x00;
    TL0 = 0x00;
}

// 验证解码结果
unsigned char Verify_Decode_Result(void) {
    // 简单的地址验证(可根据实际需要修改)
    if(address_high == 0x00 && address_low == 0x00) {
        return 0;    // 无效地址
    }
    
    // 数据码验证
    if(data_code > 0x0F) {
        return 0;    // 无效数据
    }
    
    return 1;    // 验证通过
}

// 执行解码结果
void Execute_Decode_Result(void) {
    if(decode_valid && Verify_Decode_Result()) {
        LED = 0;    // 点亮指示灯
        
        // 根据数据码执行相应动作
        switch(data_code & 0x0F) {
            case 0x01:    // 按键1 - 开灯
                RELAY = 1;
                break;
            case 0x02:    // 按键2 - 关灯
                RELAY = 0;
                break;
            case 0x04:    // 按键3 - 继电器开
                RELAY = 1;
                break;
            case 0x08:    // 按键4 - 继电器关
                RELAY = 0;
                break;
            default:
                break;
        }
        
        Delay_Ms(100);
        LED = 1;    // 熄灭指示灯
        
        // 重置解码状态
        decode_complete = 0;
        decode_valid = 0;
        bit_count = 0;
    }
}

// 主函数
void main(void) {
    // 初始化
    Timer0_Init();
    External_Int0_Init();
    
    LED = 1;        // 关闭指示灯
    RELAY = 0;      // 关闭继电器
    
    // 显示启动信息
    LED = 0;
    Delay_Ms(500);
    LED = 1;
    Delay_Ms(500);
    
    while(1) {
        // 检查解码完成
        if(decode_complete) {
            Execute_Decode_Result();
        }
        
        // 解码错误处理
        if(decode_error) {
            LED = 0;
            Delay_Ms(50);
            LED = 1;
            Delay_Ms(50);
            
            // 重置解码状态
            decode_error = 0;
            decode_complete = 0;
            bit_count = 0;
            decode_valid = 0;
        }
        
        Delay_Ms(10);
    }
}

2.2 优化版本(支持更多编码格式)

/**
 * @file rf_decoder_advanced.c
 * @brief 增强版无线解码程序(支持PT2262/PT2272/EV1527)
 */

#include "reg52.h"

// 支持的编码格式
typedef enum {
    CODEC_PT2262 = 0,
    CODEC_PT2272,
    CODEC_EV1527,
    CODEC_UNKNOWN
} CodecType;

// 解码配置结构体
typedef struct {
    CodecType codec_type;
    unsigned long sync_low_min;
    unsigned long sync_low_max;
    unsigned long sync_high_min;
    unsigned long sync_high_max;
    unsigned long bit0_high_min;
    unsigned long bit0_high_max;
    unsigned long bit1_high_min;
    unsigned long bit1_high_max;
    unsigned long bit_low_min;
    unsigned long bit_low_max;
    unsigned char total_bits;
} DecodeConfig;

// 解码结果结构体
typedef struct {
    unsigned long address;
    unsigned char data;
    unsigned char repeat_count;
    unsigned char valid;
} DecodeResult;

// 全局变量
DecodeConfig decode_config;
DecodeResult decode_result;
static unsigned char decode_state = 0;
static unsigned char bit_position = 0;
static unsigned long last_sync_time = 0;

// 初始化解码配置
void Init_Decode_Config(CodecType codec) {
    switch(codec) {
        case CODEC_PT2262:
            decode_config.codec_type = CODEC_PT2262;
            decode_config.sync_low_min = 3500;
            decode_config.sync_low_max = 4500;
            decode_config.sync_high_min = 120000;
            decode_config.sync_high_max = 130000;
            decode_config.bit0_high_min = 400;
            decode_config.bit0_high_max = 600;
            decode_config.bit1_high_min = 1400;
            decode_config.bit1_high_max = 1600;
            decode_config.bit_low_min = 400;
            decode_config.bit_low_max = 600;
            decode_config.total_bits = 24;
            break;
            
        case CODEC_EV1527:
            decode_config.codec_type = CODEC_EV1527;
            decode_config.sync_low_min = 300;
            decode_config.sync_low_max = 500;
            decode_config.sync_high_min = 8000;
            decode_config.sync_high_max = 12000;
            decode_config.bit0_high_min = 300;
            decode_config.bit0_high_max = 500;
            decode_config.bit1_high_min = 900;
            decode_config.bit1_high_max = 1100;
            decode_config.bit_low_min = 300;
            decode_config.bit_low_max = 500;
            decode_config.total_bits = 24;
            break;
            
        default:
            break;
    }
}

// 解码单帧数据
unsigned char Decode_Single_Frame(unsigned long pulse_width) {
    static unsigned long frame_start_time = 0;
    static unsigned char frame_bits = 0;
    static unsigned long frame_address = 0;
    static unsigned char frame_data = 0;
    
    unsigned char bit_value;
    unsigned char result = 0;
    
    if(decode_state == 0) {
        // 等待同步码
        if(pulse_width >= decode_config.sync_low_min && 
           pulse_width <= decode_config.sync_low_max) {
            frame_start_time = Get_Time_Us();
            decode_state = 1;
            frame_bits = 0;
            frame_address = 0;
            frame_data = 0;
        }
    }
    else if(decode_state == 1) {
        // 检查同步码高电平
        if(pulse_width >= decode_config.sync_high_min && 
           pulse_width <= decode_config.sync_high_max) {
            decode_state = 2;
        } else {
            decode_state = 0;    // 同步失败
        }
    }
    else if(decode_state == 2) {
        // 解码数据位
        if(pulse_width >= decode_config.bit0_high_min && 
           pulse_width <= decode_config.bit0_high_max) {
            bit_value = 0;
        }
        else if(pulse_width >= decode_config.bit1_high_min && 
                pulse_width <= decode_config.bit1_high_max) {
            bit_value = 1;
        }
        else {
            decode_state = 0;    // 数据位解码失败
            return 0;
        }
        
        // 存储数据位
        if(frame_bits < 20) {    // 地址位
            frame_address >>= 1;
            if(bit_value) frame_address |= 0x80000;
        }
        else {                   // 数据位
            frame_data >>= 1;
            if(bit_value) frame_data |= 0x08;
        }
        
        frame_bits++;
        
        // 检查是否解码完成
        if(frame_bits >= decode_config.total_bits) {
            decode_result.address = frame_address;
            decode_result.data = frame_data & 0x0F;
            decode_result.repeat_count++;
            decode_result.valid = 1;
            result = 1;
            decode_state = 0;
        }
    }
    
    return result;
}

2.3 学习模式程序

/**
 * @file learning_mode.c
 * @brief 遥控器学习模式程序
 */

#include "reg52.h"

#define LEARN_BUTTON P1^2    // 学习按钮
#define LEARN_LED P1^3       // 学习指示灯

typedef struct {
    unsigned long learned_address[10];    // 学习的地址
    unsigned char learned_data[10];        // 学习的数据
    unsigned char learn_count;             // 学习数量
    unsigned char learning_mode;           // 学习模式标志
} LearningData;

LearningData learning_data;

// 进入学习模式
void Enter_Learning_Mode(void) {
    unsigned char i;
    
    if(LEARN_BUTTON == 0) {
        Delay_Ms(50);
        if(LEARN_BUTTON == 0) {
            learning_data.learning_mode = 1;
            LEARN_LED = 0;    // 点亮学习指示灯
            
            // 等待遥控器按键
            for(i = 0; i < 10; i++) {
                // 等待解码完成
                while(!decode_result.valid);
                
                // 存储学习结果
                learning_data.learned_address[learning_data.learn_count] = decode_result.address;
                learning_data.learned_data[learning_data.learn_count] = decode_result.data;
                learning_data.learn_count++;
                
                // 闪烁指示灯表示学习成功
                LEARN_LED = 1;
                Delay_Ms(100);
                LEARN_LED = 0;
                Delay_Ms(100);
                
                // 清除解码结果
                decode_result.valid = 0;
                
                // 检查是否学习完成
                if(learning_data.learn_count >= 10) {
                    break;
                }
            }
            
            learning_data.learning_mode = 0;
            LEARN_LED = 1;    // 熄灭学习指示灯
        }
    }
}

// 匹配学习结果
unsigned char Match_Learned_Code(unsigned long address, unsigned char data) {
    unsigned char i;
    
    for(i = 0; i < learning_data.learn_count; i++) {
        if(learning_data.learned_address[i] == address && 
           learning_data.learned_data[i] == data) {
            return 1;    // 匹配成功
        }
    }
    
    return 0;    // 未匹配
}

三、应用示例

3.1 四路遥控开关

/**
 * @file four_channel_switch.c
 * @brief 四路遥控开关应用
 */

#include "rf_decoder.c"

// 继电器控制引脚
sbit RELAY1 = P1^0;
sbit RELAY2 = P1^1;
sbit RELAY3 = P1^2;
sbit RELAY4 = P1^3;

// 状态指示
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
sbit LED4 = P2^3;

void main(void) {
    unsigned char relay_state[4] = {0, 0, 0, 0};    // 继电器状态
    
    // 初始化
    Timer0_Init();
    External_Int0_Init();
    
    // 关闭所有继电器
    RELAY1 = 0; RELAY2 = 0; RELAY3 = 0; RELAY4 = 0;
    LED1 = 1; LED2 = 1; LED3 = 1; LED4 = 1;
    
    while(1) {
        if(decode_valid && Verify_Decode_Result()) {
            // 根据数据码控制继电器
            switch(data_code & 0x0F) {
                case 0x01:    // A键 - 继电器1
                    relay_state[0] = !relay_state[0];
                    RELAY1 = relay_state[0];
                    LED1 = !relay_state[0];
                    break;
                    
                case 0x02:    // B键 - 继电器2
                    relay_state[1] = !relay_state[1];
                    RELAY2 = relay_state[1];
                    LED2 = !relay_state[1];
                    break;
                    
                case 0x04:    // C键 - 继电器3
                    relay_state[2] = !relay_state[2];
                    RELAY3 = relay_state[2];
                    LED3 = !relay_state[2];
                    break;
                    
                case 0x08:    // D键 - 继电器4
                    relay_state[3] = !relay_state[3];
                    RELAY4 = relay_state[3];
                    LED4 = !relay_state[3];
                    break;
                    
                case 0x0F:    // *键 - 全部关闭
                    relay_state[0] = 0; relay_state[1] = 0;
                    relay_state[2] = 0; relay_state[3] = 0;
                    RELAY1 = 0; RELAY2 = 0; RELAY3 = 0; RELAY4 = 0;
                    LED1 = 1; LED2 = 1; LED3 = 1; LED4 = 1;
                    break;
                    
                case 0x00:    // #键 - 全部打开
                    relay_state[0] = 1; relay_state[1] = 1;
                    relay_state[2] = 1; relay_state[3] = 1;
                    RELAY1 = 1; RELAY2 = 1; RELAY3 = 1; RELAY4 = 1;
                    LED1 = 0; LED2 = 0; LED3 = 0; LED4 = 0;
                    break;
            }
            
            // 重置解码状态
            decode_complete = 0;
            decode_valid = 0;
            bit_count = 0;
        }
        
        Delay_Ms(10);
    }
}

参考代码 STC解码无线遥控器程序 www.youwenfan.com/contentcnv/60425.html

四、调试与优化建议

4.1 调试方法

  1. 串口输出:添加串口输出解码过程中的脉冲宽度和状态
  2. LED指示:用LED闪烁模式表示不同的解码状态
  3. 示波器观察:用示波器观察无线信号的波形

4.2 抗干扰优化

// 添加连续解码验证
unsigned char continuous_decode_check = 0;
unsigned char last_address = 0;
unsigned char last_data = 0;

if(decode_valid) {
    if(address_high == last_address && data_code == last_data) {
        continuous_decode_check++;
        if(continuous_decode_check >= 3) {    // 连续3次相同才确认
            Execute_Decode_Result();
            continuous_decode_check = 0;
        }
    } else {
        continuous_decode_check = 0;
    }
    
    last_address = address_high;
    last_data = data_code;
}

4.3 常见问题解决

问题 原因 解决方案
无法解码 脉冲宽度参数不匹配 用示波器测量实际脉冲宽度,调整参数
解码不稳定 信号干扰 添加连续解码验证,增加滤波电容
误触发 环境噪声 添加地址过滤,只响应特定地址
距离近 天线问题 增加天线长度,优化PCB布局
posted @ 2026-05-19 17:04  小前端攻城狮  阅读(7)  评论(0)    收藏  举报