大数跨境
0
0

无线遥控模块51单片机收发例程

无线遥控模块51单片机收发例程 蜂鸟无线
2025-07-18
2
导读:介绍常用433/315MHz无线遥控模块在51单片机上编码和解码方法,思路清晰、代码简洁、注释详细,帮助初次开发遥控产品的电子工程师


本文介绍了常用433/315MHz无线遥控模块在51单片机上编码和解码方法,思路清晰、代码简洁、注释详细,帮助初次研发射频遥控产品的工程师和广大电子爱好者。

(原创、版权所有,转载请注明出处 )

 

无线发射部分

推荐“远系列发射模块”+MCU              

2.1元,点此买样品包顺丰 

 


核心功能:

通过 51 单片机(如 STC89C52)检测按键按下,发送基于 FB1527 编码的 433MHz 无线信号。

引脚作用:

P3.0:连接 433MHz 发射模块,输出编码信号

P3.2:按键输入(上拉模式,低电平表示按下)

P3.7:LED 状态指示(发送时翻转,未按下时熄灭)

编码逻辑:

帧结构为 “同步码(128us)+20 位地址码 + 4 位数据码”,地址固定为 0x66666,键值固定为 0x01。

可靠性设计:

按键按下时发送 3 次编码,间隔 10ms;10ms 消抖避免误触发。

 

发射流程图

  

以下是发射程序,附带详细注释:

/*--------------------------------------------
主控:51单片机(如STC89C52)
功能:检测按键按下时发送FB1527编码的433MHz无线信号
引脚定义:
P3.7        - LED状态指示引脚
P3.0       - 数据输出引脚(连接433MHz发射模块)
P3.2 (INT0)  - 按键输入引脚(KEY1)
检测到KEY1按下时,发送地址0x66666、键值0x01的FB1527编码
@date    2025年7月18日
@version  1.0
@author  陈宝明_创意宝
---------------------------------------------*/
#include
  
// 引脚定义
sbit LED_PIN     = P3^7;    // LED状态指示引脚
sbit DATAOUT_PIN = P3^0;    // 433MHz模块数据输出引脚
sbit KEY1_PIN    = P3^2;    // 按键输入引脚(上拉输入)
// 宏定义:LED和数据输出操作#define LED_OFF      (LED_PIN = 1)    
// LED熄灭(高电平)#define LED_ON       (LED_PIN = 0)    
// LED点亮(低电平)#define LED_CPL      (LED_PIN = !LED_PIN)  
// LED状态翻转#define DATAOUT_LOW  (DATAOUT_PIN = 0)    
// 数据输出低电平#define DATAOUT_HIGH (DATAOUT_PIN = 1)    
// 数据输出高电平
/**
 * @brief  微秒级延时函数(近似实现)
 * @param  us: 延时微秒数(最大支持65535us)
 * @note   基于11.0592MHz晶振校准,通过空指令实现短延时
 */voiddelay_us(uint16_t us){
    uint16_t j;
    // 根据晶振频率计算循环系数(11.0592MHz下约1us对应11.0592个指令周期)
    us = us *12;  // 调整系数使延时更接近实际值
    for(=0; j < us; j++){
        // 执行空指令(nop),每个nop占用1个机器周期
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
    }}
