发作品签到
专业版

stm32射频拷贝遥控器

工程标签

666
0
0
13

简介

这个项目灵感来源于我的母亲把自家卷帘门钥匙弄丢了,我就想做一个可以拷贝键码,也可以没钥匙,穷举键码的遥控。

简介:这个项目灵感来源于我的母亲把自家卷帘门钥匙弄丢了,我就想做一个可以拷贝键码,也可以没钥匙,穷举键码的遥控。
智能便携电子设备设计大赛

开源协议

GPL 3.0

(未经作者授权,禁止转载)
创建时间:2025-02-27 06:57:17更新时间:2025-03-26 09:21:32

描述

视频链接:

B站视频--功能演示及介绍
https://www.bilibili.com/video/BV15s9FYNEeq/
手残党https://m.tb.cn/h.62wA6FB?tk=7Nj3eunk3yE CZ005 「我在闲鱼发布了【基于stm32的射频拷贝遥控器】」
点击链接直接打开

项目简介

本项目是基于stm32f103的射频拷贝遥控器,拷贝433频率1527协议遥控器的键码,以及穷举433频率1527协议下所有键码

项目功能

本项目是基于stm32f103的射频拷贝遥控器,设置有11个按键,分别为K1~K11。K1和K2控制遥控模式为收模式还是发模式。K3~K8、K11用于存储拷贝的键码,K9为穷举按键,K10为穷举停止按键。

项目参数

  • 本设计采用 超再生接收模块 433频率 射频接收
  • 本设计采用 远-T2L 433频率 射频发射
  • 本设计采用 MT3608 升压芯片给单片机供电
  • 本设计采用 TP4056 充电芯片给锂电池充电
  • 本设计采用 oled 0.96显示屏,显示拷贝的键码和发射的键码和模式显示;
  • 本设计采用 ADC电压检测;

原理解析(硬件说明)

本项目由以下部分组成,充电部分、升压部分、电压检测部分、主控部分、射频发射接收部分、按键部分、显示部分,本项目主要是通过32进行编码,远-T2L发送编码。通过433MHZ超再生接收模块接收键码,32解码。进行拷贝和发送。

image.png
充电电路:
采用TP4056 1A锂电池充电板模块

image.png
5V升压电路
+5为升压输出端,VCC为输入电压端,C3、C2均为22uF陶瓷电容,电感选用10uH,VD1为肖特基二极管SS34。R1u4为采样电阻

image.png
射频收发电路
采用远-T2L为发射端、433MHZ超再生接收模块为接收端、SMA-KE 直头偏脚型的天线座

image.png
主控

image.png

image.png
显示模块
0.96 OLED屏

image.png
电压检测
R14&R15进行分压,C2减小ADC的采样值振荡,然后由32进行ADC读取

image.png
按键检测电路
R20为LED7的限流电阻,K9连接单片机,配置为上拉输入防止LED随便亮。

EV1527协议介绍

image.png
由上图我们知道1527发射数据由一位同步码、20位地址、4位数据。
同步码 : 4 LCK(高) + 124 LCK(低)
DATA(1) :12 LCK(高) + 4 LCK(低)
DATA(0) : 4 LCK(高) + 12 LCK(低)
那么问题来了 1 LCK 是多少时间?

image.png
根据数据手册,加上我的实际测量电阻都是330K

image.png

根据下图的震荡表,我们知道3V,16LCK是1.69ms
那么 1 LCK = 1.69 / 16 = 106ns
同步码 : 424 ns (高) + 13144 ns (低)
DATA(1) : 1272 ns(高) + 424 ns(低)
DATA(0) : 424 ns(高) + 1272 ns(低)
image.png

1527协议发射端代码

/**发射端*/
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
//
void EV1527_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)BitValue);
}

void EV1527_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = 3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_RESET );
}

//发送同步码
//同步码
void Send_tongbu()
{
		EV1527_SDA(1);
		Delay_us(424);
		EV1527_SDA(0);
		Delay_us(13144);

}

//发送一个字节
void EV1527_SendByte(uint8_t Byte)
{
	uint8_t i;
	//同步码
	//发送一个字节
	for (i = 0; i < 8; i ++)
	{ 
		//发送1
		if(Byte & (0x80 >> i) )
		{
			EV1527_SDA(1);
			Delay_us(1272);
			EV1527_SDA(0);
			Delay_us(424);
		}
		//发送0
		else 
		{
			EV1527_SDA(1);
			Delay_us(424);
			EV1527_SDA(0);
			Delay_us(1272);
		}
	}
		
	
}





1527协议接收端代码

/**接收端代码转自https://blog.csdn.net/Vinccent_/article/details/78955376?fromshare=blogdetail&sharetype=blogdetail&sharerId=78955376&sharerefer=PC&sharesource=xdjsdd&sharefrom=from_link**/


