FM非相干解调原理及Keil代码
- 原理
- 拉格朗日插值
- 代码
原理
原理部分因为有很多人解释就不赘述,需要的人会给出链接自行学习
相干解调:相干解调也叫同步检波,它适用于所有线性调制信号的解调。实现相干解调的关键是接收端要恢复出一个与调制载波严格同步的相干载波。相干解调是指利用乘法器,输入一路与载频相干(同频同相)的参考信号与载频相乘。
非相干解调:通信接收端从已调高频信号中恢复出原始数字基带信号时,采用的非相干解调方式,相对于相干解调方式,是指不需要提取载波信息的一种解调方法。
我们将上述的调制信号分别乘以coswt,-sinwt,就可以得到相应的IQ路的数据,然后分别通过一个低通滤波器,滤除高频分量,就可以的得到以基带信号为频率的I路Q路载波信号,然后两个再相比,就可以得到其正切值,再求反正切就可以了的到其角度,角度就是我们的基带信号。
但是,在上面解调的时候,使用了反正切,这个运算量很大,在FPGA中也难以直接实现,所以,通过改进算法,可以简化计算过程。
所以今天代码的重点就在简化计算上
链接: 算法原理
拉格朗日插值
FM正交调制是分IQ两路,解调部分也是如此,但是只能得到I(n),Q(n+1),I(n+2),Q(n+3)…
实际上解调序列就是一个相互间隔、交替出现的IQ序列,但IQ值在时间上正交的,如下所示:
显然不利于计算公式的计算
简单来说,就是我有I(n),但没有Q(n),这里就用到拉格朗日插值法了,具体来说是拉格朗日型4次插值多项式.
链接: 拉格朗日插值法原理
举个栗子:已知Q1 Q3 Q5 Q7(Q路分量),来求Q4
Q4=K0Q1+K1Q3+K2Q5+K3Q7(Ki是系数)
K0=(4-3)(4-5)(4-7) / (1-3)(1-5)(1-7)=1/16
K1=(4-1)(4-5)(4-7) / (3-1)(3-5)(3-7)=-9/16
K2=(4-1)(4-3)(4-7) / (5-1)(5-3)(5-7)=9/16
K3=(4-1)(4-3)(4-5) / (7-1)(7-3)(7-5)=-1/16
这个公式不懂可以看上面拉格朗日插值的链接。
以此类推可以推出所有的IQ路分量
代码
下面代码包含了鉴频和5:1抽取
void detectFreq(float *inBuf,float *outBuf)
{
register short i = 0;
static float temp[1207] = {0};
float m;
float rssi;
const float TH = 0.18;
for(i=0;i<7;i++)
temp[i] = temp[SAMPLE_SIZE+i];
for(i=0;i<SAMPLE_SIZE;i++)
temp[i+7] = inBuf[i];
for(i=0;i<SEND_SIZE;i++)
{
m=temp[6+5*i] * temp[7+5*i] + 0.00390625 * (9*temp[7+5*i] - 9*temp[5+5*i] + temp[9+5*i] - temp[3+5*i]) * (9*temp[8+5*i] - 9*temp[6+5*i] + temp[10+5*i] - temp[4+5*i]);
//0.00390625就是1/16
rssi=temp[6+5*i]*temp[6+5*i] + 0.00390625*(9*(temp[7+5*i]-temp[5+5*i])+temp[9+5*i]-temp[3+i*5]) * (9*(temp[7+5*i]-temp[5+5*i])+temp[9+5*i]-temp[3+i*5]);
//0.00390625就是1/16
outBuf[i]=0.5*(m)/(rssi);
if(outBuf[i]>TH ) //原始数据是 0.3 限幅
outBuf[i] = TH;
else if(outBuf[i]<-TH)
outBuf[i] = -TH;
}
}
看到这里了,点个赞呗