/**
 * @brief  发送FB1527编码的同步码
 * @note   同步码格式:高电平4us + 低电平124us(总时长128us)
 */voidcoding_syn_1527(void){
    DATAOUT_HIGH;  // 数据输出高电平
    delay_us(4);   // 持续4us
    DATAOUT_LOW;   // 数据输出低电平
    delay_us(124);// 持续124us}
/**
 * @brief  发送FB1527编码的"0"码
 * @note   0码格式:高电平4us + 低电平12us(总时长16us)
 */voidcoding_L_1527(void){
    DATAOUT_HIGH;  // 数据输出高电平
    delay_us(4);   // 持续4us
    DATAOUT_LOW;   // 数据输出低电平
    delay_us(12);  // 持续12us}
/**
 * @brief  发送FB1527编码的"1"码
 * @note   1码格式:高电平12us + 低电平4us(总时长16us)
 */voidcoding_H_1527(void){
    DATAOUT_HIGH;  // 数据输出高电平
    delay_us(12);  // 持续12us
    DATAOUT_LOW;   // 数据输出低电平
    delay_us(4);   // 持续4us}
/**
 * @brief  发送完整的FB1527编码帧
 * @param  Addr_1527: 20位地址码(范围0~0xFFFFF)
 * @param  Data: 4位数据码(范围0~15)
 * @note   编码帧结构:同步码 + 20位地址码 + 4位数据码
 */voidcoding_1527(uint32_t Addr_1527, uint8_t Data){
    uint8_t i, k;
    uint32_t j;
    
    // 校验地址码和数据码合法性(地址码≤20位,数据码≤4位)
    if((Addr_1527 >0xFFFFF)||(Data >15)){
        return;  // 非法值则退出
    }
    
    // 发送同步码(帧起始标志)
    coding_syn_1527();
    
    // 发送20位地址码(从高位到低位依次发送)
    for(=0; i <20; i++){
        j =(0x80000& Addr_1527);  // 取当前最高位
        Addr_1527 =(Addr_1527 <<1);  // 地址码左移1位,准备下一位
        if(!=0){  // 最高位为1,发送1码
            coding_H_1527();
        }else{  // 最高位为0,发送0码
            coding_L_1527();
        }
    }
    
    // 发送4位数据码(从高位到低位依次发送)
    for(=0; i <4; i++){  
        k =(0x08& Data);  // 取当前最高位
        Data =(Data <<1);  // 数据码左移1位,准备下一位
        if(!=0){  // 最高位为1,发送1码
            coding_H_1527();
        }else{  // 最高位为0,发送0码
            coding_L_1527();
        }
    }}
/**
 * @brief  毫秒级延时函数(用于主循环中按键消抖)
 * @param  ms: 延时时长(毫秒)
 */voiddelay_ms(uint16_t ms){
    uint16_t i, j;
    for(=0; i < ms; i++){
        for(=0; j <112; j++);  // 11.0592MHz下约1ms
    }}
/**
 * @brief  主函数:初始化硬件并循环检测按键状态
 */voidmain(void){
    // 初始化引脚状态
    LED_OFF;           // LED初始熄灭
    DATAOUT_LOW;       // 数据输出初始低电平
    P3 |=0x04;        // 按键引脚使能内部上拉(P3.2=1,未按下时为高电平)
    
    while(1){
        // 检测按键是否按下(低电平有效,上拉输入模式下按下为0)
        if(KEY1_PIN ==0){
            delay_ms(10);  // 按键消抖(10ms延时)
            if(KEY1_PIN ==0){  // 确认按键按下
                uint8_t i =3;    // 发送次数计数器(发送3次提高可靠性)
                while(i--){
                    coding_1527(0x66666,0x01);  // 发送地址码0x66666、数据码0x01
                    LED_CPL;  // 翻转LED状态(指示发送中)
                    delay_ms(10);  // 间隔10ms,避免发送过于密集
                }
            }
        }else{
            LED_OFF;  // 按键未按下时,LED保持熄灭
        }
    }}

 

  

说明:

1、延时函数:根据 11.0592MHz 晶振校准delay_us(微秒级)和delay_ms(毫秒级)函数。

2、按键检测逻辑:采用上拉输入模式(未按下时为高电平),按下时触发 3 次编码发送(提高接收成功率),LED 同步翻转指示。

 3、编码是否成功可用“开发助手”接收编码值

99/台 点此购买包顺丰


———————————————————


无线接收部分

 

推荐“远系列接收模块”+MCU,   或LR690系列接收芯片+MCU

2.23元,此买样包顺丰

 

 

核心功能:

51 单片机通过 433MHz 接收模块接收并解码 FB1527 编码信号,检测到特定编码(0x666661)时翻转 LED 状态。

引脚作用:

P3.2:接收 433MHz 模块信号(输入)

P3.7:LED 状态指示(解码匹配时翻转)

解码逻辑:

识别同步码(5600~16000us 低电平),接收 24 位数据(20 位地址 + 4 位数据),区分 0(800~2400us 低电平)/1(80~800us 低电平)。

实现方式:

定时器 0 每 80us 中断一次,实时检测电平跳变并累计低电平时间,触发解码流程。

  

接收流程图


 

以下是无线接收解码程序

/*--------------------------------------------

主控:51单片机(如STC89C52)

功能:接收并解码433MHz RF无线信号

引脚定义:

P3.2 (INT0)  - 信号输入引脚

P3.7         - LED状态指示引脚

检测到特定RF编码时,LED状态翻转

FB1527编码解码逻辑

@date    2025年7月18日

@version  1.0

@author  陈宝明_创意宝

---------------------------------------------*/

#include

// 引脚定义

sbit LED_PIN    = P3^7;    // LED状态指示引脚

sbit SIGNAL_PIN = P3^2;    // 无线信号输入引脚(接INT0中断)

// 时间周期定义(单位:us),用于转换实际时间与计数#define TIME_CYCLE       80      // 基础时间单位:80us

// 引导码(同步码)时间范围(单位:TIME_CYCLE)

// 实际时间 = 计数 × TIME_CYCLE,对应原5600us~16000us#define MIN_START_CODE   (5600  / TIME_CYCLE)   

// 70#define MAX_START_CODE   (16000 / TIME_CYCLE)   

// 200

// 数据位"0"时间范围(单位:TIME_CYCLE)

// 对应原800us~2400us#define MIN_NUM0_DURATION (800  / TIME_CYCLE)    

// 10#define MAX_NUM0_DURATION (2400 / TIME_CYCLE)    

// 30

// 数据位"1"时间范围(单位:TIME_CYCLE)

// 对应原80us~800us#define MIN_NUM1_DURATION (80  / TIME_CYCLE)     

// 1#define MAX_NUM1_DURATION (800  / TIME_CYCLE)    

// 10

// 全局变量定义(volatile确保中断中可正确访问)volatile unsigned char  cntint        = 0;       // 接收数据位计数(0~24)volatile unsigned char  start_flag    = 0;       

// 引导码检测标志(1=已检测)volatile unsigned char  Jump_flag     = 0;       

// 电平跳变标志(0→1=低→高跳变)volatile unsigned int   Low           = 0;       

// 低电平持续时间计数(单位:TIME_CYCLE)volatile unsigned long  RF_data       = 0;       // 接收的完整24位数据volatile unsigned long  Target_address=0;        

// 解析出的地址码(高20位)volatile unsigned char  Target_Button = 0;       

// 解析出的按键码(低4位)

/**

 * @brief  定时器0初始化函数

 * @note   配置定时器0为16位自动重装载模式,约80us触发一次中断

 *         用于定时器中断,实现定时检测电平

 */void Timer0_Init(void) {

    TMOD &= 0xF0;  // 清除原定时器0配置

    TMOD |= 0x01;  // 定时器0工作在方式1(16位定时)

    TH0 = 0xFF;    // 初值高8位(计算:80us@11.0592MHz)

    TL0 = 0x83;    // 初值低8位(11.0592MHz晶振,80us对应的计数)

    ET0 = 1;       // 使能定时器0中断

    EA  = 1;       // 使能总中断

    TR0 = 1;       // 启动定时器0}

/**

 * @brief  解码函数:根据低电平持续时间解析引导码和数据位

 * @note   当检测到引导码后,连续接收24位数据,区分0/1逻辑

 */void soft_decode(void) {

    if (start_flag == 0) {  // 未检测到引导码,判断是否为同步码

        // 低电平时间在引导码范围内(5600us~16000us)

        if ((Low > MIN_START_CODE) && (Low < MAX_START_CODE)) {

            start_flag = 1;    // 标记引导码检测完成

            cntint = 0;        // 重置数据位计数

            RF_data = 0;       // 清空接收数据缓存

        } else {

            LED_PIN = 0;       // 未检测到引导码,LED熄灭

        }

    } 

    // 已检测引导码,且数据位未满24位

    else if ((start_flag == 1) && (cntint < 24)) {

        // 低电平时间在数据0范围内(800us~2400us),判定为0

        if ((Low > MIN_NUM0_DURATION) && (Low < MAX_NUM0_DURATION)) {

            RF_data <<= 1;     // 左移补0

            cntint++;          // 数据位计数+1

        }

        // 低电平时间在数据1范围内(80us~800us),判定为1

        else if ((Low > MIN_NUM1_DURATION) && (Low < MAX_NUM1_DURATION)) {

            RF_data <<= 1;     // 左移后最低位补1

            RF_data |= 1;

            cntint++;          // 数据位计数+1

        }

        // 时间超出范围,判定为无效数据,重置状态

        else {

            start_flag = 0;

            cntint = 0;

        }

    }

    // 已接收24位完整数据,解析并处理

    if (cntint == 24) {

        cntint = 0;        // 重置计数

        start_flag = 0;    // 清除引导码标志

        // 解析地址码(高20位)和按键码(低4位)

        Target_address = (RF_data >> 4) & 0xFFFFF;  // 20位地址码

        Target_Button  = RF_data & 0x0F;            // 4位按键码

 

        // 检测到特定编码0x666661时,翻转LED状态

        if (RF_data == 0x666661) {

            LED_PIN = !LED_PIN;

        }

 

        // 此处可添加串口输出代码(需自行实现51串口驱动)

        // 示例:UART_SendHex(RF_data);  // 输出接收的十六进制数据

    }}

/**

 * @brief  电平检测函数:由定时器中断周期性调用(约80us一次)

 * @note   检测信号引脚电平变化,累计低电平时间,触发跳变时解码

 */void soft_count(void) {

    if (SIGNAL_PIN == 0) {  // 检测到低电平

        Low++;              // 低电平计数+1(每80us加1)

        if (Jump_flag) {

            Jump_flag = 0;  // 高→低跳变,重置跳变标志

        }

    } else {  // 检测到高电平

        if (!Jump_flag) {   // 低→高跳变(电平发生跳变)

            Jump_flag = 1;  // 标记跳变状态

            soft_decode();  // 触发解码(根据低电平时间解析数据)

            Low = 0;        // 重置低电平计数

        }

    }}

/**

 * @brief  定时器0中断服务函数:约80us触发一次

 * @note   周期性调用电平检测函数,实现实时信号监测

 */void Timer0_ISR(void) interrupt 1 {

    // 重装载定时器初值(维持80us中断周期)

    TH0 = 0xFF;

    TL0 = 0x83;

    soft_count();  // 调用电平检测函数}

/**

 * @brief  主函数:初始化硬件并进入循环等待

 */void main(void) {

    // 初始化IO口

    LED_PIN = 0;          // LED初始熄灭

    P3 &= 0xFB;           // 配置SIGNAL_PIN为输入(P3.2默认高阻输入)

    

    Timer0_Init();        // 初始化定时器0(80us中断)

 

    while (1) {

        // 主循环空闲,核心逻辑由定时器中断处理

        // 可添加其他业务逻辑(如看门狗喂狗等)

    }}

 

 

代码说明:

1、晶振默认按 11.0592MHz 计算,若使用其他频率,需重新计算定时器初值

2、中断逻辑:定时器 0 每 80us 触发一次中断,实时监测信号电平

3、低电平时间累计后,在电平跳变时触发解码,确保数据同步性

4、推荐“灵-R1系列接收模块”,带解码、可对码,输出开关量/串口键值

3.98元,点此买样包顺丰


该代码可直接用于 51 单片机开发环境(如 Keil C51)

 

【声明】内容源于网络
0
0
蜂鸟无线
做遥控数传,用蜂鸟更远!
内容 64
粉丝 0
蜂鸟无线 做遥控数传,用蜂鸟更远!
总阅读140
粉丝0
内容64