基于STM32的红外遥控器设计,实现红外遥控器的复制与红外信号的发送

本设计是我毕业设计的一个组成部分,我花了近三个星期的时间才完成这个功能,为什么我要分享出来,因为我想帮助和我曾经遇到一样问题的同学,希望对他们有所帮助,在下面的阐述中我只给出核心代码,不会说明各个模块具体怎么实现的。

1.目的:复制遥控器红外波形然后发射出去控制红外家电设备。
2.怎么复制:

A.我是通过STM32的定时器捕获来获取遥控器发射给红外接收头解调后的电平,说的详细点,就是红外遥控器发射的是一组经过调制的红外信号,后面我们模拟的时候也是需要调制的,调制需要载波:38k左右都可以,红外接收头接收到遥控器的红外信号后内部会自动解调,如图1.0是接收到的信号和红外解调后的信号。

基于STM32的红外遥控器设计,实现红外遥控器的复制与红外信号的发送_第1张图片 图1.0


B.然后是红外接收头接32的定时器捕获引脚(这个要看32的引脚分配,不能随便分配),我所捕获的就是解调后的高低电平时间,这个不需要遵守遥控器的编码协议,因为我们是复制,那些完全不用管,如图1.1。

基于STM32的红外遥控器设计,实现红外遥控器的复制与红外信号的发送_第2张图片 图1.1


C.将我们记录的高低电平时间分开(采用定时器的上升沿捕获和下降沿捕获),将每组记录的时间都放在数组里,肯可能有点多,一般的遥控器60到70组数据(高低电平总和),像美的空调,格力空调的话大概有150多组,经测试,数组大小为200的话,复制市面上大多数遥控器都可以。采集到的数据存在32的flash里,这样实现资源的合理利用,也可以外接存储器,看你自己的选择,这样复制就完成啦!
3.怎么发射
A.产生载波:我们产生38K的载波,具体怎么产生以及原理我就不再这里啰嗦啦,我改的那部分代码里有,唉~我再次帖到这里,

void SendPort(void){      //发送端口,此端口为PWM导通端口
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        
        GPIO_InitStructure.GPIO_Pin        = GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB, GPIO_Pin_7 );
}

void TIM4_PWM_Init(u16 arr,u16 psc)//TIM4 CH3   PB8
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef        TIM_TimeBaseInitStructure;
        TIM_OCInitTypeDef              TIM_OCInitStructure;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);    //使能定时器4时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //使能GPIO外设时钟
        
        /* GPIOB.9初始化 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;         // TIM4 CH4
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // PB8复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_8);
        /* TIM4初始化*/
        TIM_TimeBaseInitStructure.TIM_Period = arr; //下一个更新事件装入活动的自                            
                                                      动重装载寄存器周期的值
        TIM_TimeBaseInitStructure.TIM_Prescaler = psc;  //作为TIMx时钟频率除数的预分频值 
        TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;  //时钟分割:TDTS = Tck_tim
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
        /* 定时器TIM4 Ch4 PWM模式初始化 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM PWM1
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出能
        //TIM_OCInitStructure.TIM_Pulse = (arr+1)/2;          //占空比 50%
        TIM_OCInitStructure.TIM_Pulse = (arr+1)/3;            //占空比1:3
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:TIM输出比较极性            
                                                                   高
        TIM_OC3Init(TIM4, &TIM_OCInitStructure);

        /* 使能TIM4在CCR1上的预装载寄存器 */
        TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); 
        
        /* 使能定时器 */
        // TIM_Cmd(TIM4,ENABLE);
        SendPort();  //这里下面说,这是红外信号控制发射端口,

}


上面就实现了38K的载波啦!要是不能理解的话,建议去看下STM32的PWM怎么产生的相关资料,加油!其实你按我这样配置完全没得问题。
B.怎么发送:先说下我的发射电路吧,如图1.2 ,发送端口随便定,有了电路后就好办啦,单片机一上电一直产生38K载波,也就是说下面那个三级管一直在开与闭合之间变化,发射端口的作用就是读取刚才存储在数组里的的那些数据,至于怎么读取发送,我也把代码帖在下面把,大家都是为了学习,我也是学生,为了学习就应该互相帮助。

基于STM32的红外遥控器设计,实现红外遥控器的复制与红外信号的发送_第3张图片 图1.2


源码太多了,我只给出核心部分,注意***为重点

     if(T1==0X00){                //串口接收,发送命令
         STMFLASH_Read(ADDR1,Pulse1,200);   //***这里读取数据
         delay_ms(500);
//       TIM_Cmd(TIM1,DISABLE ); //***
//        TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC1,DISABLE);//***
          1=0x10;
      }
      else if(T1==0x10){
             GPIOB->BRR |= 0x0020;//0 红色
             GPIOB->BSRR |= 0x0040; //1//绿色LED  //不用管,我弄的指示灯
             for(i1=1; i1<200; i1++)         //***从1开始的原因是,数组里第0位为无效数据
             {
               if(Pulse1[i1]==0x00) {      /***以防数据没有200组实际只有150组,后面的都为0, 
                                              这 样会导致死机,所以数据为0后就结束发送
                 GPIOB->BSRR |= 0x0020; //1  RED
                 GPIOB->BSRR |= 0x0020;  //1   GREEN
                 GPIOB->BSRR |= 0x0081;//***发送管脚,通过寄存器操作更快点
                 continue;   
               }
              else{
                 if(i1%2 == 0)              //***偶数位发送
                 {
                   //GPIO_SetBits(GPIOB,GPIO_Pin_7);
                   GPIOB->BSRR |= 0x0081;//****
                   delay_us(Pulse1[i1]);//***延时一定要精确,原因,模拟采集的时间控制发送端口 
                                             的高低电平,实现 和载波的调制
                 }
                 else
                 {
                    //GPIO_ResetBits(GPIOB,GPIO_Pin_7);
                     GPIOB->BRR |= 0x0081;//***
                     delay_us(Pulse1[i1]);/***
                 }
               }
             }
                    GPIOB->BSRR |= 0x0020; //1
                    GPIOB->BSRR |= 0x0040; //1
                    GPIOB->BSRR |= 0x0081;/***
                    USART3_RX_BUF[1]=0x00;
        }        

最后我的项目链接放到这里吧:https://gitee.com/little_young5280/opencode

B站演示视频:[B站](https://www.bilibili.com/video/av50295558)

你可能感兴趣的:(学习总结)