历史上的今天
返回首页

历史上的今天

今天是:2024年12月28日(星期六)

2018年12月28日 | 基于STM32和EV1527的无线接收解码程序

2018-12-28 来源:eefocus

一、1527的数据帧结构 


无线遥控的编码,从编码类型上来说,分为2类,一类是固定码,也就是编码芯片的地址是不变的,芯片型号以 EV1527、PT2262 为代表。另一种是滚动码,芯片的地址码是变化的,芯片以HS300、HS301为代表。


1 EV1527 数据帧结构 


EV1527 是一片由 CMOS 设计制造的可预烧内码的学习码编码IC ,由软件解码;内码共有 20 个位元可预烧 1048576 组内码组合,降低使用上编码重复的机率。 


EV1527 每帧数据由 24 个数据位组成,前 20 位为地址码,对于一个芯片来说,地址位的内容是固定的,是出厂前就预制好的,并且理论上每个芯片的地址码是唯一的。后面 4 位为按键码,对应芯片上的K0-K3 4 根数据线,数据线的状态不同,按键码就不同。 


在数据位之前,还有一个同步脉冲,也就是每帧数据都是从同步脉冲开始的。数据位的“1”和“0”是由高低电平宽度(脉冲宽度)的比例决定的。如果高电平宽度为低电平宽度的 3 倍,就表示逻辑“1”,反过来如果低电平为高电平宽度的 3 倍,就表示逻辑“0”。同步脉冲高电平和低电平的比例固定为 4:124. 


1527时序 
这里写图片描述
这里写图片描述 
这里写图片描述


二、中断方式的解码 


把串行输入的编码数据帧,还原成编码之前的状态,读取其中的地址码和按键码,称之为解码。 


数据帧都是由同步头开始,然后是 24位的数据码,并且此数据帧在遥控器按键的过程中是重复出现的,我们首先要判断同步码,判断出了同步码,就知道数据码是从那一位开始了。对于一款量产的无线遥控器来说,他的编码芯片匹配的电阻是一个固定值,也就是说它发射的数据帧的脉冲宽度是不变的,所以我们可以通过测量高低脉冲宽度的方式来分辨同步码、逻辑“1”、逻辑“0”。 


具体的方法是这样的,首先启用定时器,装入一个初值,打开定时器中断,让其以固定的间隔进入中断程序。在中断程序中,我们查询数据输入管脚的状态,如果为高电平,就在高电平状态累加计数,反之就在低电平状态计数,当电平发生上升沿变化的时候,判断接收到的高低电平宽度的值是否符合同步信号的要求,如果符合就进入数据位的接收,以同样的方式判断逻辑“1”或逻辑“0”。如果接受过程中出现不符合要求的电平状态,就退出接收,为了增加可靠性,我们一般要求规定时间内,成功接收到完全相同的 2 帧数据才算有效。 


接收完成后,24 个数据位被放入 3 个字节中。下一步我们要对接收到的数据进行处理,判断编码的类型,分离地址码和按键码。


三、程序代码


/*main.c*/


#include "stm32f10x.h"

#include "uart.h"

#include "led.h"

#include "delay.h"

#include "sys.h"

#include "timer.h"


uint8_t rf_data[4];

extern uint8_t decode_ok;    //解码成功标志位

extern uint8_t RF;


int main(void)

{   

    LED_Init();

    Uart_Init();

    delay_init();   //延时初始化一定要加上!!!!!!

    EV1527_GPIO_Init();

    TIM6_NVIC_Init();

    TIM6_Mode_Init();


    while(1)

    {

        if(decode_ok == 1)   //解码成功

        {

            switch(rf_data[2])

            {

                case 0xf8:   //解码为0xf8,点亮LED

                {

                    LED1 = LED_ON;

                    LED2 = LED_ON;

                    LED3 = LED_ON;

                    break;

                }

                case 0xf2:   //解码为0xf2,熄灭LED

                {

                    LED1 = LED_OFF;

                    LED2 = LED_OFF;

                    LED3 = LED_OFF;

                    break;

                }


            }


        }

/***调试用代码,查看接收到的编码***/      

//      printf("\r\n EV1527 \r\n");

//      delay_ms(500);

//      printf("i get %x  ",rf_data[0]);

//      delay_ms(500);

//      printf("i get %x  ",rf_data[1]);

//      delay_ms(500);

//      printf("i get %x  ",rf_data[2]);

//      delay_ms(500);

//      printf("i get %x  ",rf_data[3]);

//      delay_ms(500);

    }

}

/************** END OF FILE *****************/



/*Timer.c*/



#include "stm32f10x.h"                  // Device header


#include "timer.h"

#include "led.h"

#include "uart.h"

#include "delay.h"


void EV1527_GPIO_Init() //EV1527 IO口初始化

{

    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // PB9 输入端

    GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_9; 

    GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN_FLOATING;

    GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStruct);

}


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


void TIM6_NVIC_Init()   //中断分组初始化

{

NVIC_InitTypeDef NVIC_InitStructure;    

                         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

//TIM6中断

NVIC_InitStructure.NVIC_IRQChannel = TIM6_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 TIM6_Mode_Init()

{    

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    //使能TIM6时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, 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(TIM6, &TIM_TimeBaseStructure); 

    //允许更新中断 

    TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);

    TIM_ClearFlag(TIM6,TIM_FLAG_Update);

    //使能定时器6

    TIM_Cmd(TIM6,ENABLE );  

}


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;     //自动设置遥控接收波特率标志

extern uint8_t rf_data[4];  


void TIM6_IRQHandler()

{

    if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)

    {

        TIM_ClearITPendingBit(TIM6, TIM_IT_Update); 


        //接收数据的电平 PB9

        RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9); 

        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(TIM6, TIM_IT_Update, DISABLE);

        rf_ok=0; 

        rf_data[0]=mma1;

        rf_data[1]=mma2;

        rf_data[2]=mma3;


        decode_ok=1;


        TIM_ITConfig(TIM6  , TIM_IT_Update, ENABLE);

        }

    }

}


推荐阅读

史海拾趣

DFI公司的发展小趣事

随着市场竞争的加剧,DFI意识到单一产品的竞争力有限。因此,公司开始寻求垂直整合的机会,与罗升等公司合作,共同开发智能制造的全面性解决方案。这一举措不仅使DFI能够提供更完整的产品线,还增强了其在行业中的竞争力。通过与合作伙伴的紧密合作,DFI成功推出了一系列具有竞争力的智能制造解决方案,赢得了市场的广泛认可。

EDSYN公司的发展小趣事

为了帮助客户更便捷地将设备连接到物联网,Econais与Xively展开了合作。通过这一合作,Econais的WiSmart Wi-Fi用户可以无缝连接到Xively云,为工业、商业和住宅市场带来了创新的医疗保健、智能能源、无线音频控制和监控产品。这种一站式的物联网解决方案大大加快了物联网产品的上市时间,同时也降低了产品的开发成本。

Gigarams Semiconductor Device Corp公司的发展小趣事
这可能是由于传感器精度不足、控制器算法不准确或驱动器性能不稳定等原因导致的。解决方案包括提高传感器精度、优化控制器算法和更换性能更稳定的驱动器。
台湾凯励(Carli)公司的发展小趣事

随着技术的不断成熟和市场的不断拓展,凯励公司开始在全球范围内布局。1997年,公司在广东省东莞市设立“东莞凯励电子有限公司”,进一步扩大生产规模。2002年,又在浙江省嘉兴市设立“浙江嘉兴凯励电子有限公司”,进一步完善了公司的产业布局。这些举措不仅提升了凯励公司的产能和效率,也使其能够更好地满足全球客户的需求。

ATP [ATP Electronics]公司的发展小趣事

ATP Electronics自创立之初,便以技术创新为核心竞争力。公司特有的SIP(Systems-In-Package:系统级封装)技术,在闪存卡制造领域引起了革命性的变革。通过SIP技术,ATP成功研发出超大容量的闪存卡,不仅满足了市场对于高性能存储的需求,也确立了公司在闪存卡市场的领先地位。这一技术的突破,为ATP带来了大量的订单和市场份额,奠定了公司持续发展的基础。

CIRCUITCO公司的发展小趣事

CIRCUITCO公司自创立之初,就致力于电子电路技术的研发。在某一时期,公司投入大量资源研发新型高性能电路板。经过数年的努力,团队终于成功开发出一款具有更高集成度、更低能耗的电路板。这一突破不仅提升了公司的技术实力,也使其在市场上获得了显著的竞争优势。随着这款新产品的推出,CIRCUITCO公司的业绩迅速攀升,成为行业内的佼佼者。

问答坊 | AI 解惑

EVC读取串口的简单问题

本人现在有一个“英创EM9260”套件,想在上面做一个简单的串口程序,实现给一个电度表发送字符串并接收其返回的字符串,然后通过一个lcd屏幕显示返回的字符串。我把套件提供的一个串口通信的示例程序做了简单的修改,但是只能实现发送数据,回收的 ...…

查看全部问答>

求助:TI OMAP3530的问题请教下

有没有使用过OMAP3530的兄弟,有个问题请教下:   在CCS下写的基于DSP/BIOS的程序,能不能访问McBSP? OMAP的技术支持说,OMAP3530是ARM做主控,DSP做运算,只有ARM能控制外设。 但是我在网上查的一些资料,却有人说可以直接访问寄存器 ...…

查看全部问答>

如何获取鼠标点击后的坐标? 位置

如何获取鼠标点击后的坐标?   位置…

查看全部问答>

四口网卡驱动问题

像Intel四口网卡是怎么实现驱动加载之后,用ifconfig命令就可以看到这四个网口的信息(分别为eth0,eth1,eth2,eth3),这个信息的注册是在网卡驱动中完成的还是在driver/net/core/dev.c中完成的?我在网卡驱动代码中根本就没有看到针对四个网口进行处 ...…

查看全部问答>

UL 8750 用於燈具產品的發光二極體光源 安全通則

這是用於燈具產品內的發光二極體光源的評估指南的第一版,適用於發光二極體作為光源的元件,例如發光二極體模組,發光二極體陣列、電源與控制電路。也涵蓋了由最終產品製造商製作的發光二極體光源,它可以是產品的一部分或 ...…

查看全部问答>

LM3S8962自带工程boot_demo_eth经常出现烧录失败的问题。IAR编译的。大家碰到过吗?

LM3S8962自带工程boot_demo_eth经常出现烧录失败的问题。其它工程很少出现。IAR编译的。大家碰到过吗?     用LM Flash Programmer 下载是成功的,没有任何出错的信息。但是下载完成后,就是没有办法跑起来。 用IAR可以调试,但是调 ...…

查看全部问答>

一个关于CAN 电路接口的问题

我在在板子上看见在CAN接口的高低之间接一个2K的电阻有什么作用啊…

查看全部问答>

Hanker试用周计划提交

Hanker试用周计划提交…

查看全部问答>