📄 modbus_c_program.txt
字号:
tmp[1] = READ_HLD_REG;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
tmp[4] = HI(lenth);
tmp[5] = LOW(lenth);
tmp_lenth = 6;
construct_rtu_frm ( com_buf,tmp,tmp_lenth);
return 8;
}
// 4 发送读取模拟量输入
int ascii_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
{
unsigned char tmp[256], tmp_lenth;
tmp[0] = board_adr;
tmp[1] = READ_AI;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
tmp[4] = HI(lenth);
tmp[5] = LOW(lenth);
tmp_lenth = 6;
construct_ascii_frm ( com_buf, tmp, tmp_lenth);
return 18;
}
int rtu_read_anloginput( unsigned char board_adr,unsigned char *com_buf,int start_address,int lenth)
{
unsigned char tmp[256],tmp_lenth;
tmp[0] = board_adr;
tmp[1] = READ_AI;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
tmp[4] = HI(lenth);
tmp[5] = LOW(lenth);
tmp_lenth = 6;
construct_rtu_frm ( com_buf,tmp,tmp_lenth);
return 8;
}
/*
5 设置继电器
发送:status =0 继电器释放 否则继电器吸合,address 为吸合的继电器编号,0为第一个继电器,依次类推
*/
int ascii_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )
{
unsigned char tmp[256], tmp_lenth;
tmp[0] = board_adr;
tmp[1] = SET_COIL ;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
if ( status )
{
tmp[4] = 0xff;
tmp[5] = 0;
}
else
{
tmp[4]= 0;
tmp[5]= 0;
}
tmp_lenth = 6;
construct_ascii_frm ( com_buf, tmp, tmp_lenth);
return 18;
}
int rtu_set_coil ( unsigned char board_adr,unsigned char *com_buf,int start_address,int status )
{
unsigned char tmp[256], tmp_lenth;
tmp[0] = board_adr;
tmp[1] = SET_COIL ;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
if ( status )
{
tmp[4] = 0xff;
tmp[5] = 0;
}
else
{
tmp[4]= 0;
tmp[5]= 0;
}
tmp_lenth = 6;
construct_rtu_frm ( com_buf, tmp, tmp_lenth);
return 8 ;
}
/*
6 设置保持寄存器
*/
int ascii_set_hldreg( unsigned char board_adr,unsigned char *com_buf,int start_address,unsigned int value )
{
unsigned char tmp[256], tmp_lenth;
tmp[0] = board_adr;
tmp[1] = SET_HLD_REG;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
tmp[4] = HI(value);
tmp[5] = LOW(value);
tmp_lenth = 6;
construct_ascii_frm ( com_buf, tmp, tmp_lenth);
return 18;
}
int rtu_set_hldreg( unsigned char board_adr,unsigned char *com_buf, int start_address, unsigned int value )
{
unsigned char tmp[256], tmp_lenth;
tmp[0] = board_adr;
tmp[1] = SET_HLD_REG;
tmp[2] = HI(start_address);
tmp[3] = LOW(start_address);
tmp[4] = HI(value);
tmp[5] = LOW(value);
tmp_lenth = 6;
construct_rtu_frm ( com_buf, tmp, tmp_lenth);
return 8 ;
}
/*
7
接收分析:
dest_p 接收到数据指针
sourc_p 串口接收缓冲区指针
data_start_address 开始地址
*/
/* RTU 接收分析 */
int rtu_data_anlys( int *dest_p, unsigned char *source_p, int data_start_address, int fr_lenth)
{
unsigned short crc_result, crc_tmp;
unsigned char tmp1, tmp2, shift;
crc_tmp = *(source_p + fr_lenth-2); // crc 第一字节
crc_tmp = crc_tmp * 256 + *( source_p+fr_lenth-1); // CRC 值
crc_result = crc(source_p, fr_lenth-2); // 计算CRC 值
if ( crc_tmp != crc_result ) // CRC 校验正确
{
hld_reg[0x31]++;
return -1;
}
switch ( *(source_p+1) ) // 功能码
{
case READ_COIL: /*读取继电器状态 */
for ( tmp1=0; tmp1<*( source_p+2); tmp1++)
{
shift = 1;
for ( tmp2=0; tmp2<8; tmp2++)
{
*(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);
*( source_p+3) >>= 1;
}
}
break;
case READ_DI: /*读取开关量输入*/
for ( tmp1=0; tmp1<*( source_p+2); tmp1++)
{
shift = 1;
for (tmp2=0; tmp2<8; tmp2 ++)
{
*(dest_p+data_start_address+tmp1*8+tmp2) = shift & *( source_p+3);
*( source_p+3)>>=1;
}
}
break;
case READ_HLD_REG: /*读取保持寄存器*/
for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)
{
*(dest_p + data_start_address+ tmp1/2)= *( source_p+tmp1+3)*256 + *( source_p+tmp1+4) ;
}
break ;
case 4: /*读取模拟量输入*/
for ( tmp1=0; tmp1<*( source_p+2); tmp1+=2)
{
*(dest_p + data_start_address+ tmp1/2) = *( source_p+tmp1+3)*256 + *( source_p+tmp1+4) ;
}
break;
case PROTOCOL_EXCEPTION:
return -1*PROTOCOL_ERR;
//break;
default:
return -1*PROTOCOL_ERR;
// break;
}
return 0;
}
int ascii_data_anlys( int *dest_p,char *source_p,int data_start_address)
{
unsigned char tmp[256];
int lenth;
int tmp1, tmp2;
char shift;
lenth = asctortu(tmp, source_p);
if ( lenth==0) return -1* FRM_ERR;
switch (tmp[1] )
{
case READ_COIL: /*读取继电器状态 */
for ( tmp1=0; tmp1<tmp[2]; tmp1++)
{
shift = 1;
for ( tmp2=0; tmp2<8; tmp2++)
{
*(dest_p+data_start_address+tmp1*8+tmp2) = shift & tmp [tmp1+3];
tmp [tmp1+3] >>= 1;
}
}
break;
case READ_DI: /*读取开关量输入*/
for ( tmp1=0; tmp1<tmp[2]; tmp1++)
{
shift = 1;
for (tmp2=0; tmp2<8; tmp2 ++)
{
*(dest_p+data_start_address+tmp1*8+tmp2)= shift & tmp [tmp1+3];
tmp [tmp1+3]>>=1;
}
}
break;
case READ_HLD_REG: /*读取保持寄存器*/
for (tmp1=0; tmp1<tmp[2]; tmp1+=2)
{
*(dest_p + data_start_address+ tmp1/2) = tmp[tmp1+3]*256 + tmp[tmp1+4] ;
}
break ;
case 4: /*读取模拟量输入*/
for (tmp1=0; tmp1<tmp[2]; tmp1+=2)
{
*(dest_p+data_start_address+ tmp1/2) = tmp[tmp1+3]*256 + tmp[tmp1+4] ;
}
break;
case PROTOCOL_EXCEPTION:
return -1*PROTOCOL_ERR;
//break;
default:
break;
}
return 0;
}
/*
主程序按照一定的顺序调用 1~6子程序,然后把生成的缓存内容写入串口。
接收到数据送给7的子程序分析即可。
ASCII 方式下,用0X0D, 0X0A作为帧结束判断的依据
RTU方式下,以两个字节间的时间间隔大于3.5倍的一个字符周期为帧结束判断依据
READ() WRITE()是两个假想存在的函数 ,需要根据不同的系统来完成。
比如在单片机中,可能要用到中断模式;在LINUX下可能是一个阻塞的READ WRITE调用,在WINDOWS下可能是串口控件的READ WRITE 方法。。。。。
因为系统各式各样,所以只能抽象出一个假想的函数,由代码的使用者实现。
*/
/*void main ( void)
{
ascii_read_coil_status ( 1,tx_buf,0,8);
write (com1,tx_buf );
read (com1,rx_buf);
ascii_data_anlys( coil,rx_buf,0);
ascii_read_input_status ( 1,tx_buf,0,8);
write ( com1,tx_buf );
read (com1, rx_buf);
ascii_data_anlys( di,rx_buf,0);
ascii_read_hldreg ( 1,tx_buf,0,8);
write ( com1,tx_buf );
read (com1, rx_buf);
ascii_data_anlys( hld_reg,rx_buf,0);
ascii_read_anloginput( 1,tx_buf,0,8);
write ( com1,tx_buf );
read (com1, rx_buf);
ascii_data_anlys( ai,rx_buf,0);
ascii_set_coil (1,tx_buf,0,1); //第一个继电器吸合/
write ( com1,tx_buf );
read (com1, rx_buf);
ascii_data_anlys( di,rx_buf,0);
ascii_set_coil (1,tx_buf,0,0); //第一个继电器释放/
write ( com1,tx_buf );
read (com1, rx_buf);
ascii_data_anlys( di,rx_buf,0);
}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -