⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 addr.c

📁 freescale crc模块驱动 经调试
💻 C
字号:
/******************************************************************************
 * 源程序文件名: addr.c                                                       *
 * 功能: 向ARM发送遥控器的机器地址                                            *
 * 说明: 本文件包含的子模块有,发送机器地址,接收地址反馈,确认机器地址          *
 ******************************************************************************/

/* 加载头文件 */
# include "addr.h"
# include "machine.h"
# include "lowlevel.h"

/* 从ARM接收地址反馈信息 */
SioAddrPackRecvBuf sioAddrRecvBuf;
unsigned char cSioAddrRecvBufEnd;
unsigned char cRecvAddrBufType;

/* 向ARM发送地址信息及确认信息 */
SioAddrPackSendBuf sioAddrSendBuf;

/* 标志 */
unsigned char cflgSendAddr;                                // 机器地址发送完毕的标志
unsigned char cflgAddrReady;                               // 机器地址处理完毕的标志

/******************************************************************************
 * 函数原型: void InitDataAddr(void);                                         *
 * 功能: 地址传递模块相关数据的初始化                                         *
 * 说明: 无                                                                   *
 ******************************************************************************/
void InitDataAddr (void)
{
	cSioAddrRecvBufEnd = 0;
	cRecvAddrBufType = 0x00;
	cflgSendAddr = 0;
	cflgAddrReady = 0;
}

/******************************************************************************
 * 函数原型: void SendAddrPack(void);                                         *
 * 功能: 向ARM发送遥控器的机器地址                                            *
 * 说明: 1.本函数在地址传递阶段每100ms调用1次                                 *
 *       2.通过UART1口将机器地址传给ARM                                       *
 ******************************************************************************/
void SendAddrPack (void)
{
	KSCRFAddrCode machineAddr;
	machineAddr.addrCode = nMachineAddr;
	sioAddrSendBuf.buf[0] = 0xFF;
	sioAddrSendBuf.buf[1] = 0xFF;
	sioAddrSendBuf.buf[2] = ADDRSioTypeSendAddr;
	sioAddrSendBuf.buf[4] = machineAddr.s.addrh;
	sioAddrSendBuf.buf[5] = machineAddr.s.addrl;
	sioAddrSendBuf.buf[3] = sioAddrSendBuf.buf[2]^sioAddrSendBuf.buf[4]^sioAddrSendBuf.buf[5];
	UART1Send(sioAddrSendBuf.buf,ADDRSendAddrPackLen);
	cflgSendAddr = 1;
}

/******************************************************************************
 * 函数原型: void SendConfirmPack(void);                                      *
 * 功能: 向ARM发送地址确认包                                                  *
 * 说明: 1.确认ARM回馈的地址与Motorola发送的地址一致后,立即调用本函数         *
 *       2.通过UART1口将确认包发给ARM                                         *
 ******************************************************************************/
void SendConfirmPack (void)
{
	sioAddrSendBuf.buf[0] = 0xFF;
	sioAddrSendBuf.buf[1] = 0xFF;
	sioAddrSendBuf.buf[2] = ADDRSioTypeConfirm;
	sioAddrSendBuf.buf[4] = AddrFbkCorrect;
	sioAddrSendBuf.buf[5] = ReservedByte;
	sioAddrSendBuf.buf[3] = sioAddrSendBuf.buf[2]^sioAddrSendBuf.buf[4]^sioAddrSendBuf.buf[5];
	UART1Send(sioAddrSendBuf.buf,ADDRConfirmPackLen);
}

/******************************************************************************
 * 函数原型: void RecvAddrMReadRxBuf(void);                                   *
 * 功能: 将接收缓冲区中的数据转移到sioAddrRecvBuf.buf中                       *
 * 说明: 通过UART1口接收地址反馈包                                            *
 ******************************************************************************/
void RecvAddrMReadRxBuf (void)
{
	int n, m;
	if(cUART1RxEnd == cUART1RxHead)                        // 如果UART1接收缓冲区中无数据
		return;                                            // 返回
	n = ADDRIBufLenMax-cSioAddrRecvBufEnd-2;               // 最多接收的字节数(留2个字节的余量)
	m = UART1GetRx(sioAddrRecvBuf.buf+cSioAddrRecvBufEnd,n);
	                                                       // 接收数据,m为实际接收到的字节数
	cSioAddrRecvBufEnd += m;                               // 重新设置sioAddrRecvBuf.buf的尾
}

/******************************************************************************
 * 函数原型: int RecvAddrMCheckLead(void);                                    *
 * 功能: sioAddrRecvBuf.buf中寻找包头                                         *
 * 说明: 1.返回值为接收包第1个有效字节即包类型字节的下标                      *
 *       2.如果没有找到包头,返回0                                             *
 ******************************************************************************/
int RecvAddrMCheckLead (void)
{
	int k;
	for(k = 2; k < cSioAddrRecvBufEnd; k++)
		if( sioAddrRecvBuf.buf[k-2] == 0xFF &&
			sioAddrRecvBuf.buf[k-1] == 0xFF &&
			sioAddrRecvBuf.buf[k-0] != 0xFF)               // 找到包头
			return k;
	return 0;
}

/******************************************************************************
 * 函数原型: void RecvAddrMNormalBuf(int lead);                               *
 * 功能: 将接收到的有效包移至sioAddrRecvBuf.buf的起始位置                     *
 * 说明: 1.注意不同情况的处理方式                                             *
 *       2.将sioAddrRecvBuf.buf的前2个字节设置成引导字节                      *
 ******************************************************************************/
