📄 modbusrxd.c
字号:
/*********************************************************************
* FileName : modbusrxd.c
* Author : Jack Zhang
* Date : 06/6/2008
*********************************************************************/
#include <psos.h>
#include <custom_defs.h>
#include <tmInterrupts.h>
#include <AppModel.h>
#include <stdio.h>
#include <string.h>
#include <tmNxTypes.h>
#include <tmDbg.h>
#include <tmosal.h>
#include <dprintf.h>
#include <tmbslCore.h>
#include <tmosal.h>
#include "modbus.h"
#include "..\..\nexper5.5\exProject\comps\Uart8004\src\uart_local.h"
#include "..\..\nexper5.5\exProject\comps\Uart8004\inc\uart.h"
#define DEBUG_MODBUS
//----------------公有变量------------------------------------
static unsigned int addr =1; //定义静态的地址变量,用于接收数据的地址校验,以及用户修改地址数据
unsigned char *mod_ascii =NULL;//接收modbus传送过来的字符,是BIT
unsigned char *mod_rtu =NULL; //接收rtu模式的数据
unsigned char **dframe =NULL;
unsigned char *chars;
extern int valid_data(unsigned char*, int,char); //提取有效数据
//-------------------------------------------------------------
//-------------公有函数-----------------------------------------
int process_rxd(Rn_Buffer_t *pRnBuf); //通信处理函数
void change_addr(int); //改变地址
//---------------------------------------------------------------
//---------------私有函数----------------------------------------
unsigned char lrc8(unsigned char *,unsigned short); //LRC校验
int len_check(unsigned char* ); //计算每个包中数据的长度,查看是否丢失数据
extern unsigned short crc16(unsigned char *,unsigned short); //CRC校验
int ch2ii (int dfnum); //将字符转换成整形数
//---------------------------------------------------------------
//-------------------更改设备地址-----------------------------
void change_addr(int num)
{
if((num>247||num<0))
printf("输入错误!请输入一个1--247之间的整数:");
else
addr = num;
}
//-----------------------------------------------------------------
//-------------------CRC校验-----------------------------
unsigned short crc16(unsigned char *puchMsg , unsigned short usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
unsigned short uIndex ; /* will index into CRC lookup table */
while (usDataLen--)/* pass through message buffer */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ aucrchi[uIndex];
uchCRCLo = aucrclo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//-----------------------------------------------------------------
//-------------------LRC校验-----------------------------
unsigned char lrc8(unsigned char *auchMsg_,unsigned short usDataLen_)
{
unsigned char uchLRC = 0 ; /* LRC 字节初始化 */
while (usDataLen_--) /* 传送消息 */
uchLRC += *auchMsg_++; /* 累加*/
return (((unsigned char)(~uchLRC+1)));
}
//-----------------------------------------------------------------
//-------------------字符转换函数-----------------------------------
int ch2ii (int dfnum)
{
int i,k;
for(i =0; i<22; i++)
{
if(dframe[dfnum][0] ==ch2i[i].ch)
{
break;
}
}
for(k =0; k<22; k++)
{
if(dframe[dfnum][1] ==ch2i[k].ch)
{
break;
}
}
return ((((ch2i[i].num)&0x0000000f)<<4)+((ch2i[k].num)&0x0000000f));
}
//-------------------------ASCII模式数据接收----------------
int ascii_rxd(Rn_Buffer_t *pRnBuf)
{
int length=RNBUF_LEN(pRnBuf);
unsigned char *pStart = pRnBuf->buf+pRnBuf->rd;
unsigned short ascii_oper; //操作码
int i,ascii_flag;//ascii_flag表识数据接收成功与否
int j=1;
char lrcch;
#ifdef DEBUG_MODBUS
printf("hello ascii world!\n");
printf("length =%d\n",length);
#endif
mod_ascii = (unsigned char *)malloc(length*sizeof(unsigned char));
if(mod_ascii == NULL)
{
printf("mod_ascii申请内存失败。\n");
}
memcpy(mod_ascii,pStart,length);
#ifdef DEBUG_MODBUS
for(i =0;i<length;i++)
printf("0x%x\n",mod_ascii[i]);
printf("\n");
#endif
dframe = (unsigned char **)malloc(((length)/2)*sizeof(unsigned char));
chars =(unsigned char *)malloc(((length)/2)*sizeof(unsigned char));
if(dframe == NULL)
{
printf("dframe申请内存失败。\n");
}
for(i =0;i<length/2;i++)
{
dframe[i] =(unsigned char*)malloc(2*sizeof(unsigned char));
dframe[i][0] =mod_ascii[j++];
dframe[i][1] =mod_ascii[j++];
}
for(i =0;i<length/2;i++)
{
chars[i] =ch2ii(i);
#ifdef DEBUG_MODBUS
printf("char[i] =0x%x\n",chars[i]);
#endif
}
if( FRAME_START == mod_ascii[0]) // 帧头检查,帧头一个字节
{
#ifdef DEBUG_MODBUS
printf("ascii rxd start ok\n");
#endif
if(addr ==(int)chars[0]) //地址检查,地址两个字节
{
#ifdef DEBUG_MODBUS
printf("ascii addr ok!\n");
#endif
lrcch =lrc8(chars,(length/2)-1);
#ifdef DEBUG_MODBUS
printf("lrc =0x%x\n",(lrcch&0x000000ff));
printf("chars[length/2-1] =0x%x\n",chars[length/2-1]);
printf("chars[length/2-1] =0x%x\n",chars[length/2-2]);
#endif
if( chars[length/2-1]== (lrcch&0x000000ff))//LRC检查,两个字节
{
#ifdef DEBUG_MODBUS
printf("ascii lrc ok!\n");
#endif
ascii_oper =chars[1]; //取操作码两个字节
//packs_num = PACKINTS(dframe[6],dframe[5]); //取数据包量两个字节
// if(packs_num == packnum_check(dframe,length))
// {
ascii_flag =valid_data(chars,length,'a'); //取有效数据
//}
//else
// _send(addr , "长度校验有误!");
}
else
error_send(addr , mod_ascii,'a');
}
//地址不正确,不进行接收数据
}
else
error_send(addr,mod_ascii,'a');
if(ascii_flag ==0)
ok_send(addr,mod_ascii,'a');
else
error_send(addr , mod_ascii,'a');
for(i =0; i<length/2; i++)
{
free(*dframe[i]);
*dframe[i] =NULL;
}
free(mod_ascii);
mod_ascii =NULL;
return (pRnBuf->rd+length);
}
//-------------------------------------------------------------
//-------------------------RTU模式数据接收----------------
int rtu_rxd(Rn_Buffer_t *pRnBuf)
{
int length=RNBUF_LEN(pRnBuf);
unsigned char *pStart = pRnBuf->buf+pRnBuf->rd;
unsigned char rtu_oper; //操作码
int i,rtu_flag; //rtu_flag表识接收数据成功与否
int crcci;
#ifdef DEBUG_MODBUS
printf("rtu_rxd ok!\n");
printf("length =%d\n",length);
#endif
mod_rtu = (unsigned char *)malloc(length*sizeof(unsigned char));
if(mod_rtu == NULL)
{
printf("mod_rtu申请内存失败。\n");
}
memcpy(mod_rtu,pStart,length);
for(i =0;i<length;i++)
#ifdef DEBUG_MODBUS
printf("0x%x\n",mod_rtu[i]);
printf("\n");
#endif
if(addr ==mod_rtu[0]) //地址检查
{
#ifdef DEBUG_MODBUS
printf("addr ok!\n");
#endif
crcci =crc16(mod_rtu,length-2);
#ifdef DEBUG_MODBUS
printf("crc =0x%x\n",(crcci&0x0000ffff));
printf("crc2 =0x%x\n",mod_rtu[length-1]<<8|mod_rtu[length-2]);
#endif
if(mod_rtu[length-1]<<8|mod_rtu[length-2]== (crcci&0x0000ffff))//CRC检查 {
#ifdef DEBUG_MODBUS
printf("crc ok!\n");
#endif
rtu_oper =mod_rtu[1]; //取操作码两个字节
//packs_num = PACKINTS(dframe[6],dframe[5]); //取数据包量两个字节
// if(packs_num == packnum_check(dframe,length))
// {
rtu_flag =valid_data(mod_rtu,length-2,'r'); //取有效数据
//}
//else
// _send(addr , "长度校验有误!");
}
else
error_send(addr,mod_rtu,'r');
}
//地址不正确,不进行接收数据
if(rtu_flag ==0)
error_send(addr,mod_rtu,'r');
else
ok_send(addr,mod_rtu,'r');
free(mod_rtu);
mod_rtu =NULL;
return (pRnBuf->rd+length);
}
//-------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -