一、 为什么要用软件来编解码
从公司的角度来讲:
1> 省掉了
2个
IC ,
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个只有
4a(
a是时钟周期)的高电平和
2个
12a的低电平
bit1:读取
2个
12a的高电平和
2个
4a的低电平
同步头:读取一个
4a的高电平,然后再读取
124a的低电平。
三、 实际编码
我这里简化了编码,
bit0只有一个
4a的高和
1个
12a的低,
bit1有
1个
12a的高和一个
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证明解析的位是
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发送模块发送出去
第一次写分享帖子,东西虽然简单,但是我也花了点心思。
做项目的时候也经常会参考原子的哥的代码,这里分享点东西,算是对社会的回报吧
~以后还会继续拿以前做的一些东西来分享
…..
一周热门 更多>