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

📄 modbusa.h

📁 西门子PPI协议源码
💻 H
📖 第 1 页 / 共 2 页
字号:
	
	if(uc_is_excep) //如果有异常
	{
		*(puc_send_buf + --ucp_send_count) = *(puc_rec_buf + 1) + 0x80;//功能码加0x80
		ucp_send_count++;
		*(puc_send_buf + ucp_send_count++) = uc_excep_code;
	}
	
	if(is_modbus_asc)
	{
	    ucp_send_count = convert_rtu_to_ascii(puc_send_buf,ucp_send_count);    
	}
	else
	{
	    u16 = CRC16(puc_send_buf,ucp_send_count);//CRC效验,传的是数组的个数
	    *(puc_send_buf + ucp_send_count++) = (LO_UINT(u16));
	    *(puc_send_buf + ucp_send_count)   = (HI_UINT(u16));
	}
	
	return(ucp_send_count);	//返回的是下标,这是发送中断所确定的
}

#ifdef OP_TB_WRITE_REG
//**************************************************************************
//**Purpose:
//**        以下是自己发出了读PLC内部变量的命令03,PLC返回了数据,填写入自己的内存
void write_word_by_plc(uint ui_word_address,uchar uc_word_len,uchar *dat)
{
	uchar uc_i;
	uint ui_mid;
	
	for(uc_i = 0; uc_i<uc_word_len; uc_i++)
	{
		ui_mid = *dat; 
		dat++; 
		ui_mid<<=8;
		ui_mid |= *dat;
		dat++;
		
		Rtu_write_singleReg(ui_word_address+uc_i,ui_mid);
	}
}
#endif  //**end(#ifdef OP_TB_WRITE_REG)



