标签:a7139程序 stm32 a7139 a7129 a7109
A7139 拥有电磁波唤醒以及10mW的发射功率,非常容易实现长距离通信,目前测试有障碍物可以轻松达到300m以上.
通过1下午的调试,终于完成了无线收发,程序分为3层,A7139.c为底层,USER_RF.C为驱动层,main.c为应用层
底层完成硬件操作,但是收发数据包最大只能是64B,驱动层将数据进行分包以及接受,可以实现任意大小的数据包收发.
目前并没有实现低功耗以及电磁波唤醒,只是简单的数据通信.
底层代码
/*************************************************************************************************************
* 文件名: A7139.c
* 功能: STM32 A7139驱动
* 作者: cp1300@139.com
* 创建时间: 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:失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:需要写入的数据
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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读取一字节
* 参数 : 无
* 返回 : 读取的数据
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:寄存器地址
* 返回 : 寄存器值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:要写入的值
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:寄存器组地址
* 返回 : 寄存器值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:寄存器值
* 返回 : 寄存器值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:寄存器组地址
* 返回 : 寄存器值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:寄存器值
* 返回 : 寄存器值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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值
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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命令
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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 配置
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:发送失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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则一直等待
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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驱动
* 作者: cp1300@139.com
* 创建时间: 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 无线收发应用层
* 作者: cp1300@139.com
* 创建时间: 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:接收中断回调函数
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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:发送失败,响应失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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)
* 功能 : 清除接收数据计数器
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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进入接收模式
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2015-08-16
* 最后修改 : 2015-08-16
* 说明 : RF接收模式,会使用接收中断接收所有的数据,数据接收完毕后会提示
*************************************************************************************************************************/
void RF_RxMode(void)
{
A7139_RxMode(); //A7139进入接收模式
A7139_ClearRxInt(); //清除接收中断
A7139_EnableRxInt(); //开启接收中断
}
/*************************************************************************************************************************
* 函数 : bool RF_GetDataFlag(void)
* 功能 : RF新数据标志
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2015-08-16
* 最后修改 : 2015-08-16
* 说明 : 收到新数据包后有效
*************************************************************************************************************************/
bool RF_GetDataFlag(void)
{
return ((RF_Config.NewDataFlag) && (RF_Config.UartRxCnt))?TRUE:FALSE;
}
/*************************************************************************************************************************
* 函数 : u16 RF_GetRxCnt(void)
* 功能 : RF获取接收数据长度
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2015-08-16
* 最后修改 : 2015-08-16
* 说明 : 获取新数据长度
*************************************************************************************************************************/
u16 RF_GetRxCnt(void)
{
return RF_Config.UartRxCnt;
}
/*************************************************************************************************************************
* 函数 : void RF_GetRxData(u8 *pDataBuff, u16 len)
* 功能 : 读取接收到的数据
* 参数 : pDataBuff:数据缓冲区;len:需要读取的数量
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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数据接收线程
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 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 无线收发应用层 * 作者: cp1300@139.com * 创建时间: 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,应用层可以无需二次应答.
最终结果,采集温湿度以及电压(单包数据收发)
由于将模块放置在客厅的冰箱内,通信出现了丢包现象,但是通过重发机制,数据顺利接受.
多包数据收发
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:a7139程序 stm32 a7139 a7129 a7109
原文地址:http://blog.csdn.net/cp1300/article/details/47704255