绝对的IO模拟PT2262/2272编解码(433M超再生接收头),软件编码方便不同协议。

2019-07-20 06:24发布

一、      为什么要用软件来编解码 从公司的角度来讲: 1>  省掉了2IC PT2262/PT2272 2>  协议灵活,可以随自己定义,也可以传输数据(我这里是读取IC卡的数据发送出去,数据量小,就4byte) 缺点:软件编码耗CPU资源多,中间有好多延时,严重占掉CPU资源,当然有好办法,可以把这个时间省出来,我做的这个项目功能简单,就直接延时,没有做优化。 硬件图片:



|------>  一组   <-------------|     |------>  二组   <-------------| 发送一次指令2262会连续发送4组相同(防止第一组数据出错时,可以解析下一组数据)   2>  2262位编码 超再生接收头,会收到空中任何谐振(433MHz)的信号,都会产生数据输出,所以在接收头上电后数据输出端示波器看全是杂波,因此直接收发信号是不可能收到正确的数据的。但是有一个特性,就是在收到较强的ASK信号后一段时间会保持状态(这个跟超再生电路起振相关,具体可以查找“超再生接收电路”),这里是了解编码要掌握的知识。我也是第一用这个,有错误的地方,希望“道友”指正。   从发送帧可以看出,发送数据之前都要发送一个同步头,同步头波形如下: (波形都是宽度识别,所以要注意波形的宽度)  

                                           图一
  Bit0/1编码如下:  图二 说明:2262只有12位地址线,为了获得更多的地址编号,地址线除了1/0还有一个空状态,即途中的f编码,这样12位地址线就可以编3^12个地址了。 数据读取方法: bit0: 读取2个只有4aa是时钟周期)的高电平和212a的低电平 bit1:读取212a的高电平和24a的低电平 同步头:读取一个4a的高电平,然后再读取124a的低电平。 三、      实际编码 我这里简化了编码,bit0只有一个4a的高和112a的低, bit1112a的高和一个4a的低,而且帧格式为: 同步头+16位地址+16位数据    同样是连续发四次。 这是示波器抓的波形:
   可以看出图中的数据:1100000111010000110…. 以下是实际代码(CPU是飞思卡尔K20):   static U8  fac_us=0;   // 延时倍数 // GPIO初始化 void RF433MHz_Init(void) {       SIM->SCGC5 |= (1 << 13);          // 使能E口的时钟       RF_DO_OUT;                               // 发射端口       RF_DI_IN;                                  // 接收端口   // 定时器,寄存器清除,这个用于精确延时     PIT->CHANNEL[1].LDVAL = 0;                // FCCK/2/1000     //NVIC_SetPriority(PIT0_IRQn,3);     //NVIC_EnableIRQ(PIT1_IRQn);     // PIT->CHANNEL[1].TCTRL =  PIT_TCTRL_TIE_MASK;   // 中断开启     PIT->CHANNEL[1].TCTRL &= ~PIT_TCTRL_TEN_MASK;  // 启用定时器       fac_us = 36;                                   //PIT1的时钟是系统时钟的一半 }     // 500us一个单位延时 void Delay(U8 _us) {     U32 temp;       PIT->CHANNEL[1].TFLG |= PIT_TFLG_TIF_MASK;     // 清除标志     PIT->CHANNEL[1].LDVAL = fac_us*_us*500;     PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;  // 启用定时器     do     {         temp=PIT->CHANNEL[1].TFLG;     }while(!(temp&0x1));     PIT->CHANNEL[1].TFLG |= PIT_TFLG_TIF_MASK;     // 清除标志     PIT->CHANNEL[1].TCTRL &= ~PIT_TCTRL_TEN_MASK;  // 启用定时器 }   /*       模拟PT2262编码          发送数据 */ // 同步头 void RF_sof(void) {       RF_DOH;       Delay(4);       RF_DOL;       Delay(124);  // 50ms }   // BIt 0 void RF_BIt0(void) {       RF_DOH;       Delay(4);       RF_DOL;       Delay(12); }   // BIt 1 void RF_BIt1(void) {       RF_DOH;       Delay(12);       RF_DOL;       Delay(4); }   // 发送  UINT void SendINT(U16 cDat) {       U8 i;     U16 Dat;       Dat = cDat;       for(i=0; i<16; i++)       {            if(Dat&0x8000)                  RF_BIt1();            else                  RF_BIt0();            Dat <<= 1;       } }   // 发送一组编码   void RFSendData(U16 ADDER, U16 Dat1) {       RF_sof();       SendINT(ADDER);       SendINT(Dat1);       RF_sof();       SendINT(ADDER);       SendINT(Dat1);     RF_sof();       SendINT(ADDER);       SendINT(Dat1);       RF_sof();       SendINT(ADDER);       SendINT(Dat1);       RF_DOH;     Delay(32); RF_DOL; // 这里加一个高是防止帧之间的同步头,低的时间长,会使接收头数据输出端又全是杂波 }       /*       模拟PT2272解码       接收数据 */     // 同步头接收 U8 Rec_sof(void) {     U8 temp;       //if(RF_DIR)      // 这里又简化了一步,只判断124a的低状态^V^     //{         //Delay(5);         if(!RF_DIR)  // 当收到低电平         {             PIT->CHANNEL[1].TFLG |= PIT_TFLG_TIF_MASK;     // 清除标志             PIT->CHANNEL[1].LDVAL = fac_us*122*500;             PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;  // 启用定时器             Do    // 122a的时间内不断读取DO状态             {                 temp=PIT->CHANNEL[1].TFLG;                 if(RF_DIR)   // 一旦发现有到电平,证明这个不是同步头,直接跳出                 {                     PIT->CHANNEL[1].TFLG |= PIT_TFLG_TIF_MASK;     // 清除标志                     PIT->CHANNEL[1].TCTRL &= ~PIT_TCTRL_TEN_MASK;  // 启用定时器                     return 0;   // 返回0,证明不是同步头                 }             }while(!(temp&0x1));             PIT->CHANNEL[1].TFLG |= PIT_TFLG_TIF_MASK;     // 清除标志             PIT->CHANNEL[1].TCTRL &= ~PIT_TCTRL_TEN_MASK;  // 启用定时器         }         else             return 0;     //}     //else         //return 0;       return 1;  //返回1,是同步头 }   // 解析一个编码,返回0证明解析的位是反之为1 U8 RecBit(void) {     while(!RF_DIR);     Delay(10);     if(RF_DIR)     {         Delay(4);         return 1;     }     else     {         Delay(4);         return 0;     } }   // 一个Uint型数据的解析 U16 RecInt(void) {     U16 i,Dat = 0;       for(i=0; i<16; i++)     {         Dat <<= 1;         if(RecBit())             Dat |= 1;     }     return Dat; }     // 接收一个数据帧 void RecData(void) {       U16 ADDER = 0;       U16 DATA1 = 0;         if(Rec_sof()) // 同步头检测       {         ADDER=RecInt();   // 连续读取后面32位,注意这里必须要不间断的读         DATA1=RecInt();         // 通过串口打印读取到的数据         UART0_SendByte(ADDER);         UART0_SendByte(ADDER>>8);         UART0_SendByte(DATA1);         UART0_SendByte(DATA1>>8);             if(DevicAdder == ADDER)   // 数据解析,地址对比         {             switch(DATA1)             // 数据解码             {             case 1:  BUZZER(600,100,1);   // 数据DATA1 = 1 蜂鸣器响1                break;             case 2:  BUZZER(600,100,2);  // 数据DATA1 = 2 蜂鸣器响2                break;             }         }       } }   // 这是发送一帧数据的函数 HL_Read  读取到IC卡并成功,蜂鸣器响一声,串口返回读取的16个字节,然后通过433MHz发送模块发送出去     第一次写分享帖子,东西虽然简单,但是我也花了点心思。 做项目的时候也经常会参考原子的哥的代码,这里分享点东西,算是对社会的回报吧~以后还会继续拿以前做的一些东西来分享…..
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
17条回答
lushp88
1楼-- · 2019-07-20 07:54
图示中有些,以前的注释,可能是错误的。
那个延时时间我用的是500us一个单位,这个也可以修改,但是不要太快,查看发射模块的最高调制率是3Kbps,也就是最快84us左右
正点原子
2楼-- · 2019-07-20 13:19
 精彩回答 2  元偷偷看……
lushp88
3楼-- · 2019-07-20 18:27
回复【3楼】正点原子:
---------------------------------
刚刚做完,测试了几天,没发现异常。 还没到生产阶段,也只是简单的通信测试,并没有做干扰测试。
正点原子
4楼-- · 2019-07-20 20:10
 精彩回答 2  元偷偷看……
lushp88
5楼-- · 2019-07-20 23:32
 精彩回答 2  元偷偷看……
正点原子
6楼-- · 2019-07-21 00:26
回复【6楼】lushp88:
---------------------------------
好资料,应该的。

一周热门 更多>