许多刚开始玩单片机开发的人都还对某些深刻的发射接收原理有点懵逼,另外网上也可以搜到很多的模拟通信啥的代码。看起来都云里雾里的。我在这里介绍一个最简单基础的发射和接收代码。基本上单片机都能通用。**仅作参考,以示启发**
首先我先说明下原理,其实说白话。就是对电平信号的发射和接收,先和对方说好接到这个电平信号你就做什么动作。这样的互相通信,其他通信方式各有千秋,以后可以慢慢理解。先说这个最简单的。最重要是要懂原理。才能为你所用。
先说接收吧,首先想要接收电平信号,必须得配置一个引脚。来接收电平。 那么首先就要配置一个输入脚。因为众多单片机的引脚功能不一样,比如很多有什么悬浮输入输出,下拉什么的。这个大家可以去搜索下大概什么意思。 一般稳重点是下载你所用的单片机规格手册,按照里面的来配置I/O口。 我的是芯片是SH79F166A。别担心芯片和你的对不上号,今天所说的发射和接收是任意单片机I/O都可以完成的。只要配置准确。 我说一下我的配置吧,也是最基本的。有些单片机I/O口有其他特殊功能的建议了解后再考虑开不开。
第一个,既然是接收,那就肯定是输入口,关于怎么配置,这个大家自行搞定,这里说明不了那么多了。OK,配置为输入口,第二:禁止上拉电阻。什么端口寄存器啥的一般都不开。最重要一个。引脚探测高电平还是低电平的表示方法这个自己要写出来。在这里我插入一个表示引脚的一个方法。大家一开始可能都是看51的。引脚表示就是sbit Set=P1^0 这样的,我只想表示这个到了后面自己开发都不这样做的。一般都是根据芯片的头文件再根据自己的喜好自己编写一个。 我的是这样的,在自己的头文件这样定义。不会的话也可以在自己main文件里定义。
#defined Seg 0x40(因为知道它是作为P1脚的上8位的第2位所以先这样定义好。0x40为16进制8421码)。然后是
#define Gp (P1 & Seg)(这个表示为引脚检测为高电平,即Set就可以表示为高电平),实际上就是P1&0x40赋给Gp,就是吧P1上4位的第二位的地址给Seg,然后再用Gp表示。 记的是(P1 & Seg),没有等号的。下一个在发射那里就是才有等号。这样想就可以了,输入口不是你自己决定电平的,是外部决定的。所以没有赋值的动作。 低电平的表示方法 #define Dp ((P1 & Seg)==0), OK引脚配置完毕,接下是代码。![这个是用逻辑分析仪测试到的发射版的信号,你要知道你接的信号的范围,然后才能筛选自己要的。我的是有24位。也就是有24个周期(可以数数那方框)。就是有3个byte的信息在里面](https://img-blog.csdn.net/20160922230008756)
OK确定好后代码开始:
`void jieshou() //接收函数开始
{
//这里说明下,C代码里是没有byte这个数据类型的,我是在头文件定义过才
byte x; //有,byte和char是一样的。大家喜欢定不定义都可以。
byte y;
byte timeH; //高电平时间
byte timeL; //低电平时间
byte RxBit=24; //总共要接收24位。。~~~不同数据不一样的,以逻辑分析仪接收到的数量为准
long RxBuf=0; //用来存放接收到的数据
byte RFByte[2]=; //最终数据会被存到这个数组,里面有3个byte(所以能装24位)
for(x=0;x<=2;x++){ //先对数组清零
RFByte[x]=0;
}
if(Gp) //如果检测到高电平则进入接收
{ //进来开始循环
while(1){
for(x=0;x<70;x++){ //然后进入for循环,这里有点重要了,我下面那个延时函数能延时20us的。测的最长的一个电
//平信号为1340us 所以最长给它转70圈(留了点空间作为取样误差)
if(Dp){ //在高电平循环过程中,如果遇到低电平出现则跳出。
break;
}
else
yanshi(6); //低电平没出现的话,就继续每20us采样一次
}
if(x>=69) //遇到低电平跳出~,我们先判断刚才的高电平周期是否自己要的长度,这里是判断筛选
break; //假如不符合,则跳出整个while循环,重新进入采样。
if(x<6) //判断是否小于最小长度。
break;
timeH=x; //如果通过筛选,则赋给它存储
RxBuf>>=1; //存储位事先右移一次,如果为低电平则下面不用赋值,高电平的话就(往下看)
for(y=0;y<70;y++){ //然后进入低电平筛选,范围一样。都是以最大的电平为基准
if(Gp){ //如果采样期间遇到高电平则跳出
break;}
else //否则延时20us采样一次
yanshi(6);
}
if(y>=69)
break;
if (y<6) //这两个依旧是判断是否符合
break;
timeL=y; //没问题话赋给低电平
if(timeH>timeL){ //然后两个比较
RxBuf |=0x800000; //如果是高电平的话则最高位置1,低电平的话就直接跳过,因为上面已经右移过了
} //最高位本来就是0了。
RxBit--; //确定完一个周期的电平后,次数减一。然后回去循环测下一个电平
if(RxBit==0){ //如果24次都减完后则跳出
break;
}
}
if(RxBit==0) { //如果都次数都检测完后,则进来这里把所有数据存到数组里面
RFByte[0]=(byte)RxBuf; //RxBuf通过byte强转后就只剩下8位,赋给0数组
RFByte[1]=(byte)(RxBuf>>8); //以此类推,右移8位再强转。
RFByte[2]=(byte)(RxBuf>>16);
Set_Led(); //这里就会亮个等,表示接收完成。一般只要能通过上面所有数据筛选
//并且你的筛选范围都没问题的话,到了这里数据一般都是自己想要的,一般不会有误差。
}
}
}
到此接收部分就结束了,其实很简单。就是判断高电平和低电平谁的时间长。 一个是采样范围,一个是采样周期。这两个把握好就没问题。 下次我们再介绍怎么把现在接收到的信号再通过任意i/o口发出去。
代码有点乱….初次用这个编译器还不怎么那个。 我是直接把代码粘贴上去的,所以看起来有点麻烦哈。主要是传达思路。