A7139 拥有电磁波唤醒以及10mW的发射功率,非常容易实现长距离通信,目前测试有障碍物可以轻松达到300m以上.
通过1下午的调试,终于完成了无线收发,程序分为3层,A7139.c为底层,USER_RF.C为驱动层,main.c为应用层
底层完成硬件操作,但是收发数据包最大只能是64B,驱动层将数据进行分包以及接受,可以实现任意大小的数据包收发.
目前并没有实现低功耗以及电磁波唤醒,只是简单的数据通信.
底层代码
/************************************************************************************************************* * 文件名: A7139.c * 功能: STM32 A7139驱动 * 作者: [email protected] * 创建时间: 2015-07-19 * 最后修改时间:2015-07-19 * 详细: A7139驱动 *************************************************************************************************************/ #include "SYSTEM.H" #include "GPIO_INIT.H" #include "a7139.H" //设备硬件ID #define A7139_DEVER_ID 0xAA71 //晶振寄存器,用于设置晶振以及PAGE地址 //用于缓存寄存器7的值 static u16 A7139_CRYSTAL_REG = 0x18; //单包数据发送超时时间 #define A7139_SEND_TIME_OUT 5 //单位10ms //接收中断回调函数 void(*pRxCallBack)() = NULL; //调试开关 #define A7193_DBUG 1 #if A7193_DBUG #include "system.h" #define A7193_debug(format,...) uart_printf(format,##__VA_ARGS__) #else #define A7193_debug(format,...) // #endif //A7193_DBUG //寄存器配置 typedef struct { u16 SCLOCK; //系统时钟寄存器 u16 PLL1; //PLL1 u16 PLL2; //PLL2 u16 PLL3; //PLL3 u16 PLL4; //PLL4 u16 PLL5; //PLL5 u16 PLL6; //PLL6 u16 CRYSTAL; //晶振设置 u16 PREG8S; //寄存器组,由CRYSTAL控制切换 u16 PREG9S; //寄存器组,由CRYSTAL控制切换 u16 RX1; //接收设置1 u16 RX2; //接收设置2 u16 ADC; //ADC u16 PIN; //PIN u16 CALIB; //Calibration u16 MODE; //模式控制 } A7139_CONFIG_YPTE; const u16 A7139Config[]= { 0x0021, //SYSTEM CLOCK register, 0x0A21, //PLL1 register, 0xDA05, //PLL2 register, 433.301MHz 0x0000, //PLL3 register, 0x0A20, //PLL4 register, 0x0024, //PLL5 register, 0x0000, //PLL6 register, 0x0001, //CRYSTAL register, 0x0000, //PAGEA, 0x0000, //PAGEB, 0x18D4, //RX1 register, IFBW=100KHz, ETH=1 0x7009, //RX2 register, by preamble 0x4400, //ADC register, 0x0800, //PIN CONTROL register, Use Strobe CMD 0x4845, //CALIBRATION register, 0x20C0 //MODE CONTROL register, Use FIFO mode }; const u16 A7139Config_PageA[]= { 0xF706, //TX1 register, Fdev = 37.5kHz 0x0000, //WOR1 register, 0xF800, //WOR2 register, 0x1107, //RFI register, Enable Tx Ramp up/down 0x0170, //PM register, 0x0201, //RTH register, 0x400F, //AGC1 register, 0x2AC0, //AGC2 register, 0x0041, //GIO register GIO1->WTR GIO2->WTR 0xD281, //CKO register 0x0004, //VCB register, 0x0A21, //CHG1 register, 430MHz 0x0022, //CHG2 register, 435MHz 0x003F, //FIFO register, FEP=63+1=64bytes 0x1507, //CODE register, Preamble=4bytes, ID=4bytes 0x0000 //WCAL register, }; const u16 A7139Config_PageB[]= { 0x0337, //TX2 register, 0x8400, //IF1 register, Enable Auto-IF, IF=200KHz 0x0000, //IF2 register, 0x0000, //ACK register, 0x0000 //ART register, }; /*命令选择 地址格式 BIT7 BIT6-BIT4 BIT3-BIT0 R/W Command Address 0:写 000 读写控制寄存器 1:读 010 读写ID 100 读写FIFO 110 复位FIFO 111 RF复位 */ /************************************************************************************************************************* * 函数 : bool A7139_Init(u32 RF_ID, void(*p)()) * 功能 : A7139初始化 * 参数 : RF_ID:RF ID;*p:回调函数 * 返回 : TRUE:成功;FALSE:失败 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 无 *************************************************************************************************************************/ bool A7139_Init(u32 RF_ID, void(*p)()) { u32 ID; A7139_DisableRxInt(); //关闭接收中断 pRxCallBack = NULL; //回调函数无效 A7139_IO_INIT(); //初始化IO A7139_CS_H(); A7139_CLK_L(); A7139_DIO_H(); A7139_CRYSTAL_REG = 0x0001; A7139_SoftReset(); //软复位 if(A7139_ReadID() != 0) { A7139_SoftReset(); //软复位 } nop;nop; A7139_WriteID(RF_ID); //写入ID if(A7139_ReadID() != RF_ID)//读取ID { A7139_WriteID(RF_ID); } ID = A7139_ReadID(); //读取用户ID if(ID != RF_ID) { A7193_debug("A7139 初始化失败,芯片检测错误!\r\n"); return FALSE; } A7193_debug("A7139 用户ID:%X\t硬件ID:%X\r\n",ID, A7139_ReadDeverID()); A7139_Config(); //初始化寄存器 Delay_MS(10); if(A7139_Cal()) { A7193_debug("A7139 初始化失败!\r\n",ID, A7139_ReadDeverID()); return FALSE; } A7193_debug("A7139 初始化成功!\r\n",ID, A7139_ReadDeverID()); A7139_WriteReg(A7139_PLL1, 0x0A21); A7139_WriteReg(A7139_PLL2, 0xDE05); // Frequency = 433.501MHz A7139_WritePageB(A7139_REG9_TX2, 0x035F); // TX power = 18.3dBm pRxCallBack = p; //记录回调函数 A7139_EnableInt(); //开启总中断 return TRUE; } /************************************************************************************************************************* * 函数 : void A7139_WriteByte(u8 data) * 功能 : A7139写一字节 * 参数 : data:需要写入的数据 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 不带片选,最底层写入1B *************************************************************************************************************************/ void A7139_WriteByte(u8 data) { u8 i; for(i = 0;i < 8;i ++) { if(data & 0x80) { A7139_DIO_H(); } else { A7139_DIO_L(); } nop; A7139_CLK_H(); data <<= 1; nop; A7139_CLK_L(); } } /************************************************************************************************************************* * 函数 : u8 A7139_ReadByte(void) * 功能 : A7139读取一字节 * 参数 : 无 * 返回 : 读取的数据 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 不带片选,最底层读取1B *************************************************************************************************************************/ u8 A7139_ReadByte(void) { u8 i; u8 data = 0; for(i = 0;i < 8;i ++) { A7139_CLK_H(); data <<= 1; if(A7139_DIO_IN()) { data |= 1; } nop; A7139_CLK_L(); nop;nop; } return data; } /************************************************************************************************************************* * 函数 : u16 A7139_ReadReg(A7139_CREG RegAddr) * 功能 : 读取控制寄存器 * 参数 : RegAddr:寄存器地址 * 返回 : 寄存器值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : *************************************************************************************************************************/ u16 A7139_ReadReg(A7139_CREG RegAddr) { u16 data; RegAddr &= 0x0f; //地址限制为BIT0-BIT3 RegAddr |= A7139_RCR_CMD; //读命令 A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(RegAddr); A7139_InMode(); //输入 data = A7139_ReadByte(); data <<= 8; data |= A7139_ReadByte(); A7139_CS_H(); return data; } /************************************************************************************************************************* * 函数 : void A7139_WriteReg(u8 RegAddr, u16 data) * 功能 : 写入控制寄存器 * 参数 : RegAddr:寄存器地址,data:要写入的值 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : *************************************************************************************************************************/ void A7139_WriteReg(A7139_CREG RegAddr, u16 data) { RegAddr &= 0x0f; //地址限制为BIT0-BIT3 RegAddr |= A7139_WCR_CMD; //写命令 A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(RegAddr); A7139_WriteByte(data>>8); A7139_WriteByte(data); A7139_CS_H(); } /************************************************************************************************************************* * 函数 : u16 A7139_ReadPageA(A7139_PAGE_A RegAddr) * 功能 : 读取控制寄存器组寄存器A * 参数 : RegAddr:寄存器组地址 * 返回 : 寄存器值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 寄存器组8 *************************************************************************************************************************/ u16 A7139_ReadPageA(A7139_PAGE_A RegAddr) { u16 data; //先选择组 if((A7139_CRYSTAL_REG>>12) != RegAddr) //08寄存器组设置不对,需要重新设置 { A7139_CRYSTAL_REG &= ~(0xf << 12); //清除寄存器组8地址 A7139_CRYSTAL_REG |= (RegAddr << 12); //存储寄存器组8地址 A7139_WriteReg(A7139_CRYSTAL, A7139_CRYSTAL_REG); //重新设置此存器组8地址 } data = A7139_ReadReg(A7139_PREG8S);//读取寄存器组数据 return data; } /************************************************************************************************************************* * 函数 : void A7139_WritePageA(A7139_PAGE_A RegAddr, u16 data) * 功能 : 写入控制寄存器组寄存器 * 参数 : RegAddr:寄存器组地址,data:寄存器值 * 返回 : 寄存器值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 寄存器组8 *************************************************************************************************************************/ void A7139_WritePageA(A7139_PAGE_A RegAddr, u16 data) { u8 temp; //先选择组 if((A7139_CRYSTAL_REG>>12) != RegAddr) //08寄存器组设置不对,需要重新设置 { A7139_CRYSTAL_REG &= ~(0xf << 12); //清除寄存器组8地址 A7139_CRYSTAL_REG |= (RegAddr << 12); //存储寄存器组8地址 A7139_WriteReg(A7139_CRYSTAL, A7139_CRYSTAL_REG); //重新设置此存器组8地址 } A7139_WriteReg(A7139_PREG8S, data); //设置寄存器组数据 } /************************************************************************************************************************* * 函数 : u16 A7139_ReadPageB(A7139_PAGE_B RegAddr) * 功能 : 读取控制寄存器组寄存器 * 参数 : RegAddr:寄存器组地址 * 返回 : 寄存器值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 寄存器组9 *************************************************************************************************************************/ u16 A7139_ReadPageB(A7139_PAGE_B RegAddr) { u16 data; if(((A7139_CRYSTAL_REG >> 7) & 0x7) != RegAddr) //09寄存器组设置不对,需要重新设置 { A7139_CRYSTAL_REG &= ~(0x7 << 7); //清除寄存器组9地址 A7139_CRYSTAL_REG |= ((RegAddr&0x7) << 7); //存储寄存器组9地址 A7139_WriteReg(A7139_CRYSTAL, A7139_CRYSTAL_REG); //重新设置此存器组9地址 } data = A7139_ReadReg(A7139_PREG9S); //读取寄存器组数据 return data; } /************************************************************************************************************************* * 函数 : void A7139_WritePageB(A7139_PAGE_B RegAddr, u16 data) * 功能 : 写入控制寄存器组寄存器 * 参数 : RegAddr:寄存器组地址,data:寄存器值 * 返回 : 寄存器值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 寄存器组9 *************************************************************************************************************************/ void A7139_WritePageB(A7139_PAGE_B RegAddr, u16 data) { //先选择组 if(((A7139_CRYSTAL_REG >> 7) & 0x7) != RegAddr) //09寄存器组设置不对,需要重新设置 { A7139_CRYSTAL_REG &= ~(0x7 << 7); //清除寄存器组9地址 A7139_CRYSTAL_REG |= ((RegAddr&0x7) << 7); //存储寄存器组9地址 A7139_WriteReg(A7139_CRYSTAL, A7139_CRYSTAL_REG); //重新设置此存器组9地址 } A7139_WriteReg(A7139_PREG9S, data);//设置寄存器组数据 } /************************************************************************************************************************* * 函数 : u32 A7139_ReadID(void) * 功能 : 读取A7139 ID * 参数 : 无 * 返回 : ID值 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 读取ID *************************************************************************************************************************/ u32 A7139_ReadID(void) { u32 data; u8 i; A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(A7139_RID_CMD); //读ID命令 A7139_InMode(); //输入 data = 0; for(i = 0;i < 4;i ++) { data <<= 8; data |= A7139_ReadByte(); } A7139_CS_H(); return data; } /************************************************************************************************************************* * 函数 : void A7139_WriteID(u32 ID) * 功能 : 设置A7139 ID * 参数 : 无ID值 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 设置ID *************************************************************************************************************************/ void A7139_WriteID(u32 ID) { A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(A7139_WID_CMD); //写ID命令 A7139_WriteByte(ID >> 24); A7139_WriteByte(ID >> 16); A7139_WriteByte(ID >> 8); A7139_WriteByte(ID >> 0); A7139_CS_H(); } /************************************************************************************************************************* * 函数 : void A7139_StrobeCmd(A7139_STROBE_CMD StrobeCmd) * 功能 : A7139发送Strobe命令 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : *************************************************************************************************************************/ void A7139_StrobeCmd(A7139_STROBE_CMD StrobeCmd) { A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(StrobeCmd); A7139_CS_H(); } /************************************************************************************************************************* * 函数 : void A7139_ReadFIFO(u8 *pData, u8 DataLen) * 功能 : A7139读取FIFO * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : *************************************************************************************************************************/ void A7139_ReadFIFO(u8 *pData, u8 DataLen) { u8 i; A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(A7139_RFIFO_CMD); A7139_InMode(); //循环读取FIFO for(i = 0;i < DataLen;i ++) { pData[i] = A7139_ReadByte(); } A7139_CS_H(); } /************************************************************************************************************************* * 函数 : void A7139_WriteFIFO(u8 *pData, u8 DataLen) * 功能 : A7139写FIFO * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : *************************************************************************************************************************/ void A7139_WriteFIFO(u8 *pData, u8 DataLen) { u8 i; A7139_CS_L(); A7139_OutMode(); A7139_WriteByte(A7139_WFIFO_CMD); //循环写入FIFO for(i = 0;i < DataLen;i ++) { A7139_WriteByte(pData[i]); } A7139_CS_H(); } /************************************************************************************************************************* * 函数 : void A7139_Config(void) * 功能 : A7139 配置 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 初始化配置 *************************************************************************************************************************/ void A7139_Config(void) { u8 i; for(i=0; i<8; i++) A7139_WriteReg(i, A7139Config[i]); for(i=10; i<16; i++) A7139_WriteReg(i, A7139Config[i]); for(i=0; i<16; i++) A7139_WritePageA(i, A7139Config_PageA[i]); for(i=0; i<5; i++) A7139_WritePageB(i, A7139Config_PageB[i]); } /************************************************************************************************************************* * 函数 : bool A7139_SendData(u8 pData[64], bool isClear) * 功能 : A7139 发送数据 * 参数 : pData:发送数据缓冲区,大小固定为64字节;isClear:是否清除发送缓冲区 * 返回 : TRUE:发送成功;FALSE:发送失败 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : A7139 发送数据 *************************************************************************************************************************/ bool A7139_SendData(u8 pData[64], bool isClear) { u8 retry = 0; if(isClear) //需要清除发送缓冲区 { A7139_StrobeCmd(A7139_STBY_CMD); A7139_DelayMS(2); A7139_StrobeCmd(A7139_RESTFIFO_CMD); A7139_DelayMS(1); } A7139_WriteFIFO(pData,64); //将数据块写入A7139内部FIFO缓存区 A7139_StrobeCmd(A7139_TX_CMD); //发送命令牌,使A7139进入“发送”状态,其后A7139会将数据打包后自动发送 A7139_DelayMS(1); while(A7139_GIO1_IN()) { A7139_DelayMS(10); retry ++; if(retry == (A7139_SEND_TIME_OUT+1)) return FALSE; } return TRUE; } /************************************************************************************************************************* * 函数 : bool A7139_WaitRxData(u8 pData[64], u16 TimeOut) * 功能 : A7139 接收数据 * 参数 : pData:接收数据缓冲区,大小固定为64字节;TimeOut:等待时间,单位10ms,如果为0则一直等待 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : A7139 接收函数 *************************************************************************************************************************/ bool A7139_WaitRxData(u8 pData[64], u16 TimeOut) { u16 retry = 0; A7139_StrobeCmd(A7139_IDLE_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_RESRFIFO_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_STBY_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_RX_CMD); A7139_DelayMS(1); while(A7139_GIO1_IN()) { A7139_DelayMS(10); if(TimeOut > 0) { retry ++; if(retry > (TimeOut+1)) return FALSE; } } //数据接收完成 A7139_ReadFIFO(pData,64); //从A7139内部FIFO缓存区读取数据块 return TRUE; } /************************************************************************************************************************* * 函数 : bool A7139_RxMode(void) * 功能 : A7139 进入接收模式 * 参数 : 无 * 返回 : TRUE:成功;FALSE:失败 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : A7139 进入接收模式 *************************************************************************************************************************/ bool A7139_RxMode(void) { u16 retry = 0; A7139_StrobeCmd(A7139_IDLE_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_RESRFIFO_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_STBY_CMD); A7139_DelayMS(1); A7139_StrobeCmd(A7139_RX_CMD); A7139_DelayMS(1); if(A7139_GIO1_IN()) return TRUE; else return FALSE; } /************************************************************************************************************************* * 函数 : void A7139_SetFreq(float RfFreq) * 功能 : A7139 配置RF频率 * 参数 : rfFreq:RF频率,单位MHz * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 初始化配置 *************************************************************************************************************************/ void A7139_SetFreq(float RfFreq) { float divFreq = RfFreq / 12.800f; u8 intFreq = (u8)(divFreq); //integer part float fltFreq = divFreq - intFreq * 1.000f; //fraction part u16 fpFreg = (u16)(fltFreq * 65536); //FP register val u16 orgVal; A7139_StrobeCmd(A7139_STBY_CMD); //enter stand-by mode //AFC[15:15] = 0 orgVal = A7139Config[A7139_PLL3] & 0x7FFF; A7139_WriteReg(A7139_PLL3,orgVal); //RFC[15:12] = 0000 orgVal = A7139Config[A7139_PLL6] & 0x0FFF; A7139_WriteReg(A7139_PLL6,orgVal); //MD1[12:12]=0,1 if(RfFreq < 860) //433-510 orgVal = A7139Config[A7139_PLL4] & 0xEFFF; else //868-915 orgVal = A7139Config[A7139_PLL4] | 0x1000; A7139_WriteReg(A7139_PLL4,orgVal); //IP[8:0] = intg orgVal = A7139Config[A7139_PLL1] & 0xFF00; A7139_WriteReg(A7139_PLL1,orgVal|intFreq); //FP[15:0] = fpFreg A7139_WriteReg(A7139_PLL2,fpFreg); //FPA[15:0] = 0x0000 A7139_WritePageB(A7139_REG9_IF2,0x0000); } u8 A7139_Cal(void) { u8 fbcf; //IF Filter u8 vbcf; //VCO Current u8 vccf; //VCO Band u8 tmp; //IF calibration procedure @STB state A7139_WriteReg(A7139_MODE, A7139Config[A7139_MODE] | 0x0802); //IF Filter & VCO Current Calibration do{ tmp = A7139_ReadReg(A7139_MODE); }while(tmp & 0x0802); //for check(IF Filter) tmp = A7139_ReadReg(A7139_CALIB); //fb = tmp & 0x0F; //fcd = (tmp>>11) & 0x1F; fbcf = (tmp>>4) & 0x01; if(fbcf) { return ERR_CAL; } //for check(VCO Current) tmp = A7139_ReadPageA(A7139_REG8_VCO); //vcb = tmp & 0x0F; vccf = (tmp>>4) & 0x01; if(vccf) { return ERR_CAL; } //RSSI Calibration procedure @STB state A7139_WriteReg(A7139_ADC, 0x4C00); //set ADC average=64 A7139_WritePageA(A7139_REG8_WOR2, 0xF800); //set RSSC_D=40us and RS_DLY=80us A7139_WritePageA(A7139_REG8_TX1, A7139Config_PageA[A7139_REG8_TX1] | 0xE000); //set RC_DLY=1.5ms A7139_WriteReg(A7139_MODE, A7139Config[A7139_MODE] | 0x1000); //RSSI Calibration do{ tmp = A7139_ReadReg(A7139_MODE); }while(tmp & 0x1000); A7139_WriteReg(A7139_ADC, A7139Config[A7139_ADC]); A7139_WritePageA(A7139_REG8_WOR2, A7139Config_PageA[A7139_REG8_WOR2]); A7139_WritePageA(A7139_REG8_TX1, A7139Config_PageA[A7139_REG8_TX1]); //VCO calibration procedure @STB state A7139_WriteReg(A7139_MODE, A7139Config[A7139_MODE] | 0x0004); //VCO Band Calibration do{ tmp = A7139_ReadReg(A7139_MODE); }while(tmp & 0x0004); //for check(VCO Band) tmp = A7139_ReadReg(A7139_CALIB); //vb = (tmp >>5) & 0x07; vbcf = (tmp >>8) & 0x01; if(vbcf) { return ERR_CAL; } return 0; } //PC4接收中断程序 void EXTI4_IRQHandler(void) { if(pRxCallBack != NULL) { pRxCallBack(); //调用回调函数 } EXTI_ClearInt(4); //清除中断 }
/************************************************************************************************************* * 文件名: A7139.h * 功能: STM32 A7139驱动 * 作者: [email protected] * 创建时间: 2015-07-19 * 最后修改时间:2015-07-19 * 详细: A7139驱动 *************************************************************************************************************/ #ifndef __A7139_H__ #define __A7139_H__ #include "system.h" //三线spi #define A7139_DIO_OUT PAout(7) #define A7139_DIO_IN() PAin(7) #define A7139_CS PAout(4) #define A7139_CLK PAout(6) #define A7139_OutMode() GPIOx_OneInit(GPIOA,7,OUT_PP,SPEED_50M) #define A7139_InMode() GPIOx_OneInit(GPIOA,7,IN_IPU,IN_IN) #define A7139_GIO1 PCin(4) #define A7139_IO_INIT() DeviceClockEnable(DEV_GPIOA,ENABLE);/*使能GPIOA时钟*/ GPIOx_Init(GPIOA,BIT4|BIT6|BIT7, OUT_PP, SPEED_50M); DeviceClockEnable(DEV_GPIOC,ENABLE);/*使能GPIOC时钟*/ GPIOx_Init(GPIOC,BIT4, IN_IPT, IN_IN); //接口 //DIO #define A7139_DIO_H() (A7139_DIO_OUT=1) //输出1 #define A7139_DIO_L() (A7139_DIO_OUT=0) //输出0 #define A7139_CS_H() (A7139_CS=1) #define A7139_CS_L() (A7139_CS=0) #define A7139_CLK_H() (A7139_CLK=1) #define A7139_CLK_L() (A7139_CLK=0) #define A7139_GIO1_IN() (A7139_GIO1) //中断 #define A7139_EnableInt() NVIC_IntEnable(IRQ_EXTI4,ENABLE) //总中断开启 #define A7139_DisableInt() NVIC_IntEnable(IRQ_EXTI4,DISABLE) //总中断关闭 #define A7139_EnableRxInt() EXTI_IntConfig(GPIO_C,4,NegEdge) //下降沿触发中断 #define A7139_DisableRxInt() EXTI_IntConfig(GPIO_C,4,OFF_INT) //关闭触发中断 //清除接收中断 #define A7139_ClearRxInt() EXTI_ClearInt(4) //清除中断 //控制寄存器 typedef enum { A7139_SCLOCK = 0x00, //系统时钟寄存器 A7139_PLL1 = 0x01, //PLL1 A7139_PLL2 = 0x02, //PLL2 A7139_PLL3 = 0x03, //PLL3 A7139_PLL4 = 0x04, //PLL4 A7139_PLL5 = 0x05, //PLL5 A7139_PLL6 = 0x06, //PLL6 A7139_CRYSTAL = 0x07, //晶振设置 A7139_PREG8S = 0x08, //寄存器组,由CRYSTAL控制切换 A7139_PREG9S = 0x09, //寄存器组,由CRYSTAL控制切换 A7139_RX1 = 0x0A, //接收设置1 A7139_RX2 = 0x0B, //接收设置2 A7139_ADC = 0x0C, //ADC A7139_PIN = 0x0D, //PIN A7139_CALIB = 0x0E, //Calibration A7139_MODE = 0x0F, //模式控制 }A7139_CREG; //控制寄存器组A typedef enum { //寄存器8 A7139_REG8_TX1 = 0, //addr8 page0, A7139_REG8_WOR1 = 1, //addr8 page1, A7139_REG8_WOR2 = 2, //addr8 page2, A7139_REG8_RF = 3, //addr8 page3, A7139_REG8_POWER = 4, //addr8 page4, A7139_REG8_AGCRC = 5, //addr8 page5, A7139_REG8_AGCCON1 = 6, //addr8 page6, A7139_REG8_AGCCON2 = 7, //addr8 page7, A7139_REG8_GPIO = 8, //addr8 page8, A7139_REG8_CKO = 9, //addr8 page9, A7139_REG8_VCO = 10, //addr8 page10, A7139_REG8_CHG1 = 11, //addr8 page11, A7139_REG8_CHG2 = 12, //addr8 page12, A7139_REG8_FIFO = 13, //addr8 page13, A7139_REG8_CODE = 14, //addr8 page14, A7139_REG8_WCAL = 15, //addr8 page15, }A7139_PAGE_A; //控制寄存器组B typedef enum { //寄存器9 A7139_REG9_TX2 = 0, //addr9 page0, A7139_REG9_IF1 = 1, //addr9 page1, A7139_REG9_IF2 = 2, //addr9 page2, A7139_REG9_ACK = 3, //addr9 page3, A7139_REG9_ART = 4, //addr9 page4, }A7139_PAGE_B; //Strobe命令 typedef enum { A7139_WCR_CMD = 0x00, //写控制寄存器 A7139_RCR_CMD = 0x80, //读控制寄存器 A7139_WID_CMD = 0x20, //写ID A7139_RID_CMD = 0xA0, //读ID A7139_WFIFO_CMD = 0x40, //写FIFO A7139_RFIFO_CMD = 0xC0, //读FIFO A7139_RESRF_CMD = 0x70, //复位RF A7139_RESTFIFO_CMD = 0x60, //复位发送FIFO A7139_RESRFIFO_CMD = 0xE0, //复位接收FIFO A7139_SLEEP_CMD = 0x10, //SLEEP模式 A7139_IDLE_CMD = 0x12, //IDLE模式 A7139_STBY_CMD = 0x14, //Standby模式 A7139_PLL_CMD = 0x16, //PLL模式 A7139_RX_CMD = 0x18, //RX模式 A7139_TX_CMD = 0x1A, //TX模式 A7139_TSLEEP_CMD = 0x1C, //Deep sleep 模式 三态 A7139_PSLEEP_CMD = 0x1F, //Deep sleep 模式 上拉 }A7139_STROBE_CMD; #define ERR_PARAM 0x01 #define ERR_PLATFORM 0x02 #define ERR_UNK 0x03 #define ERR_CAL 0x04 #define ERR_TMO 0xFF #define ERR_RCOSC_CAL 0x04 #define OK_RCOSC_CAL 0x05 #define ERR_GET_RSSI 0x00 //宏定义接口 #ifdef _UCOS_II_ #include "ucos_ii.h" #define A7139_DelayMS(x) OSTimeDlyHMSM(0,0,0,x) //ms延时,最大999ms #else #include "delay.h" #define A7139_DelayMS(x) Delay_MS(x) #endif //相关函数 void A7139_SoftReset(void); //A7139软复位 bool A7139_Init(u32 RF_ID, void(*p)()); //A7139 初始化 void A7139_WriteReg(A7139_CREG RegAddr, u16 data); //写入控制寄存器 u16 A7139_ReadReg(A7139_CREG RegAddr); //读取控制寄存器 u32 A7139_ReadID(void); //读取A7139 ID void A7139_WriteID(u32 ID); //设置A7139 ID u16 A7139_ReadPageA(A7139_PAGE_A RegAddr); //读取控制寄存器组寄存器A void A7139_WritePageA(A7139_PAGE_A RegAddr, u16 data);//写入控制寄存器组寄存器A u16 A7139_ReadPageB(A7139_PAGE_B RegAddr); //读取控制寄存器组寄存器B void A7139_WritePageB(A7139_PAGE_B RegAddr, u16 data);//写入控制寄存器组寄存器B void A7139_RestRxFIFO(void); //A7139复位接收FIFO指针 void A7139_RestTxFIFO(void); //A7139复位发送FIFO指针 void A7139_ReadFIFO(u8 *pData, u8 DataLen); //A7139读取FIFO void A7139_WriteFIFO(u8 *pData, u8 DataLen); //A7139写FIFO void A7139_StrobeCmd(A7139_STROBE_CMD StrobeCmd); //A7139发送Strobe命令 void A7139_Config(void); //配置A7139 void A7139_SetFreq(float RfFreq); //A7139 配置RF频率 bool A7139_SendData(u8 pData[64], bool isClear); //A7139发送数据 bool A7139_WaitRxData(u8 pData[64], u16 TimeOut); //等待接收数据 bool A7139_RxMode(void); //A7139进入接收模式 #define A7139_ReadDeverID() (A7139_ReadPageB(A7139_REG9_TX2)) //读取设备硬件ID,只读 #define A7139_RestRxFIFO() A7139_StrobeCmd(A7139_RESRFIFO_CMD) //A7139复位接收FIFO指针 #define A7139_RestTxFIFO() A7139_StrobeCmd(A7139_RESTFIFO_CMD) //A7139复位发送FIFO指针 #define A7139_SoftReset() A7139_StrobeCmd(A7139_RESRF_CMD) //A7139软复位 u8 A7139_Cal(void); #endif //A7139
驱动层
/************************************************************************************************************* * 文件名: USER_RF.c * 功能: USER_RF 无线收发应用层 * 作者: [email protected] * 创建时间: 2015-08-16 * 最后修改时间:2015-08-16 * 详细: RF驱动 *************************************************************************************************************/ #include "SYSTEM.H" #include "GPIO_INIT.H" #include "USER_RF.H" #include "A7139.H" #include "stdlib.h" //单包重试次数 #define RF_SEND_RETRY 8 //单包数据超时时间 #define RF_TIME_OUT 20 //单位10ms,总共200ms //单包数据帧数据大小 #define RF_FRAME_DATA_SIZE (RF_HARDWAVE_FRAME_SIZE-9) //响应ACK延时发送 #define RF_ACK_DELAY 8 //单位ms,ACK响应必须延时,否则发送方将无法接收到响应ACK //单包通信数据格式 typedef struct { u16 Addr; u16 PackCnt; u16 AllPackCnt; u8 Len; u8 DataBuff[RF_FRAME_DATA_SIZE]; u16 CRC16; } RF_DATA_FRAME; //底层响应数据包 typedef struct { u16 Addr; u16 PackCnt; u16 AllPackCnt; u8 Ack; u8 DataBuff[RF_FRAME_DATA_SIZE]; u16 CRC16; } RF_ACK_FRAME; //相关RF状态结构 typedef struct { bool NewDataFlag;//接收到新数据 bool BuffFull; //接收Buff满 u8 *pRxBuff; //接收Buff指针 u16 RxBuffSize; //接收缓冲区大小,一帧数据大小 u16 UartRxCnt; //接收数据计数器 u16 RF_Addr; //设备地址 u16 PackCnt; //包计数器 //单包数据缓冲区 u8 TxTempBuff[RF_HARDWAVE_FRAME_SIZE]; u8 RxTempBuff[RF_HARDWAVE_FRAME_SIZE]; } RF_TypeDef; static RF_TypeDef RF_Config; //调试开关 #define USER_RF_DBUG 1 #if USER_RF_DBUG #include "system.h" #define USER_RF_debug(format,...) uart_printf(format,##__VA_ARGS__) #else #define USER_RF_debug(format,...) // #endif //USER_RF_DBUG //CRC校验 static u16 CRC16_Check(u8 *Pushdata,u16 length); /************************************************************************************************************************* * 函数 : bool RF_Init(u32 RF_ID,u16 Addr, u8 *pRxBuff, u16 RxBuffSize, void(*p)()) * 功能 : RF初始化 * 参数 : RF_ID:RF ID,通信通道地址,必须一致才能互相通信;Addr:设备地址,软件定义地址;pRxBuff:接收缓冲区; RxBuffSize:接收缓冲区大小;p:接收中断回调函数 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : 初始化配置0x13547862 *************************************************************************************************************************/ bool RF_Init(u32 RF_ID,u16 Addr, u8 *pRxBuff, u16 RxBuffSize, void(*p)()) { u8 i; RF_Config.RF_Addr = Addr; //记录本机地址 RF_Config.pRxBuff = pRxBuff; //接收缓冲区指针 RF_Config.RxBuffSize = RxBuffSize; //接收缓冲区大小 //初始化硬件 for(i = 0;i < 3;i ++) { if(A7139_Init(RF_ID, p) == TRUE) { USER_RF_debug("[RF]初始化RF硬件成功!\r\n"); break; } else { USER_RF_debug("[RF]初始化RF硬件失败!\r\n"); RF_DelayMS(100); } } if(i == 3) return FALSE; return TRUE; } /************************************************************************************************************************* * 函数 : bool RF_SendData(u8 *pBuff, u16 Len) * 功能 : RF发送数据包 * 参数 : pBuff:发送数据缓冲区;Len:发送数据长度 * 返回 : TRUE:发送成功(成功响应);FALSE:发送失败,响应失败 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-07-19 * 最后修改 : 2015-07-19 * 说明 : RF发送应用层,一包数据可能被分成多包数据进行发送 *************************************************************************************************************************/ bool RF_SendData(u8 *pBuff, u16 Len) { u16 i,j,k; u16 AllPackCnt; u16 PackCnt; u8 EndPackSize = Len % RF_FRAME_DATA_SIZE; RF_DATA_FRAME *pFrame = (RF_DATA_FRAME *)RF_Config.TxTempBuff; RF_ACK_FRAME *pAckFrame = (RF_ACK_FRAME *)RF_Config.RxTempBuff; A7139_DisableRxInt(); //关闭接收中断 //计算总包数量 AllPackCnt = Len / RF_FRAME_DATA_SIZE + ((EndPackSize)?1:0); //最后一包如果为0,则是满数据包 if(EndPackSize == 0) EndPackSize = RF_FRAME_DATA_SIZE; //循环发送数据包 for(PackCnt = 0;PackCnt < AllPackCnt; PackCnt ++) { pFrame->Addr = RF_Config.RF_Addr; //地址 pFrame->PackCnt = PackCnt; //当前数据包计数 pFrame->AllPackCnt = AllPackCnt; //总数据包数量 if(PackCnt == (AllPackCnt-1)) //最后一包数据 { memcpy(pFrame->DataBuff, &pBuff[PackCnt*RF_FRAME_DATA_SIZE], EndPackSize); //复制数据包内容 } else { memcpy(pFrame->DataBuff, &pBuff[PackCnt*RF_FRAME_DATA_SIZE], RF_FRAME_DATA_SIZE);//复制数据包内容 } if(PackCnt == (AllPackCnt-1)) //最后一包数据 { pFrame->Len = EndPackSize; //最后一包数据大小 pFrame->CRC16 = CRC16_Check(RF_Config.TxTempBuff, RF_HARDWAVE_FRAME_SIZE-2);//计算CRC16 for(i = 0;i < (RF_SEND_RETRY+1);i ++) //发送失败则重试 { if(A7139_SendData(RF_Config.TxTempBuff, TRUE) == TRUE) //发送成功 { if(A7139_WaitRxData(RF_Config.RxTempBuff, RF_TIME_OUT) == TRUE) //接收数据成功 { if(pAckFrame->Addr == RF_Config.RF_Addr) //返回的数据地址无误 { if(pAckFrame->CRC16 == CRC16_Check(RF_Config.RxTempBuff, 64-2))//返回的数据校验无误 { if(pAckFrame->Ack) //ACK相应无误 { break; } } } } else { USER_RF_debug("[RF]数据包ACK响应超时!\r\n"); } } else //发送失败则清空发送缓冲区 { USER_RF_debug("[RF]数据包发送超时!\r\n"); A7139_StrobeCmd(A7139_RESTFIFO_CMD); OSTimeDlyHMSM(0,0,0,1); } } if(i == (RF_SEND_RETRY+1)) return FALSE; //发送超时 } else //不是最后一包数据 { pFrame->Len = RF_FRAME_DATA_SIZE; //数据包长度 pFrame->CRC16 = CRC16_Check(RF_Config.TxTempBuff, RF_HARDWAVE_FRAME_SIZE-2);//计算CRC16 if(PackCnt == 0) //第一包 { for(i = 0;i < (RF_SEND_RETRY+1);i ++) //发送失败则重试 { if(A7139_SendData(RF_Config.TxTempBuff, TRUE) == TRUE) //发送成功 { if(A7139_WaitRxData(RF_Config.RxTempBuff, RF_TIME_OUT) == TRUE) //接收数据成功 { if(pAckFrame->Addr == RF_Config.RF_Addr) //返回的数据地址无误 { if(pAckFrame->CRC16 == CRC16_Check(RF_Config.RxTempBuff, 64-2))//返回的数据校验无误 { if(pAckFrame->Ack) //ACK相应无误 { break; } } } } else { USER_RF_debug("[RF]数据包ACK响应超时!\r\n"); } } else { USER_RF_debug("[RF]数据包发送超时!\r\n"); A7139_StrobeCmd(A7139_RESTFIFO_CMD); OSTimeDlyHMSM(0,0,0,1); } } if(i == (RF_SEND_RETRY+1)) return FALSE; //发送超时 } else { for(i = 0;i < (RF_SEND_RETRY+1);i ++) //发送失败则重试 { if(A7139_SendData(RF_Config.TxTempBuff, TRUE) == TRUE) //发送成功 { if(A7139_WaitRxData(RF_Config.RxTempBuff, RF_TIME_OUT) == TRUE) //接收数据成功 { if(pAckFrame->Addr == RF_Config.RF_Addr) //返回的数据地址无误 { if(pAckFrame->CRC16 == CRC16_Check(RF_Config.RxTempBuff, 64-2))//返回的数据校验无误 { if(pAckFrame->Ack) //ACK相应无误 { break; } } } } else { USER_RF_debug("[RF]数据包ACK响应超时!\r\n"); } } else //发送失败则清空发送缓冲区 { USER_RF_debug("[RF]数据包发送超时!\r\n"); A7139_StrobeCmd(A7139_RESTFIFO_CMD); OSTimeDlyHMSM(0,0,0,1); } } if(i == (RF_SEND_RETRY+1)) return FALSE; //发送超时 } } } return TRUE; } /************************************************************************************************************************* * 函数 : void RF_ClearRxCnt(void) * 功能 : 清除接收数据计数器 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : RF中断接收数据计数器 *************************************************************************************************************************/ void RF_ClearRxCnt(void) { RF_Config.BuffFull = FALSE; //清除接收缓冲区满标记 RF_Config.NewDataFlag = FALSE; //清除新数据标记 RF_Config.UartRxCnt = 0; //接收数据大小为0 RF_Config.PackCnt = 0; //包计数器为0 } /************************************************************************************************************************* * 函数 : bool RF_RxMode(void) * 功能 : RF进入接收模式 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : RF接收模式,会使用接收中断接收所有的数据,数据接收完毕后会提示 *************************************************************************************************************************/ void RF_RxMode(void) { A7139_RxMode(); //A7139进入接收模式 A7139_ClearRxInt(); //清除接收中断 A7139_EnableRxInt(); //开启接收中断 } /************************************************************************************************************************* * 函数 : bool RF_GetDataFlag(void) * 功能 : RF新数据标志 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : 收到新数据包后有效 *************************************************************************************************************************/ bool RF_GetDataFlag(void) { return ((RF_Config.NewDataFlag) && (RF_Config.UartRxCnt))?TRUE:FALSE; } /************************************************************************************************************************* * 函数 : u16 RF_GetRxCnt(void) * 功能 : RF获取接收数据长度 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : 获取新数据长度 *************************************************************************************************************************/ u16 RF_GetRxCnt(void) { return RF_Config.UartRxCnt; } /************************************************************************************************************************* * 函数 : void RF_GetRxData(u8 *pDataBuff, u16 len) * 功能 : 读取接收到的数据 * 参数 : pDataBuff:数据缓冲区;len:需要读取的数量 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : 必须接收到数据后读取才有效 数据读取后请清除接收计数器 *************************************************************************************************************************/ void RF_GetRxData(u8 *pDataBuff, u16 len) { if(len > RF_Config.RxBuffSize) len = RF_Config.RxBuffSize; //防止超出缓冲区大小 memcpy(pDataBuff, RF_Config.pRxBuff, len); } /************************************************************************************************************************* * 函数 : void RF_RxTask(void) * 功能 : RF数据接收线程 * 参数 : 无 * 返回 : 无 * 依赖 : 底层宏定义 * 作者 : [email protected] * 时间 : 2015-08-16 * 最后修改 : 2015-08-16 * 说明 : 如果没有使用ucOS请将次函数在接收中断中调用,如果使用了ucos,请在接收线程中调用,接收线程使用接收中断进行 唤醒,并且接收线程拥有较高的优先级,否则响应可能会超时,导致通信不稳定 *************************************************************************************************************************/ void RF_RxTask(void) { static RF_DATA_FRAME *pFrame; static RF_ACK_FRAME *pAckFrame; static u16 crc16; A7139_DisableRxInt(); //关闭接收中断 if(A7139_GIO1_IN() == 0) //状态有效 { pFrame = (RF_DATA_FRAME *)RF_Config.RxTempBuff; pAckFrame = (RF_ACK_FRAME *)RF_Config.TxTempBuff; A7139_ReadFIFO(RF_Config.RxTempBuff,RF_HARDWAVE_FRAME_SIZE); //从A7139内部FIFO缓存区读取数据块 //地址必须一致,并且crc校验无误,包计数有效 if((pFrame->Addr == RF_Config.RF_Addr) && (pFrame->PackCnt < pFrame->AllPackCnt)) { crc16 = CRC16_Check(RF_Config.RxTempBuff, RF_HARDWAVE_FRAME_SIZE-2); if(crc16 == pFrame->CRC16) { //响应 pAckFrame->Addr = pFrame->Addr; //地址 pAckFrame->AllPackCnt = pFrame->AllPackCnt; //总包数量 pAckFrame->PackCnt = pFrame->PackCnt; //当前包计数器 pAckFrame->Ack = 0x01; //响应有效 pAckFrame->CRC16 = CRC16_Check(RF_Config.TxTempBuff, RF_HARDWAVE_FRAME_SIZE-2);//计算校验 RF_DelayMS(RF_ACK_DELAY); //发送ACK延时 A7139_SendData(RF_Config.TxTempBuff, TRUE); //发送ACK数据 USER_RF_debug("[RF]收到数据包有效!\r\n"); if(RF_Config.PackCnt == pFrame->PackCnt) //数据包计数器一致才有效,防止重复 { if((RF_Config.UartRxCnt + pFrame->Len) < RF_Config.RxBuffSize) //接收缓冲区没有满 { memcpy(&RF_Config.pRxBuff[RF_Config.UartRxCnt], pFrame->DataBuff, pFrame->Len); //复制数据到接收缓冲区 RF_Config.UartRxCnt += pFrame->Len; //记录数据总长度 } else { RF_Config.BuffFull = TRUE; //数据接收缓冲区满了 } RF_Config.PackCnt ++; //偏移到下一包数据 } if(RF_Config.PackCnt >= pFrame->AllPackCnt) //数据接收完毕 { RF_Config.NewDataFlag = TRUE; //数据接收完毕,有新数据可以读取了 } } else { //响应 pAckFrame->Addr = pFrame->Addr; //地址 pAckFrame->AllPackCnt = pFrame->AllPackCnt; //总包数量 pAckFrame->PackCnt = pFrame->PackCnt; //当前包计数器 pAckFrame->Ack = 0x00; //响应无效 pAckFrame->CRC16 = CRC16_Check(RF_Config.TxTempBuff, RF_HARDWAVE_FRAME_SIZE-2);//计算校验 RF_DelayMS(RF_ACK_DELAY); //发送ACK延时 A7139_SendData(RF_Config.TxTempBuff, TRUE); //发送NAK数据 USER_RF_debug("[RF]收到数据包无效!\r\n"); } } } RF_RxMode(); //重新进入接收模式 } //CRC校验 static u16 CRC16_Check(u8 *Pushdata,u16 length) { u16 Reg_CRC=0xffff; u8 Temp_reg=0x00; u16 i,j; for( i = 0; i<length; i ++) { Reg_CRC^= *Pushdata++; for (j = 0; j<8; j++) { if (Reg_CRC & 0x0001) Reg_CRC=Reg_CRC>>1^0xA001; else Reg_CRC >>=1; } } return (Reg_CRC); }
/************************************************************************************************************* * 文件名: USER_RF.c * 功能: USER_RF 无线收发应用层 * 作者: [email protected] * 创建时间: 2015-08-16 * 最后修改时间:2015-08-16 * 详细: RF驱动 *************************************************************************************************************/ #ifndef __USER_RF_H__ #define __USER_RF_H__ #include "system.h" //相关定义 #define RF_HARDWAVE_FRAME_SIZE 64 //RF硬件一包数据大小 //宏定义接口 #ifdef _UCOS_II_ #include "ucos_ii.h" #define RF_DelayMS(x) OSTimeDlyHMSM(0,0,0,x) //ms延时,最大999ms #else #include "delay.h" #define RF_DelayMS(x) Delay_MS(x) #endif bool RF_Init(u32 RF_ID,u16 Addr, u8 *pRxBuff, u16 RxBuffSize, void(*p)()); //RF初始化 bool RF_SendData(u8 *pBuff, u16 Len); //RF发送数据包 void RF_RxTask(void); //RF接收数据处理,在接收中断或接收线程中进行调用 void RF_RxMode(void); //RF进入接收模式 bool RF_GetDataFlag(void); //RF新数据标志 u16 RF_GetRxCnt(void); //获取新数据长度 void RF_GetRxData(u8 *pDataBuff, u16 len); //读取新数据 void RF_ClearRxCnt(void); //清除接收计数器 #endif //__USER_RF_H__
//应用层发送
//任务1: //系统任务 void TaskSystem(void *pdata) { u8 i; u8 TxBuff[64]; u8 RxBuff[64]; //RF_ACK_FRAME *pAckFrame = (RF_ACK_FRAME *)TxBuff; s16 Temp; u16 Humi; u16 Voltage; u16 len; DeviceClockEnable(GPIO_A, ENABLE); GPIOx_Init(GPIOA, BIT12, OUT_PP, SPEED_10M); PAout(12) = 1; //启动A7139电源 //初始化相关线程 OSTaskCreate(TaskLED, (void *)0,&TASK_LED_STK[LED_STK_SIZE-1], LED_TASK_Prio); //LED OSTimeDlyHMSM(0,0,0,10); //读取电源电压 ADC1_Init(); //初始化ADC1 ADC1_PowerUP(); DeviceClockEnable(DEV_GPIOA, ENABLE);/*使能PA时钟*/ GPIOx_Init(GPIOA, BIT1, IN_AIN, IN_IN);/*/PA1模拟输入*/ Voltage = GetDCVoltage()/10; uart_printf("电池电压:%d.%02dV\r\n",Voltage/100,Voltage%100); //初始化A7139 if(RF_Init(0x13547862,1, TempBuff, 2048-1, ThaskCallBack) == TRUE) { for(i = 0;i < 10;i ++) { LED_FLASH(); OSTimeDlyHMSM(0,0,0,10); } LED_OFF(); } else //初始化失败 { } if(1) //发送方 { //初始化并读取温湿度 AM2305_Init(); for(i = 0;i < 10;i ++) { if(AM2305_ReadData(&Temp,&Humi) == TRUE) { uart_printf("温度:%d.%d℃ \t 湿度:%d.%d%%RH\r\n", Temp / 10, abs(Temp) % 10, Humi/10, Humi%10); break; } OSTimeDlyHMSM(0,0,1,0); } if(i == 10) //读取温湿度失败 { } len = sprintf((char *)TempBuff, "电池电压:%d.%02dV\t温度:%d.%d℃\t 湿度:%d.%d%%RH\r\n",Voltage/100,Voltage%100, Temp / 10, abs(Temp) % 10, Humi/10, Humi%10); //发送数据 uart_printf("发送数据:"); for(i = 0;i < 3;i ++) { LED_ON(); if(RF_SendData(TempBuff, len) == TRUE) { uart_printf("成功!\r\n"); break; } } if(i == 3) //发送失败 { uart_printf("失败!\r\n"); } LED_OFF(); //数据发送完成,休眠 PAout(12) = 0; //关闭电源 uart_printf("采集发送完成,关闭电源,休眠!\r\n"); OSTimeDlyHMSM(0,0,0,100); EXTI_IntConfig(GPIO_A,0,PosEdge); //PA0上升沿中断,用于唤醒单片机 SYSTEM_Standby(); } else //接收方 { RF_RxMode(); //进入接收模式 RF_ClearRxCnt(); //清除接收缓冲区 }
应用层接收
//A7139接收中断回调函数,用于唤醒接收线程 void ThaskCallBack(void) { OSTaskResume(LED_TASK_Prio); //唤醒数据接收线程 }
//任务1: //系统任务 void TaskSystem(void *pdata) { u8 i; u8 TxBuff[64]; u8 RxBuff[64]; //RF_ACK_FRAME *pAckFrame = (RF_ACK_FRAME *)TxBuff; s16 Temp; u16 Humi; u16 Voltage; u16 len; DeviceClockEnable(GPIO_A, ENABLE); GPIOx_Init(GPIOA, BIT12, OUT_PP, SPEED_10M); PAout(12) = 1; //启动A7139电源 //初始化相关线程 OSTaskCreate(TaskLED, (void *)0,&TASK_LED_STK[LED_STK_SIZE-1], LED_TASK_Prio); //LED OSTimeDlyHMSM(0,0,0,10); //读取电源电压 ADC1_Init(); //初始化ADC1 ADC1_PowerUP(); DeviceClockEnable(DEV_GPIOA, ENABLE);/*使能PA时钟*/ GPIOx_Init(GPIOA, BIT1, IN_AIN, IN_IN);/*/PA1模拟输入*/ Voltage = GetDCVoltage()/10; uart_printf("电池电压:%d.%02dV\r\n",Voltage/100,Voltage%100); //初始化A7139 if(RF_Init(0x13547862,1, TempBuff, 2048-1, ThaskCallBack) == TRUE) { for(i = 0;i < 10;i ++) { LED_FLASH(); OSTimeDlyHMSM(0,0,0,10); } LED_OFF(); } else //初始化失败 { } RF_RxMode(); //进入接收模式 RF_ClearRxCnt(); //清除接收缓冲区 while(1) { OSTimeDlyHMSM(0,0,1,100); IWDG_Feed(); if(RF_GetDataFlag() == TRUE) { len = RF_GetRxCnt(); if(len > 0) { RF_GetRxData(TempBuff, len); //读取数据 TempBuff[len] = 0; uart_printf("%s",(char *)TempBuff); } for(i = 0;i < 10;i ++) { LED_FLASH(); OSTimeDlyHMSM(0,0,0,100); } RF_ClearRxCnt(); //清除接收缓冲区 } } }
//任务2 //负责数据接收 void TaskLED(void *pdata) { while(1) { OSTaskSuspend(LED_TASK_Prio); //挂起数据接收线程 LED_ON(); //收到数据唤醒后,处理数据 RF_RxTask(); //接收数据处理 LED_OFF(); } }
//数据接收采用中断方式,发送都带有ACK,应用层可以无需二次应答.
最终结果,采集温湿度以及电压(单包数据收发)
由于将模块放置在客厅的冰箱内,通信出现了丢包现象,但是通过重发机制,数据顺利接受.
多包数据收发
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-05 04:12:30