📄 communicate.c
字号:
#define __COMMUNICATE
#include "communicate.h"
#undef __COMMUNICATE
//********************** Global Variable **********************
unsigned char connect = 0; // 连接标记
unsigned char cLocalAddress = 1; // 本机地址
DWORD dwTemp;
char cIpAddr[16];
ushort wport;
uchar bTouchAddr = 1;
//*************************************************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 计算并添加数据包校验和.
// 描述: 计算数据阿伯的校验和字节, 并添加到数据包末端.
// 若发送方式为串口, 赋值串口发送长度.
//
// [参数表]
// port: 串口号. 0-UART0; 1-UART1; 2-UART2.
// data: 数据数组始地址.
// sendType: 通信方式. 0-串口; 1-网络.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void CalCommSum (uchar port, uchar *data, uchar sendType)
{
unsigned long i, sum = 0;
// 计算校验和
for( i=0; i<data[1]-1; i++ )
sum += data[i];
sum &= 0xff;
sum = 0x100-sum;
data[i] = sum; // 将校验和添加到数据包末端
if( sendType == UART_SEND )
UartSendLens[port] = data[1]-1; // 为串口发送赋长度
// 注: 由于后续用到UartStartSend函数, 所以此长度不含第一个字节.
}//CalCommSum()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 检查UART0.
// 描述: 串口0与PC机通信.
//
// [参数表]
// Uart0ReceData: 串口0接收数据数组始地址.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void CheckUart0(unsigned char *Uart0ReceData)
{
uchar i, sum = 0;
ulong DataLen; // 数据长度
DataLen = Uart0ReceData[1] + (Uart0ReceData[2]<<8); // 长度两个字节
if((DataLen >= 6) && (DataLen == UartReceLen[UART0]))
// 通过数据长度判断数据包是否已接收完毕
{
for( i=0; i<UartReceLen[UART0]; i++ ) // 计算累加和
{
sum += Uart0ReceData[i];
}
UartReceLen[UART0] = 0; // 串口0接收长度清零
DataLen = 0; // 数据长度清零
UARTprintf("%d ", Uart0ReceData[3]);
if( (sum & 0xff) == 0 ) // 校验和判断
{
// 接收方地址与本机地址不等时,不处理
if( Uart0ReceData[3] != cLocalAddress )
return;
switch(Uart0ReceData[4]) //命令
{
case 127:
Uart0_CommProcess(Uart0ReceData); //子命令
break;
default: break;
}
}
else
{
Uart0_SendCommOK(0xAA); //发送通信成功
}
}
}//CheckUart0()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: UART0发送通信成功.
// 描述: 向上位机发送通信成功数据包.
//
// [参数表]
// status: 状态.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Uart0_SendCommOK(unsigned char status)
{
Uart0_SendBuf(0) = 2;
Uart0_SendBuf(1) = 7+1;
Uart0_SendBuf(2) = Uart0_ReceBuf(4);
Uart0_SendBuf(3) = Uart0_ReceBuf(3);
Uart0_SendBuf(4) = cLocalAddress; //本机地址
Uart0_SendBuf(5) = Uart0_ReceBuf(6); //子命令
Uart0_SendBuf(6) = status;
CalCommSum(UART0, UartSendBuf[UART0], UART_SEND); // 计算校验和
UartStartSend(UART0); // 启动串口发送
}//Uart0_SendCommOK()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 串口0通信处理.
// 描述: 根据数据包的子命令执行相应的通信处理操作.
//
// [参数表]
// RecData: 接收数据数组的始地址.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Uart0_CommProcess(unsigned char *RecData)
{
// ulong dwDstAddress;
ulong dwLength;
uchar subCmd = RecData[6]; // 子命令
ulong i,j;
switch(subCmd)
{
case 0: //读控制板地址
Uart0_SendCommOK(1);
break;
case 1: //获取当前时间
SendCurrTime(UART0,UartSendBuf[UART0],RecData, UART_SEND);
break;
case 2: //建立联络
BuildConnect(UART0,UartSendBuf[UART0],RecData, UART_SEND);
break;
case 7: //读内存
ReadMemory(UartSendBuf[UART0],RecData,UART_SEND);
UartStartSend(UART0);
break;
case 28: //go, 程序复位
goCommand(MAIN_ENTRY); // 强制跳转到目标地址
// 注: 要根据list文件中main_boot的入口地址进行赋值.
break;
case 29: //
Uart0_SendCommOK(0x29);
break;
case 30: //把程序搬到Norflash
dwLength = RecData[7]+(RecData[8]<<8)+(RecData[9]<<16)+(RecData[10]<<24);
j = (dwLength - 1)/NOR_FLASH_SECTOR_SIZE + 1;//擦除块数
if(connect == 1)
{
for( i=0; i<j; i++)
{
if(EraseSector(i) == FALSE)
return;
}
Writeflash((uchar *)DOWNLOAD_SDRAM_ADDR,0,dwLength);
Uart0_SendCommOK(0x55);
}
break;
case 255://卸去连接
connect = 0;
Uart0_SendCommOK(0x55);
break;
default: break;
}//switch(SubCmd)
}//Uart0_CommProcess()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络发送通信成功.
// 描述: 向上位机发送通信成功数据包.
//
// [参数表]
// port: 串口号. 0-UART0; 1-UART1; 2-UART2.
// sendData: 发送数据数组始地址.
// RecData: 接收数据数组始地址.
// status: 状态.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetSendCommOK(uchar port,uchar *sendData, uchar *RecData, uchar status)
{
DWORD i;
sendData[0] = 2;
sendData[1] = 12;
sendData[2] = RecData[5];
sendData[3] = RecData[4];
sendData[4] = RecData[3]; // 本机地址
sendData[5] = RecData[6]; // 子命令
sendData[6] = status;
sendData[7] = RecData[7];
sendData[8] = RecData[8];
sendData[9] = RecData[9];
sendData[10] = RecData[10];
CalCommSum(port, sendData, NET_SEND);
for(i=0;i<2000;i++);
NetTrPack(sendData,cIpAddr,wport,sendData[1]);//NETTS
}//NetSendCommOK()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 发送当前时间.
//
// [参数表]
// port: 串口号. 0-UART0; 1-UART1; 2-UART2.
// sendData: 发送数据数组的始地址.
// RecData: 接收数据数组的始地址.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SendCurrTime (uchar port,uchar *sendData, uchar *RecData, uchar sendType)
{
int i;
connect = 0;
sendData[0] = 2;
sendData[1] = 7+6;
sendData[2] = RecData[5];
sendData[3] = RecData[4];
sendData[4] = bTouchAddr; //本机地址
sendData[5] = RecData[6];//子命令
dwTemp = rTCNTO4;
sendData[6] = dwTemp&0xFF;
sendData[7] = (dwTemp>>8);
dwTemp = dwTickCount+300; //记录当前时间
sendData[8] = (dwTemp-300)&0xFF;
sendData[9] = ((dwTemp-300)>>8) ^ sendData[6];
sendData[10] = ((dwTemp-300)>>16) ^ sendData[6] ^ 0x78;
sendData[11] = ((dwTemp-300)>>24) ^ sendData[5] ^ 0x34;
CalCommSum(port,sendData,sendType);
if(sendType == UART_SEND)
UartStartSend(port);
else
{
for(i=0;i<2000;i++);
NetTrPack(sendData,cIpAddr,wport,sendData[1]);
}
}//SendCurrTime()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 建立连接.
//
// [参数表]
// port: 串口号. 0-UART0; 1-UART1; 2-UART2.
// sendData: 发送的数据数组的始地址.
// RecData: 接收数据数组的始地址.
// sendType: 通信方式. 0-串口; 1-网络.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BuildConnect(uchar port, uchar *sendData, uchar *RecData, uchar sendType)
{
int i,j;
if( dwTemp > dwTickCount )
{
//以dwTickCount(dwTemp - 300)为种子 经上位机做作计算的值(加上了一个
//随机值RecData[7]*60*1000)
i = RecData[8] + (RecData[9]<<8) + (RecData[10]<<16) + (RecData[11]<<24);
j = RecData[7] *60000;
if( i == (j + dwTemp - 300) )
{
connect = 1;
if( sendType == UART_SEND )
Uart0_SendCommOK(0x55);
else
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
}
else
if( sendType == UART_SEND )
Uart0_SendCommOK(0x55);
else
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x57);
}
else
if( sendType == UART_SEND )
Uart0_SendCommOK(0x55);
else
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x56);
}//BuildConnect()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络通信处理.
// 描述: 根据数据包的子命令执行相应的通信处理操作.
//
// [参数表]
// RecData: 接收数据数组的始地址.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetCommProcess (uchar *RecData)
{
ulong dwDstAddress;
ulong j,k;
ulong dwLength;
uchar subCmd = RecData[6]; // 子命令
uchar udpData[4096];
switch( subCmd )
{
case 0: //读控制板地址
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,bTouchAddr);
break;
case 1: //获取当前时间
SendCurrTime(UART0,UartSendBuf[UART0], RecData, NET_SEND);
break;
case 2: //建立联络
BuildConnect(UART0,UartSendBuf[UART0], RecData, NET_SEND);
break;
case 7: //读内存
ReadMemory(udpData,RecData,NET_SEND);
NetTrPack(udpData,cIpAddr,wport,udpData[1]);
break;
case 8: //写内存
dwDstAddress = RecData[7]+(RecData[8]<<8)+(RecData[9]<<16)+(RecData[10]<<24);
dwLength = RecData[11]|(RecData[12]<<8);
memcpy((char *)dwDstAddress,(char *)&RecData[13],dwLength);
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
break;
case 26:
nand_init();
break;
case 28: //go
goCommand(MAIN_ENTRY);
break;
case 29: //
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
break;
case 30: //把程序从SDRAM搬到Norflash
dwLength = RecData[7]+(RecData[8]<<8)+(RecData[9]<<16)+(RecData[10]<<24);
j = (dwLength - 1)/NOR_FLASH_SECTOR_SIZE + 1;//擦除块数
if(connect == 1)
{
for(k=0;k<j;k++)
{
if(EraseSector(k) == FALSE) return;
}
Writeflash((uchar *)DOWNLOAD_SDRAM_ADDR,0,dwLength);
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
}
break;
case 31: // 当程序下载到SDRAM后, 直接跳转到其入口运行
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
goCommand(DOWNLOAD_SDRAM_ADDR);
break;
case 33: // 读NandFlash
break;
case 34: // 写NandFlash
dwDstAddress = RecData[7]+(RecData[8]<<8)+(RecData[9]<<16)+(RecData[10]<<24);
dwLength = RecData[11]|(RecData[12]<<8);
if(NandWriteData((u32)dwDstAddress,(u32)&RecData[13],(u32)dwLength) == 0)
{
NetSendCommOK(UART0,UartSendBuf[UART0],RecData,0x55);
}
break;
case 82: // 初始化网络
DM9000_init();
break;
case 83: // 检查网卡数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -