无线收发模块的设计一、设计方案为了能实现数据通过无线方式进行传输的目的,采用hopeRF公司的无线单片收发IC RF12完成无线收发功能。
为了能对RF12进行控制,采用ATMEL公司单片机A VRMEGA48对RF12进行控制,为了与PC机连接方便,采用了沁恒公司的USB转串口电路CH340与单片机相连。
系统结构示意图如下:二、电路设计2.1 RF12电路设计2.1.1 RF12功能简介RF12是通用ISM频段的FSK发送接收集成单片电路,低功耗,多通道,可以工作在免许可的433,868和915MHz频段。
RF12首发电路为需要外部很少器件的集成电路,具有低成本,柔韧性好的高度集成的解决方案。
芯片集成所有射频要求功能,完整的模拟射频部分和数字基带收发部分,多频段PLL频率合成器,射频功率放大器PA,低噪声放大器LNA。
正交(I/Q)下变频混频器,基带滤波器和基带放大器,和正交(I/Q)解调器。
唯一需要的外部器件就是外部晶振和带同滤波器。
RF12具有一个全集成的PLL,便于射频设计,它的快速设定时间可以用于快速调频,对于多路径衰落信道可以获得强健的无线连接。
PLL的高分辨率允许在任一频段进行多信道应用。
接收部分的基带滤波带宽(BW)是可编程的,以可以包纳各种偏差,数据速率和晶振偏差的要求。
接收部分应用了零中频方法,该方法采用了正交解调技术。
同样在大多数应用中不需要外部器件(除了晶振和耦合电路)。
RF12通过集成的数字信号处理特性:数字滤波,时钟恢复,数字判决,集成的FIFO 和发送数据寄存器(TX data register),显著的减小了微处理器的负担。
自动频率控制特性允许使用低精度(低成本)晶振。
对于低功耗应用,RF12支持基于内部唤醒定时器的小占空比的周期工作模式。
功能模块框图2.1.2RF12电路设计在设计中采用RF12接收部分采用片内数字滤波器来提取接收数据流的位时钟方案,通过SPI接口设置工作参数,发送数据和接收数据。
频带设计为433MHz,射频匹配滤波电路根据生产商提供的资料设计电路如下:2.2、RF112与单片机Mega48接口设计Mega48单片机通过SPI接口与RF12相接,系统图如下:2由于SPI接口是单片机在线编程的下载口,同时又是与RF12的通信接口,为了在下载时不受RF12的影响,特在SPI接口与RF12接口之间通过电阻进行隔离。
2.3USB转传串口电路设计:CH340集成电路可以完成USB转串口的功能,PC机的驱动程序有沁恒公司提供,在PC上的界面与串口通信界面相同,根据厂家提供的参考电路设计如下:UART---USB二、射频参数计算2.1、RF12的工作原理:RF12为单片无线收发芯片,接收部分为采用正交解调的零中频技术,片上集成有基带低通滤波器,其带宽可程序控制,达到减低噪声系数的目的,同时还具有频率自动控制功能,以离散步进方式使得本振频率与发射机的载波频率差最小。
对于RF12的应用需要根据接收信号的特性需要对基带滤波器的代换进行计算。
2.2、正交零中频解调原理及低通滤波器带宽的计算:接收机结构如下图所示:设射频输入信号为:s(t)=Acos(ωt+(-1)DΔωt);本振信号为:L(t)=cos(ωLt+φ)通过正交下变频器:I(t)=s(t)×L(t)=A{cos(ω0t+(-1)DΔωt-ωL t-φ)+ cos(ω0t+(-1)DΔωt+ωL t+φ)}/2Q(t)=s(t)×sin(ωL t+φ)=A{sin(ω0t+(-1)DΔωt-ωL t-φ)+ sin(ω0t+(-1)DΔωt+ωL t+φ)}/2通过低通滤波器有:Ib(t)= Acos(ω0t+(-1)DΔωt-ωL t-φ)/2Qb (t)=Asin(ωt+(-1)DΔωt-ωL t-φ)/2当ω0=ωL,φ=0时有:Ib(t)= Acos((-1)DΔωt)/2 Qb (t)=(-1)D Asin(Δωt)/2当D=0时Ib和Qb构成正方向旋转向量,标识为频偏大于零;判读为0或1当D=1 时Ib和Qb构成反方向旋转向量,标识为频偏小于零;判读为1或0.在这里对于码元宽度为T,频偏为Δω,那么低通滤波器的带宽不应小于:Δω+2∏/T当考虑到本振与信号载波的偏差,滤波器的带宽应包含:频偏,数据速率和频率误差。
三、RF12的命令RF12的命令通过SPI口发送,共有15条命令:对于部分命令说明如下:频率设置命令12位参数F取值在96到3903之间,当送入的F值在范围之外,以前的F数据任然被保留。
频率合成器的中心频率f0可以计算如下:f0 = 10 * C1 * (C2 + F/4000) [MHz]常数C1和C2由所选择频段确定:数据速率命令在发射模式中发送数据的实际位速率和接收模式中接收数据期望的位速率通过7位参数R(bits r6 to r0)和cs位确定。
BR = 10000 / 29 / (R+1) / (1+cs*7) [kbps]在接收部分根据下面的函数设置R参数:R= (10000 / 29 / (1+cs*7) / BR) – 1, 这里BR是期望的位速率kbps。
除了设定客户数值外,标准位速率可以很小的误差设定从600bps到115.2kbps数据数率精度要求:在慢模式恢复时钟:ΔBR/BR < 1/(29*Nbit))在快模式恢复时钟:ΔBR/BR < 3/(29*NbitBR是在接收机设置的位速率,ΔBR是发射机与接收机之间的数率偏差。
Nbit是在数据流中最大的连续1或0的个数。
建议在长数据包中要包含足够多的1/0或0/1的变换,并在接收机和发射机中小心应用相同的分频比。
发送设置命令:位8-4 (mp, m3 to m0):FSK 调制参数为:导致输出的频率为:fout = f 0+ (-1)SIGN * (M + 1) * (15 kHz)这里:f0 为信道的中心频率(见频率设置命令)M is思维二进制数:<m3: m0>SIGN = (mp) XOR (Data bit)四、控制接口时序:对RF12的命令以串行方式发送。
只要当引脚nSEL信号为低逻辑电平,在SDI引脚上的数据在引脚SCK上的时钟信号的上升沿被移入器件。
当nSEL信号为高,接口被初始化。
所有命令由命令码,后跟可变数量的参数或数据位构成。
所有数据以高位先发送(例如对于16位命令的第15位)。
用X标识的位没有影响。
上电复位(POR)电路所有控制寄存器和命令寄存器设置默认值。
当下列事件发生,接收机通过将nIRQ引脚拉低对微处理机产生一个中断请求:TX寄存器准备接收下一个字节(RGIT)FIFO已经接收到程序设定的位数量(FFIT)上电复位(POR)FIFO溢出(FFOV)/TX寄存器覆盖(RGUR)唤醒定时器溢出(WKUP)在中断输出引脚nINT有负脉冲(EXT)电源电压低于设定的电压(LBD)当FIFO许可时FFIT和FFOV才能应用。
当TX寄存器许可时RGIT和RGUR才能应用。
通过读出状态位来识别中断源。
控制接口的时序图五、调试方法:对于发射功能调试的方法为采用频谱分析仪测量RF12的发射功率和频率,调试系统结构示意图如下:接口PC机通过USB口发送命令使无线模块工作在不同的通道上,连续发射,来观察整个频段的功率大小分布,频率精度等情况,以检验是否工作正常。
六、天线的制作:采用四分之一波长的天线,设计过程主要计算天线的尺寸,关键是调试其阻抗,调到50欧姆。
截取略长与四分之一波长硬铜线20CM,与50欧姆同轴电缆芯线焊接。
通过微波网络分析仪测量天线的驻波比,用手钳对天线顶端小心剪截,改变天线长度,使其驻波比最小即可。
七、单片机程序设计:两个模块分别通过USB口与PC机连接,PC机上运行串口调试程序,两台PC可以互相收发数据,下面是单片机程序:////////////////////////////////////////////////////// 芯片采用mega48,时钟采用外部晶振11.0592M ////连线图mega48 RFM12 //// (PB5)SCK ——> SCK// (PB3)MOSI ——> SDI// (PB4)MISO ——> SDO //// (PB2)SS ——> nSEL //// (PD2) ——> nIRQ// 编译器用CodeVisionA VR C Compiler //////////////////////////////////////////////////////#include<mega48.h>#include<delay.h>typedef unsigned char uchar;typedef unsigned int uint;#define SDI PORTB.3#define SDO PINB.4#define SCK PORTB.5#define nSEL PORTB.2#define nIRQ PIND.2#define LED PORTD.6void Init_RF12(void);void Write0(void);void Write1(void);void WriteCMD(uint CMD);void WriteFSKbyte(uchar *ptr,uchar num);void uart0_init(void);void INT0_init(void);uchar RF12_RDFIFO(void);//ucharmes[]={0xAA,0xAA,0x2D,0xD4,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0 x3B,0x3C,0x3D,0x3E,0x61,0xAA};//eeprom uchar mes1[25];uchar mes[50]={0xAA,0xAA,0x2D,0xD4};uchar RF_RXBUF[50];uchar i=0,j=0,t=0;uchar flag1=0,flag2=0;uchar tempdata;void Init_RF12(void){DDRB=0x2c;DDRD=0x42;PORTD.2=1;nSEL=1;SDI=1;SCK=0;WriteCMD(0x80D8);//EL,EF,433Mband,12.5pFWriteCMD(0x82D8);//turn on crystal,!PAWriteCMD(0xA640);//434MHz// WriteCMD(0xAE10);//439M// WriteCMD(0xA9B0);//436.2MWriteCMD(0xC647);//4.8kbpsWriteCMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm WriteCMD(0xC2AC);//AL,!ml,DIG,DQD4WriteCMD(0xCA80);//FIFO8,SYNC,!ff,DRWriteCMD(0xCA83);WriteCMD(0xC49B);//@PWR,NO RSTRIC,!st,!fi,OE,EN WriteCMD(0x9850);//!mp,9810=30kHz,MAX OUTWriteCMD(0xE000);//NOT USEWriteCMD(0xC80E);//NOT USEWriteCMD(0xC000);//1.0MHz,2.2V}void main(){Init_RF12();uart0_init();//INT0_init();delay_us(10);#asm("sei");while(1){if(flag1){#asm("cli");LED=0;flag1=0;WriteCMD(0x8228); //OPEN PAdelay_us(4);WriteCMD(0x8238);#asm("nop");#asm("nop");WriteFSKbyte(mes,i+4);delay_ms(10);WriteCMD(0x8208); //CLOSE PALED=1;i=0;#asm("sei");}WriteCMD(0x82D8);WriteCMD(0xCA83);if(!nIRQ){ LED=0;//WriteCMD(0xCA83);RF_RXBUF[t++]=RF12_RDFIFO();//tempdata=RF_RXBUF[t--];//if(tempdata=='a')if(RF_RXBUF[t-1]==0x61){flag2=0;WriteCMD(0xCA80);for(j=0;j<t-1;j++){while(!(UCSR0A&(0x20)));UDR0=RF_RXBUF[j];}t=0;LED=1;// #asm("sei");}} /**/// }//WriteCMD(0x82D8);}}void uart0_init(void){UCSR0A = 0x00; //使用波特率不倍增,不使用多从机模式UCSR0C = 0x06; //异步串口模式,禁止奇偶校验,1位停止位,8-bit帧模式UBRR0L = 51; //设置波特率,9600UBRR0H = 0;UCSR0B = 0x98; //允许接收发送允许接收中断}void Write0(void){SDI=0; //SDI=0#asm("nop");SCK=0; //SCK=0#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");SCK=1; //SCK=1 #asm("nop");}void Write1(void){SDI=1; //SDI=1#asm("nop");SCK=0; //SCK=0#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");#asm("nop");SCK=1; //SCK=1 #asm("nop");}void WriteCMD(uint CMD){uchar n=16;SCK=0;nSEL=0;while(n--){if(CMD&0x8000)Write1();elseWrite0();CMD=CMD<<1;}SCK=0;nSEL=1;}void WriteFSKbyte(uchar *ptr,uchar num){uchar i=0;uchar RGIT=0;uint temp=0xB800;for(i=0;i<num;i++){temp=*(ptr++)+0xB800;Loop:SCK=0;nSEL=0;SDI=0;SCK=1;if(SDO){RGIT=1;}else{RGIT=0;SCK=0;SDI=1;nSEL=1;if(RGIT==0){goto Loop;}else{RGIT=0;WriteCMD(temp);//while(!(UCSR0A&(0x20)));//UDR0=temp;}}}interrupt [USART_RXC] void usart_rx_isr(void) { uchar data;while(!(UCSR0A&(0x80)));data=UDR0;mes[(i++)+4]=data;if(data=='a'){flag1=1;}}// INT0/*interrupt [EXT_INT0] void ext_int0_isr(void) {flag2=1;}void INT0_init(void){EICRA=0x00; // INT0?????EIMSK=0x01; //int0????EIFR=0x01; // ??INT0????? ???0}*/uchar RF12_RDFIFO(void){uchar i,Result;SCK=0;nSEL=0;for(i=0;i<16;i++){ //skip status bitsSCK=1;#asm("nop");#asm("nop");SCK=0;#asm("nop");#asm("nop");}Result=0;for(i=0;i<8;i++){ //read fifo data byte Result=Result<<1;if(SDO){Result|=1;}SCK=1;#asm("nop");#asm("nop");SCK=0;#asm("nop");#asm("nop");}nSEL=1;return(Result);}。