//*****************************************************************************************
//**Purpose:当modbus为主时,分析接收帧,并根据接收帧作相应处理.
//**Entry: puc_rec_buf:---指向接收缓冲. uc_rec_len:---接收缓冲的长.uc_op_table_pos:指向发送命令表的下标。
void rtu_reqframe_anlys_master(UCHAR* puc_rec_buf,UCHAR uc_rec_len,UCHAR uc_op_table_pos)
{
    UCHAR uc_func_code,uc_bytes;
	
	if(is_modbus_asc) //modbus为asc模式
	{   
	    uc_func_code = 	MAKE_HEX_TO_DEC(*(puc_rec_buf+uc_rec_len-2),*(puc_rec_buf+uc_rec_len-1));
		uc_rec_len   =  convert_ascii_to_rtu(puc_rec_buf,uc_rec_len-2,0); //不包含crc校验
        if(uc_func_code != lrc(puc_rec_buf,uc_rec_len))
		{
		    return ;
		}
	}
	else             //modbus为rtu模式
	{
	    if(CRC16(puc_rec_buf,uc_rec_len-2) != (puc_rec_buf[uc_rec_len-1]<<8 |puc_rec_buf[uc_rec_len-2]))//效验出错
	    {
           return;
	    }  
    }
	
	if(*(puc_rec_buf +1) != (uc_func_code = stMod_Master_OP[uc_op_table_pos].uc_cmd))//功能码不同
	{
        return;
	}
	
    uc_bytes = (uc_func_code == 0x01 || uc_func_code == 0x02)?((stMod_Master_OP[uc_op_table_pos].uc_lenth -1)/8+1):(stMod_Master_OP[uc_op_table_pos].uc_lenth*2);
    if(uc_bytes != *(puc_rec_buf + 2)) //如果长度不同
	{
        return;
	}
	
    switch(uc_func_code) //功能码
	{
    #ifdef MB_MST_BIT_READ_EN  
	case MB_READ_COIL: //coil
	case MB_READ_DISCRETE:
		write_bit_by_plc(stMod_Master_OP[uc_op_table_pos].ui_mem_begin_addr,
			stMod_Master_OP[uc_op_table_pos].uc_lenth,puc_rec_buf+3);
		break;
    #endif //**end(#ifdef MB_MST_BIT_READ_EN )
	
	#ifdef MB_MST_REG_READ_EN
	case MB_READ_HOLD_REG:
	case MB_READ_INPUT_REG:
	
	     write_word_by_plc(	stMod_Master_OP[uc_op_table_pos].ui_mem_begin_addr,
			stMod_Master_OP[uc_op_table_pos].uc_lenth,puc_rec_buf+3);	                
		  break;
    #endif //**end(#ifdef MB_MST_REG_READ_EN)
	
	#ifdef MB_MST_REG_RW_EN
	case MB_READ_WRITE_REG:
		write_word_by_plc(	stMod_Master_OP[uc_op_table_pos].ui_mem_begin_addr,
			stMod_Master_OP[uc_op_table_pos].uc_lenth,puc_rec_buf+3);	                
		
		break;
	#endif //**end(#ifdef MB_MST_REG_RW_EN)
	default:
		break;
		
	}
}
///////////////////////////////////////////////////////////////////////////////
//以下是自己发出了写PLC内部Word/bit的命令0x10/0x0F,组成发送数据串,返回串长度
///////////////////////////////////////////////////////////////////////////////
uchar rtu_modbus_master_send(uchar uc_op_table_xb,uchar uc_plc_address,uchar *puc_send_buf)
{
	uchar uc_mid,uc_h,uc_l;
	uint  ui_mid,ui_mem_begin_addr;
	UCHAR ucp_send_count = 0;
	
	*(puc_send_buf + ucp_send_count++) = uc_plc_address;  //address
	uc_mid = stMod_Master_OP[uc_op_table_xb].uc_cmd;
	*(puc_send_buf + ucp_send_count++) = uc_mid;//stMod_Master_OP[uc_op_table_xb].uc_cmd; //func code
	ui_mid = stMod_Master_OP[uc_op_table_xb].ui_plc_begin_addr;
	*(puc_send_buf + ucp_send_count++) = ui_mid >>8;  //start address
	*(puc_send_buf + ucp_send_count++) = (uchar)ui_mid;
	
	switch(uc_mid)
	{
    
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
		*(puc_send_buf + ucp_send_count++) = 0;
		*(puc_send_buf + ucp_send_count++) = stMod_Master_OP[uc_op_table_xb].uc_lenth;
		break;
	#ifdef MB_MST_BIT_WRITE_EN
	case 0x05: //写单个位
		*(puc_send_buf + ucp_send_count++) = rtu_read_bits(stMod_Master_OP[uc_op_table_xb].ui_mem_begin_addr,1)>0?0xff:0;
		*(puc_send_buf + ucp_send_count++) = 0;
		break;
	case 0x0f://写多个位
		uc_h = (stMod_Master_OP[uc_op_table_xb].uc_lenth-1)/8;
		uc_l = (stMod_Master_OP[uc_op_table_xb].uc_lenth-1)%8;
		*(puc_send_buf + ucp_send_count++) = 0;
		*(puc_send_buf + ucp_send_count++) = stMod_Master_OP[uc_op_table_xb].uc_lenth; 
		*(puc_send_buf + ucp_send_count++) = uc_h + 1;
		ui_mid = stMod_Master_OP[uc_op_table_xb].ui_mem_begin_addr;
		for(uc_mid = 0;uc_mid < uc_h;uc_mid++)
		{
			*(puc_send_buf + ucp_send_count++) = rtu_read_bits( ui_mid+ uc_mid*8,8);
		}
		*(puc_send_buf +ucp_send_count++) = rtu_read_bits(ui_mid + uc_mid*8,uc_l+1);
		break;
	#endif  //**end(#ifdef MB_MST_BIT_WRITE_EN)
	
	#ifdef MB_MST_REG_WRITE_EN
	case 0x06: //写单个寄存器
		ui_mid = ui_RTU_ret_Word(stMod_Master_OP[uc_op_table_xb].ui_mem_begin_addr);
		*(puc_send_buf + ucp_send_count++) = ui_mid>>8;
		*(puc_send_buf + ucp_send_count++) = (uchar)ui_mid;
		break;
	case MB_WRITE_MULTI_REG: //写多个寄存器
		*(puc_send_buf + ucp_send_count++) = 0;
		*(puc_send_buf + ucp_send_count++) = stMod_Master_OP[uc_op_table_xb].uc_lenth; 
		*(puc_send_buf + ucp_send_count++) = stMod_Master_OP[uc_op_table_xb].uc_lenth<<1;
		uc_l = stMod_Master_OP[uc_op_table_xb].uc_lenth;
		ui_mem_begin_addr = stMod_Master_OP[uc_op_table_xb].ui_mem_begin_addr;
		for(uc_mid=0;uc_mid<uc_l;uc_mid++)
		{
			ui_mid = ui_RTU_ret_Word( ui_mem_begin_addr+ uc_mid);
			*(puc_send_buf + ucp_send_count++) = ui_mid>>8;
			*(puc_send_buf + ucp_send_count++) = (uchar)ui_mid;
		}
		break;
	#endif //**(#ifdef MB_MST_REG_WRITE_EN)
	
	#ifdef MB_MST_REG_RW_EN
	  case 0x17: //写读多个寄存器
	    ui_mem_begin_addr = stMod_Master_OP[uc_op_table_xb].ui_write_plc_addr;
		*(puc_send_buf + ucp_send_count++) = 0;
		*(puc_send_buf + ucp_send_count++) = stMod_Master_OP[uc_op_table_xb].uc_lenth;//读的个数 
		*(puc_send_buf + ucp_send_count++) = ui_mem_begin_addr>>8;   //写的开始地址
		*(puc_send_buf + ucp_send_count++) = (uchar)ui_mem_begin_addr;
		uc_l = stMod_Master_OP[uc_op_table_xb].uc_write_len;
		*(puc_send_buf + ucp_send_count++) = 0;               //写的数量
		*(puc_send_buf + ucp_send_count++) = uc_l;
		*(puc_send_buf + ucp_send_count++) = uc_l<<1;          //写的字节数
		ui_mem_begin_addr                  = stMod_Master_OP[uc_op_table_xb].ui_write_mem_addr;
		for(uc_mid=0;uc_mid<uc_l;uc_mid++)
		{
			ui_mid = ui_RTU_ret_Word( ui_mem_begin_addr+ uc_mid);
			*(puc_send_buf + ucp_send_count++) = ui_mid>>8;
			*(puc_send_buf + ucp_send_count++) = (uchar)ui_mid;
		}
		break;
	#endif //**end(#ifdef MB_MST_REG_RW_EN)
	default:
		break;
	}
	
	if(is_modbus_asc)
	{
	    ucp_send_count = convert_rtu_to_ascii(puc_send_buf,ucp_send_count);
	}
	else
	{
	    ui_mid = CRC16(puc_send_buf,ucp_send_count);//CRC效验,传的是数组的个数 
	    *(puc_send_buf + ucp_send_count++) = ui_mid & 0x00ff;
	    *(puc_send_buf + ucp_send_count) = (uchar)(ui_mid>>8);
	}
	
	return(ucp_send_count);	//返回的是下标,这是发送中断所确定的
}

//*******************************************************************
//**Purpose: 将modbus的rtu帧转化为asc码,rtu中不包含crc。
//**Entry:   uc_bytes:--指定缓冲的字节数
//**Return:  返回的是下标,而不是字节数.
UCHAR convert_rtu_to_ascii(UCHAR* puc_buf,UCHAR uc_bytes)
{   
    UCHAR uc_pos,uc_index,uc_value,uc_lrc;
	UCHAR* puc_src_buf,*puc_dst_buf;
    UCHAR uc_temp_buf[comm_array_max_xb+1];
	uc_pos  = 0;
	
	uc_lrc      = lrc(puc_buf,uc_bytes);
	puc_src_buf = puc_buf;
	puc_dst_buf = uc_temp_buf;
	uc_index    = uc_bytes;
	while(uc_index--)
	{
	  *puc_dst_buf++ = *puc_src_buf++;
	}
    
	*(puc_buf + uc_pos++) = MB_HEAD_ASCII; //帧头
	
    for(uc_index = 0;uc_index < uc_bytes;uc_index++)
	{   
	    uc_value = uc_temp_buf[uc_index];
	    *(puc_buf + uc_pos++) = HI_UCHAR_TO_HEX(uc_value);
		*(puc_buf + uc_pos++) = LO_UCHAR_TO_HEX(uc_value);    
	}
	
	*(puc_buf + uc_pos++) = HI_UCHAR_TO_HEX(uc_lrc);//lrc 高
	*(puc_buf + uc_pos++) = LO_UCHAR_TO_HEX(uc_lrc);//lrc 低
	*(puc_buf + uc_pos++) = MB_PRE_END_ASCII;         //pre end
	*(puc_buf + uc_pos)   = MB_END_ASCII;             //end
     
	return uc_pos;	
}

//***************************************************************
//**Purpose: 将modbus的ascii帧转化为rtu帧.不包含头.uc_is_crc为0无crc效验,否则有crc效验。
UCHAR convert_ascii_to_rtu(UCHAR* puc_buf,UCHAR uc_bytes,UCHAR uc_is_crc)
{   
    UCHAR uc_index;
	UINT  ui_crc;
	UCHAR_PDATA uc_temp_buf[comm_array_max_xb+1];  
	UCHAR_PDATA * puc_src_buf,*puc_dst_buf;
	
	puc_src_buf = puc_buf;
	puc_dst_buf = uc_temp_buf;
	uc_index    = uc_bytes;
	while(uc_index--)
	{
		*puc_dst_buf++ = *puc_src_buf++;
	}
    
	puc_dst_buf = puc_buf;
	for(uc_index = 0;uc_index < uc_bytes;uc_index++)
	{
		*puc_dst_buf++ = MAKE_HEX_TO_DEC(uc_temp_buf[uc_index],uc_temp_buf[uc_index+1]);
		uc_index++;
	}
    
	uc_bytes = uc_bytes / 2;
	if(uc_is_crc)
	{
        ui_crc = CRC16(puc_buf,uc_bytes);
    	*puc_dst_buf++ = LO_UINT(ui_crc);
		*puc_dst_buf   = HI_UINT(ui_crc);
		uc_bytes       += 2;
	}
	return uc_bytes;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -