⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbusrxd.c

📁 一个关于MODBUS方面的程序
💻 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 + -