📄 communication.c
字号:
//20070407在此基础上进行调试
/*************************************旋转部分管理CPU********************************/
#include "communication.h"
//#define
/*******************************************************************************
*********************************全局变量**************************************
*******************************************************************************/
UINT8 Wait_Flag = 0; //等待标志
UINT8 Right_Send_Flag = 0; //正确发送了一帧数据
UINT8 Send_Time_Flag = 0; //发送次数标志位
UINT8 Error_Flag = 0; //错误标志
UINT8 Receive_flag = 0; //1:接收数据;0:没有接收到数据
UINT8 Encrypt[13] = {0,0,0,0,0,0,0,}; //用来存放一个数据帧
UINT8 R_Encrypt[13] = {0,0,0,0,0,0,0}; //
UINT8 Lead[Lead_length] = {0xf0,0xf0,0xf0,0xf0,0xf0}; //引导码
UINT8 Parameter[8] = {0x10,0x80,0x33,0x44}; //参数区
UINT8 order1 = 0; //命令1
UINT8 order2 = 0; //命令2
/**********************************************
**函数功能:把要发送的数据编制成数据帧的格式
**入口参数:UINT8 addr命令的目的地址 UINT8 order1 要发送的命令1,UINT8 order2,命令2(参数的字节数)UINT8 ×Par:参数的内容
**出口参数:无
**调用模块:无
**备 注:修改了数组Encrypt[]的内容;
**********************************************/
void Encrypt_Rotary(UINT8 flag,UINT8 addr,UINT8 order1,UINT8 order2,UINT8 *par)
{
UINT8 k=0;
if(flag == 1)//回答头还是命令头 为1是命令头 0是回答头
{
Encrypt[0] = COMMAND;
}
else
{
Encrypt[0] = REPLY_TO;
}
Encrypt[1] = ADDR_ROTARYCON;
Encrypt[2] = addr;
Encrypt[3] = order1;
Encrypt[4] = order2;
for(k = 1;k <= order2; k++)
{
Encrypt[4+k] = *par;
par++;
}
Encrypt[order2+5] = BCC_checkout(Encrypt,Encrypt[4]+6);
}
/*************************************************
**函数功能:把数据帧发送到总线上,并实现超时重传功能
**入口参数:UINT8 flag UINT8 Destination_Addr UINT8 Ord1,Ord2,*Par
**出口参数:无
**调用模块:底层的串口发送程序
**备 注:在发送有效数据之前先发送至少四个字节的引导码
**************************************************/
void Send_Rotary(UINT8 flag,UINT8 Destination_Addr,UINT8 Ord1,UINT8 Ord2,UINT8 *Par)//把数据帧发送到总线上
{
//调用一个串口发送程序,把全局变量(数组Encrpyt[])发送到总线上
Encrypt_Rotary(flag,Destination_Addr,Ord1,Ord2,Par);
SendUart(COM2,Lead,Lead_length); //在发送数据帧之前先发送引导码;引导码长度由Lead_length确定
SendUart(COM2,Encrypt,Encrypt[4]+6);//发送的数据帧长度由发送数组的第四个元素的值即order2的值加上固有部分(计6个字节)确定
}
/*************************************************
**函数功能:接收总线上的数据帧并将其存放到临时数组R_Encrypt[]中
**入口参数:无
**出口参数:无
**调用模块:USART.C中的全局变量g_aRecvBuf[];
**************************************************/
void Receive_Rotary(void)//接收总线上的数据帧
{
UINT8 i = 0;
UINT8 n = 0;
Stop_COM(COM2,UsartRXD);//关串口中断,
for(i = 0 ;i <= g_aRecvBuf[4]+6 ;i++)//for(i = 0;i < 7;i++)
{
R_Encrypt[i] = g_aRecvBuf[i];
}
for(n = 0 ;n <= g_aRecvBuf[4]+6 ;n++)//for(n = 0;n < 7;n++)
{
g_aRecvBuf[n] = 0;
}
Verify_Rotary();
Start_COM(COM2,UsartRXD);//开串口中断
/*****************************原来的全局数组有64个字节修改后有7个字节***********************/
}
/*************************************************
**函数功能:对给的数组进行BCC校验
**入口参数:UINT *SBCC,UINT8 S_Length
**出口参数:BCC_String
**调用模块:无
**************************************************/
UINT8 BCC_checkout(UINT8 *SBCC, UINT8 S_Length)
{
UINT8 BCC_string = 0;
UINT8 m = 0;
SBCC++;
S_Length--;
for(m = 1 ;m < S_Length ;m++)
{
BCC_string ^= *SBCC;
SBCC++;
}
return BCC_string;
}
/*************************************************
**函数功能:校验接收到的数据的BCC码,如果BCC码正确则验证接收到的数据
帧的目的地址是不是本地地址,如果是则说明收到的是一帧正确的数据
无论是BCC码还是地址校验错误都将丢弃接收到的数据帧。
注意此函数可以修改数组Encrpyt[7]的值。
**入口参数:无
**出口参数:无
**调用模块:无
**************************************************/
void Verify_Rotary(void)
{
UINT8 temp,i,x,temp1;
temp = R_Encrypt[R_Encrypt[4]+5];//temp = R_Encrypt[6];
temp1 = BCC_checkout(R_Encrypt,R_Encrypt[4]+6);
if(temp == temp1)
{
if(R_Encrypt[2] == ADDR_ROTARYCON)// 验证接收到的数据帧中的目的地址是否是本机地址
{
for(i = 0;i < R_Encrypt[4]+6;i++)
{
Encrypt[i] = R_Encrypt[i];//验证通过后,把临时数组的值给接收数组
Receive_flag = 1;//接收标志位置1
}
}
else
{
for(x = 0;x < R_Encrypt[4]+6;x++)
{
R_Encrypt[x] = 0;//清空临时数组
}
Receive_flag = 0;//接收标志清零
}
}
else
{
Receive_flag = 0;//接收标志清零
}
}
/*************************************************
**函数功能:处理经过BCC校验和地址校验的数据帧,根据数据帧的第一个字节来判断是命令还是回复,
如果是回复则把发送成功标志位Right_Send_Flag置位,如果是命令则提取命令并且给发送端
回复信息
**入口参数:
**出口参数:
**调用模块:Send_Rotary()
**************************************************/
void Decipher_Rotary(void)//把接收到的帧中的命令提取出来
{
UINT8 temp = 0,j = 0;
UINT8 Read_Length = 0;
UINT8 r;
UINT8 temp_BUF[8];
UINT16 adr_temp;
temp = Encrypt[0];
if(temp == REPLY_TO)//如果收到的是回答帧则说明对方成功的收到了命令
{
Right_Send_Flag = 1;//成功的发送了一帧数据
}
if(temp == COMMAND)//如果收到的是命令帧,则提取命令并做出答复
{
order1 = Encrypt[3];//取出数组中的第4个字节中的数据存放到order1中
order2 = Encrypt[4];//数组的第5个字节为命令2,其作用是用来规定参数Parameter的字节数
for(j = 1;j <= order2; j++)
{
Parameter[j-1] = Encrypt[4+j];//把数据接收到的数据帧的第6个字节起的数据给参数数组
}
Send_Rotary(REPLY_TO_HEAD,ADDR_FIXED,order1,order2,Parameter);
switch(order1)
{
case WRITE_FLASH:
{
adr_temp = Parameter[0];
adr_temp = adr_temp << 8;
adr_temp |= Parameter[1];//参数数组的前两个字节的内容分别为地址的高8位和低8位
FlashModify_N_Byte_WriteSeg( adr_temp, Parameter+2,order2);
};break;
case READ_FLASH:
{
adr_temp = Parameter[0];
adr_temp = adr_temp << 8;
adr_temp |= Parameter[1];//参数数组的前两个字节的内容分别为地址的高8位和低8位
Read_Length = Parameter[2];
for(r = 0 ; r < Read_Length; r++)
{
temp_BUF[r] = FlashReadByte(adr_temp+r);
}
//f0 f0 f0 f0 f0 f0 f0 f0 AA 04 14 15 04 10 82 44 55 82 //写
//f0 f0 f0 f0 f0 f0 f0 f0 AA 04 14 16 03 10 80 01 94 //读一个字节
//f0 f0 f0 f0 f0 f0 f0 f0 AA 04 14 16 03 10 80 04 91 //Read 4个字节
Send_Rotary(REPLY_TO_HEAD,ADDR_FIXED,order1,Read_Length,temp_BUF);
};break;
default:break;
}
}
}
/*************************************************
**函数功能:命令解释程序,根据命令完成规定好的动作
**入口参数:
**出口参数:
**调用模块:
**************************************************/
/*void Unpuzzle_Rotary()
{
switch(order1)
{
case READ_FLASH:
...
}
}*/
/***************************************************
****************此主函数仅供测试用*******************
****************************************************/
void main(void)
{ InitSys();
Open_All_Int();//打开全局中断
InitCom(COM2,BPS9600);//串口初始化
RS485_Set(ConstManageIC, RS485_REC);//485设置 为接收
Send_Rotary(COMMAND_HEAD,ADDR_FIXED,0x15,0x04,Parameter);
while(1)
{
if(COM2_R_flag)
{
Receive_Rotary();//接受收到的数据
if(Receive_flag)
{
Decipher_Rotary();
}
COM2_R_flag = 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -