📄 link.c
字号:
#include <reg52.h>
#include "link.h"
#include "profibus.h"
struct DPRAM485 xdata dpram485 _at_ 0x8000; //定义双口RAM中的结构体
struct SLA_DATA_CONSTRUCT slave_data_str[125]; //模块的数据结构体,最多可以支持124个站(有一个是主站)
uchar uc_station_num; //站总数
uchar uc_out_command_old; //用于保存上一次的命令
uchar data uc_link485_life_flag_old; //用于保存sys_master上一次的存活标志值
uchar data uc_link485_life_flag; //与上一次的值比较,以确定LINK485是否还在正常工作
//uchar data uc_link_life_flag_old; //用于保存LINK_Profibus上一次的存活标志值
//uchar data uc_link_life_flag; //提供给sys_master用于判断自己是否正常工作
uchar data uc_system_status_flag; //系统状态标志,标志系统目前处于何种状态
uchar data uc_handshake_error_count; //握手错误计数器,用于判断握手是否超时
uchar data uc_life_error_counter; //心跳信号错误计数器,达到一定数值就确认对方已经出错
uchar data uc_prm_com_old; //用于保存老的参数化命令
uchar data uc_sys_command_old; //用于保存老的系统命令.
uchar data uc_command_succeful_flag; //命令采用同步方式处理,此标志用于判断是否成功
uchar *p_out_command; //指向输出型命令
uchar *p_in_command; //指向输入型命令
//struct LINK_DATA_BUF xdata *p_link_data_buf ;
void update_data(struct LINK_DATA_BUF *p_link_data_buf)
{
uchar *p_dpram; //用于向双口RAM中某一字节写入一个值
dpram485.uc_link_life_counter ++; //声明自己还在正常运行
p_dpram= (uchar xdata *)0x8507;
*p_dpram= uc_link485_life_flag; //由于LINK的板上没有LED,把对方的存活标志通过双口RAM传递过去
*(p_dpram+1) = uc_system_status_flag; //然后是系统状态标志
switch(p_link_data_buf->interface_flag&0x03) //根据接口命令决定进行什么操作
{
case PARAM_COM: //参数化命令,要求先发STOP命令,再发参数化命令,再发OPERATE命令
// p_out_command = p_link_data_buf->p_out_tol_ptr; //
// p_in_command = p_link_data_buf->p_in_tol_ptr;
// p_link_data_buf->p_in_tol_ptr; //重新赋输入输出命令的地址
*p_link_data_buf->p_diag_tol_ptr = 0X1; //置诊断信息
dpram485.datum[7]=0x1;
//uc_system_status_flag=RESET_STATE;
system_state_deal(p_link_data_buf);
if (uc_system_status_flag==WORK_STATE)
{
p_link_data_buf->interface_flag=EXA_COM;
}
else
{
p_link_data_buf->interface_flag=PARAM_COM;
}
break;
case EXA_COM: //数据交换命令,按顺序更新数据
uc_link485_life_flag=link485_life_juge(); //判断link的存活标志
if (uc_link485_life_flag== TRUE_485)
{
*p_link_data_buf->p_diag_tol_ptr = 0X0;
dpram485.datum[7]=0x0;
update_in_data();
update_out_data();
update_sys_command();
update_diag_data();
}
else
{
uc_system_status_flag = RESET_STATE; //否则命令错误,重启
p_link_data_buf->interface_flag=PARAM_COM;
*p_link_data_buf->p_diag_tol_ptr = 0X1;
dpram485.datum[7]=0x1;
}
break;
default:
p_link_data_buf->interface_flag=PARAM_COM;
*p_link_data_buf->p_diag_tol_ptr = 0X1;
dpram485.datum[7]=0x1;
uc_system_status_flag = RESET_STATE; //否则命令错误,重启
break;
}
/*if (uc_system_status_flag == WORK_STATE) //更新LINK的诊断标志
{
*p_link_data_buf->p_diag_tol_ptr = 0X0;
dpram485.datum[7]=0x0;
}
else
{
*p_link_data_buf->p_diag_tol_ptr = 0X1;
dpram485.datum[7]=0x1;
}*/
return;
}
void update_sys_command() //命令处理
{
// p_out_command = p_link_data_buf->p_out_tol_ptr; //
// p_in_command = p_link_data_buf->p_in_tol_ptr;
if(p_out_command != 0) //如果有新的命令
{
if (uc_out_command_old != *p_out_command)
{
uc_out_command_old = *p_out_command;
if(uc_out_command_old==RESET_COM||uc_out_command_old==PRM_COM)
{
*p_in_command=0;
}
else
{
write_command(*p_out_command);
}
*p_in_command=uc_out_command_old;
//*p_out_command = 0; //写完后把命令清0,以方便判断是否有新命令
dpram485.mcu_com_sig=INVALID;
}
}
else
{
uc_out_command_old = *p_out_command;
*p_in_command=uc_out_command_old; //返回给主站卡
*p_out_command = 0; //写完后把命令清0,以方便判断是否有新命令
}
}
void update_prm_data(struct LINK_DATA_BUF *p_link_data_buf) //更新参数化区
{
uint data ii,jj;
cal_dpram_addr(p_link_data_buf); //重新计算双口RAM的传输列表
for(ii=1; ii<=uc_station_num; ii++)
{
dpram485.pc_s_sig_list[ii] = BUSY; //参数化数据不管从站有没有故障都照写
for(jj=0; jj<slave_data_str[ii].prm_len; jj++) //按照传输列表重新构造双口RAM的数据结构
{
*((uchar xdata*)(dpram485.trans_list[ii].base_addr+DPRAM_BASE_ADDR+jj)) = *(slave_data_str[ii].prm_ptr+jj);
}
dpram485.pc_s_sig_list[ii] = FREE;
}
}
void update_in_data(void) //更新输入数据区
{
uchar data ii,jj;
for(ii=1; ii<=uc_station_num; ii++)
{
dpram485.pc_s_sig_list[ii] = BUSY;
if(dpram485.mcu_s_sig_list[ii] == FREE) //发现对方忙则丢弃一帧
{
for(jj=0; jj<slave_data_str[ii].in_len; jj++)
{
*(slave_data_str[ii].in_ptr+jj) = *((uchar xdata*)(DPRAM_BASE_ADDR+dpram485.trans_list[ii].base_addr+dpram485.trans_list[ii].prm_len+jj));
}
}
dpram485.pc_s_sig_list[ii] = FREE;
}
}
void update_out_data(void) //更新输出数据区
{
uchar data ii,jj;
for(ii=1; ii<=uc_station_num; ii++)
{
dpram485.pc_s_sig_list[ii] = BUSY;
if(dpram485.mcu_s_sig_list[ii] == FREE) //如果双口RAM忙则丢弃一帧
{
for(jj=0; jj<slave_data_str[ii].out_len; jj++)
{
*(uchar xdata*)(DPRAM_BASE_ADDR+dpram485.trans_list[ii].base_addr+dpram485.trans_list[ii].prm_len+dpram485.trans_list[ii].in_len+jj) = *(slave_data_str[ii].out_ptr+jj);
}
}
dpram485.pc_s_sig_list[ii] = FREE;
}
}
void update_diag_data(void)
{
uchar data ii,jj;
for(ii=1; ii<=uc_station_num; ii++)
{
dpram485.pc_s_sig_list[ii] = BUSY;
if(dpram485.mcu_s_sig_list[ii] == FREE) //如果双口RAM忙则丢弃一帧
{
for(jj=0; jj<slave_data_str[ii].diag_len; jj++)
{
*(slave_data_str[ii].diag_ptr+jj) = *(uchar xdata*)(DPRAM_BASE_ADDR+dpram485.trans_list[ii].base_addr+dpram485.trans_list[ii].prm_len+dpram485.trans_list[ii].in_len+dpram485.trans_list[ii].out_len+jj);
}
}
dpram485.pc_s_sig_list[ii] = FREE;
}
*(slave_data_str[0].diag_ptr+0) = *(uchar*)(DPRAM_DATA_ADDR+6); //取LINK485本身的三个诊断信息
*(slave_data_str[0].diag_ptr+1) = *(uchar*)(DPRAM_DATA_ADDR+7);
*(slave_data_str[0].diag_ptr+2) = *(uchar*)(DPRAM_DATA_ADDR+8);
}
void cal_dpram_addr(struct LINK_DATA_BUF *p_link_data_buf)
{
uchar data ii,jj;
uchar station_type_cal_temp; //暂时存放每个从站的站类型(方便计算)
uchar *p_link_data_buf_temp; //暂时存放每个从站的参数化区的首地址
uchar station_mark_flag; //暂时存放每个站的掩码字节
uchar station_diag_len; //暂时存放诊断长度
uchar station_data_len; //暂时存放通道数据的长度
uchar prm_ptr_count_temp; //用于保存每个站参数化区指针的位置信息
uint dpram_addr_temp; //用于暂时保存双口RAM地址
uchar rout_num; //通道数
uchar station_type_cal_temp2;
uchar *p_master_data;
// p_link_data_buf->p_prm_tol_ptr = (uchar xdata*)0x9f1;
p_out_command=p_link_data_buf->p_out_tol_ptr;
p_in_command=p_link_data_buf->p_in_tol_ptr;
slave_data_str[0].prm_len = 6; //0号站即为主站,的参数化区共6字节
slave_data_str[0].in_len = 0;
slave_data_str[0].out_len = 0;
slave_data_str[0].diag_len = 3; //三个保留的诊断信息位
slave_data_str[0].prm_ptr = p_link_data_buf->p_prm_tol_ptr;
slave_data_str[0].in_ptr = p_link_data_buf->p_in_tol_ptr+1;
slave_data_str[0].out_ptr = p_link_data_buf->p_out_tol_ptr+1;
slave_data_str[0].diag_ptr = p_link_data_buf->p_diag_tol_ptr+1;
////////////////////////////////////////////////////////////////
//下面是主站的传输列表
////////////////////////////////////////////////////////////////
uc_station_num = *(p_link_data_buf->p_prm_tol_ptr); //站的总数,全局通用
if (uc_station_num >125)
{
uc_station_num =125;
}
dpram485.trans_list[0].base_addr = DPRAM_DATA_ADDR;
dpram485.trans_list[0].prm_len = slave_data_str[0].prm_len;
dpram485.trans_list[0].in_len = slave_data_str[0].in_len;
dpram485.trans_list[0].out_len = slave_data_str[0].out_len;
dpram485.trans_list[0].diag_len = slave_data_str[0].diag_len;
dpram485.trans_list[0].station_addr = 0; //主站的站地址
////////////////////////////////////////////////////////////////
//下面是主站的参数化信息
////////////////////////////////////////////////////////////////
p_master_data = (uchar xdata*)(DPRAM_DATA_ADDR+DPRAM_BASE_ADDR);
*p_master_data = 0;
*(p_master_data+1) = *(p_link_data_buf->p_prm_tol_ptr+1); //主站的类型
*(p_master_data+2) = *(p_link_data_buf->p_prm_tol_ptr+2);
*(p_master_data+3) = *(p_link_data_buf->p_prm_tol_ptr+3);
*(p_master_data+4) = *(p_link_data_buf->p_prm_tol_ptr+4);
*(p_master_data+5) = *(p_link_data_buf->p_prm_tol_ptr+5);
// *(p_master_data+5) = *(p_link_data_buf->p_prm_tol_ptr+6); //系统波特率
// *((uint xdata*)(DPRAM_DATA_ADDR+2)) = *(p_link_data_buf->p_prm_tol_ptr+3); //最小帧间延时
// *((uint xdata*)(DPRAM_DATA_ADDR+4)) = *(p_link_data_buf->p_prm_tol_ptr+5); //最小字节间延时
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -