#include "ModBus.h"
/******************************************************************/
StrRxd xdata sys_rxd; //定义接收处理结构体
/******************************************************************/
/*******公有函数***************************************************/
void init_proc_rxd(void); //初始化串口通信变量
void process_rxd(void); //通信处理函数
void init_serial(void); //初始化串口
/*******私有函数***************************************************/
uint8 read_sys_rxd(void); //读接收缓冲区
uint8 data_check(void); //校验和检验
uint8 lenghchk(void); //数据长度检验
void data_change(void); //数据ASCII转换成HEX
/******************************************************************/
void init_proc_rxd(void)//初始化串口通信变量
{
uint8 idata i;
for( i = 0;i < POOLLEN;i++ )
{
//读
sys_rxd.pool[i] = 0;//接收数据缓冲区
sys_rxd.rec_buf[i] = 0;//去除包头包尾后的数据保留区,这里只保留一帧有效数据
//写
sys_txd.pool[i] = 0;//发送数据ASCII缓冲区
sys_txd.combuf[i] = 0;//发送数据HEX缓冲区
}
for( i = 0;i < 16;i++ )
{
sys_rxd.add_buf[i] = 0;//用于存放接收缓冲的地址,可以存放16个帧地址,奇数位是首地址,偶数位是尾地址
}
sys_rxd.front = 0;
sys_rxd.rear = 0;
sys_rxd.frm_num = 0;//缓冲区中的帧数量
sys_rxd.rd_byte = 0;//暂存读数据
sys_rxd.start_0x7e = 0;
sys_rxd.end_0x0d = 0;
sys_txd.txd_len = 0;//发送数据长度
}
/*****************************************************************/
uint8 read_sys_rxd(void)//读接收缓冲区
{
if( sys_rxd.rear == sys_rxd.front )
{
return WRONG;
}
else
{
sys_rxd.rd_byte = sys_rxd.pool[sys_rxd.front];
sys_rxd.front = (sys_rxd.front+1) % POOLLEN;
return RIGHT;
}
}
/*****************************************************************/
uint8 data_check(void)//校验和检验
{
uint8 add_len,temp;
uint8 i,j,k,fram_temp;
uint16 chk_sum,chk_sum_temp;
fram_temp = sys_rxd.frm_num;//如何防止在处理数据的同时新的中断使该值变化
add_len = 0;
if( fram_temp )//接收的一帧完整数据
{
fram_temp -= 1;
j = sys_rxd.add_buf[fram_temp * 2];
k = sys_rxd.add_buf[fram_temp * 2 + 1];
if(k > j)
{
add_len = k-j;
}
else
{
add_len = (POOLLEN - j ) + k;//地址确认
}
sys_rxd.front = j;
chk_sum = 0;
for( i = 0;i < add_len - 4;i++ ) //4 byte is check sum
{
read_sys_rxd(); //the poionter is add1
if( sys_rxd.rd_byte == FRAME_START )
{
sys_rxd.rd_byte = 0;
}
chk_sum += sys_rxd.rd_byte;
}
chk_sum = (~chk_sum) + 1;
chk_sum_temp = 0;
for(i=0;i<4;i++)
{
read_sys_rxd();
temp = sys_rxd.rd_byte;//rd_byte 暂存读数据
if(temp > 0x40)
{
temp -= 0x37; // get the hex valume
}
else
{
temp -= 0x30;
}
chk_sum_temp += temp;
if( i < 3 )
{
chk_sum_temp = chk_sum_temp << 4;
}
}
if( chk_sum_temp == chk_sum )
{
return RIGHT;
}
else
{
return WRONG;
}
}
else
{
return WRONG;
}
}
/*****************************************************************/
uint8 lenghchk(void) //数据长度检验
{
uint8 link_sum,link_sum_temp;
uint8 add_len;
uint8 j,k,fram_temp;
if( sys_rxd.rec_buf[4] != lchksum(sys_rxd.rec_buf[5]) )
{
return WRONG;
}
fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
if ( fram_temp == 0 )
{
return WRONG;
}
fram_temp--;
j = sys_rxd.add_buf[fram_temp*2];
k = sys_rxd.add_buf[fram_temp*2+1];
if(k>j)
{
add_len = k-j;
}
else
{
add_len = ( POOLLEN - j ) + k;
}
link_sum_temp = (add_len - 17);
link_sum = sys_rxd.rec_buf[5];
if(link_sum != link_sum_temp)
{
return WRONG;
}
else
{
return RIGHT;
}
}
/*****************************************************************/
void data_change(void)//数据ASCII转换成HEX
{
uint8 add_len;
uint8 i,j,k,temp1,fram_temp;
uint8 temp;
fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
if ( fram_temp == 0 )
{
return;
}
fram_temp--;
j = sys_rxd.add_buf[fram_temp*2];
k = sys_rxd.add_buf[fram_temp*2+1];
if(k>j)
{
add_len = k-j;
}
else
{
add_len = ( POOLLEN - j ) + k;
}
add_len = add_len / 2 + 1; //cup down 2 byte chksum
sys_rxd.front = j;
for(i = 0;i < add_len;i++ )
{
read_sys_rxd(); //the poionter is add1
if (sys_rxd.rd_byte == 0x0d)
{
sys_rxd.rec_buf[i] = 0xaa;
sys_rxd.rec_buf[i+1]=0x55;
return;
}
if (sys_rxd.rd_byte == 0x7e)
{
read_sys_rxd();
}
temp = sys_rxd.rd_byte;
if(temp>0x40)
{
temp-=0x37;
}
else
{
temp -=0x30;
}
temp = temp<<4;//高4位
read_sys_rxd();//the poionter is add1
temp1 = sys_rxd.rd_byte;
if(temp1>0x40)
{
temp1-=0x37;
}
else
{
temp1-=0x30;
}
sys_rxd.rec_buf[i] = temp+temp1; // include ver/adr/cid1/cid2/length/info
}
}
/*****************************************************************/
void process_rxd(void) //接收缓冲区中的数据 入处理缓冲区
{
while(sys_rxd.frm_num)
{
if(data_check() == WRONG)
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x02); //校验和错误
return;
}
data_change();
if( (sys_rxd.rec_buf[1] == ADDR ) ) //地址正确
{
if( lenghchk() ==WRONG ) //长度校验
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x03); //长度校验错误
return;
}
if(sys_rxd.rec_buf[0] != VER)
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x01); //版本错
return;
}
if( (sys_rxd.rec_buf[2] != M_CID)) //设备ID错
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num--;
txd_uni(0xe1); //设备ID错
return;
}
switch(sys_rxd.rec_buf[3])
{
case 0x44:
txd_sta();
break;
case 0x4f:
txd_uni(0x4f); //发送通讯协议版本号
break;
case 0x50:
txd_uni(0x50); //发送设备地址
break;
case 0x51:
txd_man(); //发送设备厂家信息
break;
case 0x60:
txd_uni(0x60); //系统初始化
break;
default:
txd_uni(0x04); //无效命令
break;
}
}
sys_rxd.frm_num--;
}
}
/*****************************************************************/
void init_serial(void)//初始化串口
{
//串行口波特率等设置
TMOD=0x21; // T1 mode 2 T0,mode 1 //GATE C/T M1 M0 GATE C/T M1 M0
TL1=0xfa; // 0xfa=4800 bps 0xfd=960
modbus完整协议源码(c/c++)
4星 · 超过85%的资源 需积分: 49 102 浏览量
2012-01-05
09:58:34
上传
评论 13
收藏 6KB RAR 举报
eriby
- 粉丝: 0
- 资源: 2
最新资源
- 自动驾驶-状态估计和定位之Error State EKF.pdf
- STM32F103ZET6+北斗
- 程序流程图的说明及图形示例
- FDN5618P-NL-VB一款SOT23封装P-Channel场效应MOS管
- Go语言基础(变量和基本类型).zip
- 基于CYCLONE2 (EP2C8Q) FPGA 设计PLL锁相环设置时钟Verilog源码Quartus工程文件.zip
- FDN372S-NL-VB一款SOT23封装N-Channel场效应MOS管
- date0425111111111111111111111
- 包含贪心算法的定义及python代码部分实现
- 自动驾驶-状态估计和定位之扩展卡尔曼滤波.pdf
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
- 4
- 5
- 6
前往页