/*Timer.c*/
#include "stm32f10x.h"                  // Device header
#include "timer.h"

uint8_t rf_data[4];

void EV1527_GPIO_Init() //EV1527 IO口初始化
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // PB9 输入端
    GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_1; 
    GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
}

//中断函数使用定时器4

void TIM4_NVIC_Init()   //中断分组初始化
{
NVIC_InitTypeDef NVIC_InitStructure;    
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
//TIM4中断
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 
//先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  
//从优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
//IRQ通道被使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
NVIC_Init(&NVIC_InitStructure); 
}

void TIM4_Mode_Init()
{    
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    //使能TIM4时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    
    //初始化定时器6
    //设定计数器自动重装值     
    TIM_TimeBaseStructure.TIM_Period = 100; 
    //时钟预分频系数 驱动计数器的时钟 CK_CNT=CK_INT/(71+1) = 1M
    //计数器计数1次时间等于1/CK_CNT = 1us
    TIM_TimeBaseStructure.TIM_Prescaler =71; 
    //设置时钟分割:TDTS = Tck_tim                                                                                   
    TIM_TimeBaseStructure.TIM_ClockDivision =        
    TIM_CKD_DIV1; 
    //TIM向上计数模式
    TIM_TimeBaseStructure.TIM_CounterMode = 
    TIM_CounterMode_Up; 
    //根据指定的参数初始化TIMx的时间基数单位
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
    //允许更新中断 
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
    TIM_ClearFlag(TIM3,TIM_FLAG_Update);
    //使能定时器6
    TIM_Cmd(TIM3,DISABLE );  
}

uint8_t RF;
uint8_t decode_ok;            //解码成功
uint8_t  hh_w,ll_w;           //高,低电平宽度
uint8_t  ma_x;                //接收到第几位编码了
uint8_t  bma1,bma2,bma3,bma4; //用于接收过程存放遥控编码,编码比较两次,这是第一次
uint8_t  mma1,mma2,mma3,mma4;
uint8_t mmb1,mmb2,mmb3,mmb4; // 用于接收过程存放遥控编码,第二次
//extern uint8_t mmb1,mmb2,mmb3,mmb4;

uint8_t rf_ok1,rf_ok2,rf_ok;         //解码过程中的临时接收成功标志,接收到一个完整的遥控命令后置1,通知解码程序可以解码了
uint8_t old_rc5;             //保存上一次查询到的电平状态
uint8_t tb_ok;               //接收到同步的马时置1   
uint8_t D0,D1,D2,D3 ;
uint16_t s ,s1; 
uint8_t bt_auto;     //自动设置遥控接收波特率标志


void TIM3_IRQHandler()
{
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 

        //接收数据的电平 PB1
        RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1); 
        if (!RF) 
        { 
            ll_w++;   // 检测到低电平 低电平时间加1,记录本 
                      // 次电平状态old_rc5
            old_rc5=0; 
        }               
         else         // 检测到高电平
         { 
            hh_w++;
            if (!old_rc5)  // 检测到从低到高的跳变,已检测
                           // 到一个完整(高-低)电平周期
            {   //判同步码    2/5 100/130
                if (((hh_w>=2)&&(hh_w<=5))&&
                ((ll_w>=100)&&(ll_w<=130))) 
                { 
                    tb_ok = 1 ;
                    ma_x = 0;
                    bma1=0; bma2=0; bma3=0; bma4=0;    
                }
                else if ((tb_ok)&&((ll_w>=8)&&
                                (ll_w<=13))) //8/13
                {   
                    ma_x++; //已经接收到同步码,判0
                    if(ma_x>23)
                    {
                        if(!rf_ok1) //rf_ok1临时接收成功
                        {   //将接收到的编码复制到解码寄存器中 
                            mma1=bma1;
                            mma2=bma2;
                            mma3=bma3;
                            mma4=bma4; 
                            // 通知解码子程序可以解码了                                                        
                            rf_ok1=1;                    
                            tb_ok=0;
                            s=1000;                             
                            }
                            else
                            {//将接收到的编码复制到解码寄存器中  
                                mmb1=bma1;
                                mmb2=bma2;
                                mmb3=bma3;
                                mmb4=bma4;  
                                // 通知解码子程序可以解码了                                             
                                rf_ok2=1;                     
                                tb_ok=0;                                                                        
                            }
                        }
                     }  
                     else if ((tb_ok)&&((ll_w>=2)&&
                                  (ll_w<=7)))   // 2/7
                     { 
                         switch (ma_x)
                         { 
                         case 0 : { bma1=bma1 | 0x80; 
                             break; }   //遥控编码第1位
                         case 1 : { bma1=bma1 | 0x40;  
                             break; }
                         case 2 : { bma1=bma1 | 0x20; 
                             break; }
                         case 3 : { bma1=bma1 | 0x10; 
                             break; }
                         case 4 : { bma1=bma1 | 0x08; 
                             break; }
                         case 5 : { bma1=bma1 | 0x04; 
                             break; }
                         case 6 : { bma1=bma1 | 0x02; 
                             break; }
                         case 7 : { bma1=bma1 | 0x01; 
                             break; }
                         case 8 : { bma2=bma2 | 0x80; 
                             break; }
                         case 9 : { bma2=bma2 | 0x40; 
                             break; }
                         case 10: { bma2=bma2 | 0x20; 
                             break; }
                         case 11: { bma2=bma2 | 0x10; 
                             break; }
                         case 12: { bma2=bma2 | 0x08; 
                             break; }
                         case 13: { bma2=bma2 | 0x04; 
                             break; }
                         case 14: { bma2=bma2 | 0x02; 
                             break; }
                         case 15: { bma2=bma2 | 0x01; 
                             break; }
                         case 16: { bma3=bma3 | 0x80; 
                             break; }
                         case 17: { bma3=bma3 | 0x40; 
                             break; }
                         case 18: { bma3=bma3 | 0x20; 
                             break; }
                         case 19: { bma3=bma3 | 0x10; 
                             break; }
                         case 20: { bma3=bma3 | 0x08; 
                             break; }// 按键状态第1位
                         case 21: { bma3=bma3 | 0x04; 
                             break; }
                         case 22: { bma3=bma3 | 0x02; 
                            break; }
                         case 23: { bma3=bma3 | 0x01;              
                                  if(!rf_ok1)
                                  {
                                      mma1=bma1;
                                      mma2=bma2;
                                      mma3=bma3;
                                   // mma4=bma4;                                           // 将接收到的编码复制到解码寄存器中                             
                                     rf_ok1=1;         // 通知解码子程序可以解码了
                                     tb_ok=0;
//                                   bt_auto=0;
                                     s=1000;
                                     break;                                 
                                  }
                                  else
                                  {
                                      mmb1=bma1;
                                      mmb2=bma2;
                                      mmb3=bma3;
                                    //mmb4=bma4;               // 将再次接收到的编码复制到解码寄存器中,                             
                                    rf_ok2=1;                                      // 通知解码子程序可以解码了
                                    tb_ok=0;
                                    break;                                                                          
                                 }                                    
                         }
                    } 
                    ma_x++; 
                 }
                 else
                 {ma_x=0; tb_ok=0;bt_auto=0;bma1=0;bma2=0; bma3=0; hh_w=1;ll_w=0;}                                      //接收到不符合的高-低电平序列
                 ll_w=0;hh_w=1; 
             }          
             old_rc5=1;      // 记录本次电平状态
       }
       if(rf_ok1)  //规定时间内接受到2帧相同的编码数据才有效
        {
            s--;
            if(!s) rf_ok1=0;
            if(rf_ok2) 
            {
            if((mma1==mmb1)&&(mma2==mmb2)&&(mma3==mmb3))
            {
                rf_ok=1;
                rf_ok1=0;
                rf_ok2=0;                    
            }
            else
            {
                rf_ok=0;
                rf_ok1=0;
                rf_ok2=0;

             }          
        }                   
    }

    if((rf_ok))      //判断是否接收成功
    {   
        TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
        rf_ok=0; 
        rf_data[0]=mma1;
        rf_data[1]=mma2;
        rf_data[2]=mma3;

        decode_ok=1;

        TIM_ITConfig(TIM3  , TIM_IT_Update, ENABLE);
        }
    }
}

1527协议发射穷举代码

void ev1527_while()
{
if(KeyNum==5)//判断按键标志位,按键是否按下
{	
   TIM_Cmd(TIM3,DISABLE ); //按键按下接收模式停止
	uint32_t i=0;
	while(i<0xffffff)//开始循环穷举
	{  
        i++;
	  for(uint8_t c=0;c<9;c++)  //循环多次发送键码
	 {
       Send_tongbu();//发送同步码
	   EV1527_SendByte(i>>16);//发送键码最高8位
       EV1527_SendByte(i>>8); //发送键码中8位
	   EV1527_SendByte(i);    //发送键码最低8位
        }
         if(K10==0)//判断结束按键是否按下
			{
				KeyNum=4;//置标志为4进入发射模式
				OLED_ShowChinese(0, 33, "穷举结束");	
		        OLED_Update();
			    return;//结束循环
			
			}
	}
	
}

实物图

IMG_20250302_101209.jpg

IMG_20250302_101215.jpg

IMG_20250317_183435.jpg
IMG_20250302_101224.jpg

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
固件.zip
27
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航