void RecvAddrMNormalBuf (int lead)
{
	int n, adj, len;
	n = cSioAddrRecvBufEnd - ADDRILeadLenMax;
	if(n <= 0)                                             // 如果sioAddrRecvBuf.buf中的字节数不超
	                                                       // 过4
		return;                                            // 不处理,返回

	/* "lead == 0"处理模块 */
	if(!lead)
	{
		// __memmovebufforlittle
		__memmovebuf(sioAddrRecvBuf.buf,n,ADDRILeadLenMax);
		                                                   // 移动最末尾的4个字节到包的头部,以便不
		                                                   // 影响下一次寻找包头的操作
		cSioAddrRecvBufEnd = ADDRILeadLenMax;              // 设置sioAddrRecvBuf.buf的尾为4
		return;
	}

	/* "lead == 1"处理模块 */
	// 由函数RecvAddrMCheckLead可知,lead不可能为1

	/* "lead == 2"处理模块 */
	if(lead == ADDRILeadLen)                               // 如果包类型字节的下标是2
		return;                                            // 不必处理,返回

	/* "lead >= 3"处理模块 */
	/* 将有效包移至sioAddrRecvBuf.buf的起始位置 */
	adj = lead - ADDRILeadLen;                             // adj为整体移动位置
	len = cSioAddrRecvBufEnd - adj;                        // len为需要移动的字节个数
	// __memmovebufforlittle
	__memmovebuf(sioAddrRecvBuf.buf,adj,len);              // 统一将有效包调整为2个引导字
	cSioAddrRecvBufEnd -= adj;                             // 重新设置sioAddrRecvBuf.buf的尾
}

/******************************************************************************
 * 函数原型: int RecvAddrMCheckData(void);                                    *
 * 功能: 对收到的包进行整体校验                                               *
 * 说明: 1.本函数依次对接收到的数据进行包类型校验和异或校验                   *
 *       2.校验成功,返回1                                                     *
 ******************************************************************************/
int RecvAddrMCheckData (void)
{
	unsigned char chk;
	unsigned char type;
	if(cSioAddrRecvBufEnd < ADDRIBufLenMin)
		return 0;
	type = sioAddrRecvBuf.buf[2];

	/* 包长度及类型校验模块 */
	switch(type)
	{
	case ADDRSioTypeFbkAddr:
		if(cSioAddrRecvBufEnd < ADDRFbkAddrPackLen)
			return 0;
		break;
	default:
		return -1;
	}

	/* 异或校验模块 */
	chk = sioAddrRecvBuf.buf[2]^sioAddrRecvBuf.buf[4]^sioAddrRecvBuf.buf[5];
	if(chk != sioAddrRecvBuf.buf[3])
		return -2;

	/* 存储接收包的类型 */
	cRecvAddrBufType = type;

	return 1;
}

/******************************************************************************
 * 函数原型: int RecvAddrMDataDispatch(void);                                 *
 * 功能: 判断接收包的类型并做相应的处理                                       *
 * 说明: 正常情况下返回包的类型                                               *
 ******************************************************************************/
int RecvAddrMDataDispatch (void)
{
	int type;
	KSCRFAddrCode machineAddr;
	if(!cRecvAddrBufType)                                  // cRecvAddrBufType未被赋值,说明接收到的
		                                                   // 包类型错误或未通过异或校验
		return 0;
	type = cRecvAddrBufType;
	cRecvAddrBufType = 0x00;                               // 注意清0!
	switch(type)
	{
	case ADDRSioTypeFbkAddr:
		if(cflgSendAddr)
		{
			cflgSendAddr = 0;
			machineAddr.addrCode = nMachineAddr;
			if( sioAddrRecvBuf.fbkAddr.addrh == machineAddr.s.addrh &&
				sioAddrRecvBuf.fbkAddr.addrl == machineAddr.s.addrl )
			{
				cflgAddrReady = 1;
				SendConfirmPack();
				return type;
			}
			return -3;
		}
		return -2;
	default:
		return -1;
	}
}

/******************************************************************************
 * 函数原型: void RecvAddrMDeleteLead(void);                                  *
 * 功能: 删除包头                                                             *
 * 说明: 无                                                                   *
 ******************************************************************************/
void RecvAddrMDeleteLead (void)
{
	int n;
	n = cSioAddrRecvBufEnd - ADDRILeadLen;                 // n > 0
	__memmovebuf(sioAddrRecvBuf.buf,ADDRILeadLen,n);       // 除包头外的所有数据向前移动2字节
	cSioAddrRecvBufEnd -= ADDRILeadLen;                    // 更新cSioAddrRecvBufEnd的值
}

/******************************************************************************
 * 函数原型: void RecvAddrMsg(void);                                          *
 * 功能: 接收并处理有关机器地址的信息                                         *
 * 说明: 从UART1口接收机器地址信息                                            *
 ******************************************************************************/
void RecvAddrMsg (void)
{
	int lead, data, r;
	RecvAddrMReadRxBuf();
	lead = RecvAddrMCheckLead();
	RecvAddrMNormalBuf(lead);
	if(lead == 0)                                          // 如果未在sioAddrRecvBuf.buf中找到包头
		return;
	data = RecvAddrMCheckData();
	if(data == 0)                                          // 如果sioAddrRecvBuf.buf中的字节数不够
		return;
	r = RecvAddrMDataDispatch();
	RecvAddrMDeleteLead();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -