📄 addr.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 + -