A7139 无线通信驱动(STM32)

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

A7139 无线通信驱动(STM32)的相关文章

BLDC 无刷电机FOC驱动 STM32官方培训资料

STM32 PMSM FOC SDK V3.2 培训讲座一http://v.youku.com/v_show/id_XNTM2NjgxMjU2.html?from=s1.8-1-1.2STM32 PMSM FOC SDK V3.2 培训讲座二 http://v.youku.com/v_show/id_XNT ... -87.3.6-2.1-1-1-5-0 STM32 PMSM FOC SDK V3.2 培训讲座三 http://v.youku.com/v_show/id_XNT ... 5.3.

SPI详解

本文的程序是主控室STM32F107各种宏定义和文件会在末尾说明 1. SPI简介 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口.是Motorola首先在其MC68HCXX系列处理器上定义的.SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正

[stm32] NRF24L01+USART搞定有线和无线通信

前言 一般进行远程监控时,2.4G无线通信是充当远程数据传输的一种方法.这时就需要在现场部分具备无线数据发送装置,而在上位机部分由于一般只有串口,所以将采集到的数据送到电脑里又要在上位机端设计一个数据接收的适配器.这里基于stm32分别设计了现场部分和适配器部分,这里只是基本通信功能实现的讲解,一些复杂的技术比如加密.可靠等要根据具体的应用来设计~ 总体说明 这里采用stm32作为MCU,采用nRF24L01作为2.4G通信模块.其中适配器中仅仅采用了USART和NRF24L01两个主要部分,负

[stm32] 一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO

书接上文: 最近在研究用低速.低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果 首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X160), 发现,刷一屏大约要0.8s左右的时间, 具体收录在<1.一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO>中 觉得,如果用72MHz的STM32也许效果会好很多 于是在stm32上做了个类似的版本, 具体收录在<一个简单的stm32vet6驱动的天马4线S

STM32的FSMC总线驱动ili9341,掉电重启无法正常显示的问题

问题描述 通过STM32的FSMC总线驱动ili9341,程序调试和刚下载的时候,显示完全正常.可是就在我掉电关机,重新启动的时候就完全跑飞了.这令我非常疑惑.以下是我的FSMC总线配置程序, static void LCD_FSMC_Config(void) { FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef p; p.FSMC_AddressSetupTime = 0x02; p

炜煌E30 E31微型热敏打印机 STM32 串口驱动

设置为汉字模式 十六进制 命令:1C    26 USART_SendData(USART2,0x1C); while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); USART_SendData(USART2,0x26); while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); USART_OUT(USART2,"秦皇岛燕大滨沅科技发展有限公司\r\n"); 将会看到打印输

基于STM32的RFID射频识别技术 韦根协议C语言驱动解码程序

RFID工作原理 RFID技术的基本工作原理并不复杂:标签进入磁场后,接收解读器发出的射频信号,凭借感应电流所获得的能量发送出存储在芯片中的产品信息(无源标签或被动标签),或者由标签主动发送某一频率的信号(Active Tag,有源标签或主动标签),解读器读取信息并解码后,送至中央信息系统进行有关数据处理. 一套完整的RFID系统, 是由阅读器与电子标签也就是所谓的应答器及应用软件系统三个部份所组成,其工作原理是Reader发射一特定频率的无线电波能量,用以驱动电路将内部的数据送出,此时Read

ecos stm32 步步深入8 - 手工打造串口usart2驱动实验ecos中断

最近忙别的事情,很长时间没碰ecos了,这两天有点空,抽空写个串口驱动玩玩,也验证一下ecos的中断调用.LZ花了两天时间写好这个驱动,中间遇到了几个比较恶心的问题,后来发现是前面的基础没打好,所幸都解决了. 尽管ECOS已经写好了串口的驱动程序,只需要在配置工具中使能即可.不过别人写的毕竟不是自己的,还是自己写的用的方便,这次试验的主要目的是为了调试ecos的中断服务,让串口中断能收发数据. 首先遇到的最大的问题,事实上跟什么串口都没关系,就是debug时一执行task delay,调试程序就

STM32 FSMC LCD 液晶的驱动—ILI9320

STM32 FSMC LCD 液晶的驱动—ILI9320 STM32利用DMA 和FSMC驱动ISSI 25616 外部SRAM 成功