895 lines
50 KiB
C
895 lines
50 KiB
C
#include "modbus.h"
|
||
/*--------------------------------------变量定义-----------------------------------*/
|
||
emu16 fast_type ecbm_modbus_rtu_crc =0xFFFF; //初始化CRC变量各位为1。
|
||
emu8 fast_type ecbm_modbus_rtu_status =ECBM_MODBUS_RTU_READY; //状态机使用的变量。
|
||
emu8 fast_type ecbm_modbus_rtu_id =ECBM_MODBUS_RTU_ID_ADRESS; //本机的设备ID。
|
||
emu8 fast_type ecbm_modbus_rtu_fun_code =0; //功能码。
|
||
emu8 fast_type ecbm_modbus_rtu_fun_err_num =0; //异常码。
|
||
emu16 fast_type ecbm_modbus_rtu_address =0; //数据地址。
|
||
emu16 fast_type ecbm_modbus_rtu_data_count =0; //数据/个数。
|
||
emu16 fast_type ecbm_modbus_rtu_crc_buf =0; //CRC缓存。
|
||
emu16 fast_type ecbm_modbus_rtu_timeout =0; //超时计算。
|
||
emu16 fast_type ecbm_modbus_rtu_uart_crc =0xFFFF; //CRC计算缓存。
|
||
emu8 fast_type ecbm_modbus_rtu_cmd_count =0; //指令缓存计数。
|
||
emu8 fast_type ecbm_modbus_rtu_broadcast_en =0; //广播模式。
|
||
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
emu8 large_type ecbm_modbus_rtu_bit_buf[ECBM_MODBUS_RTU_BIT_BUF_SIZE]; //比特线圈存放变量。
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
emu16 large_type ecbm_modbus_rtu_reg_buf[ECBM_MODBUS_RTU_REG_BUF_SIZE]; //寄存器存放变量。
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
emu16 large_type ecbm_modbus_rtu_cmd_buf[ECBM_MODBUS_RTU_BUF_SIZE]; //指令缓存。
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
CRC16计算函数。
|
||
-------------------------------------------------------*/
|
||
void ecbm_modbus_rtu_crc16(emu8 buf){
|
||
emu8 j;
|
||
ecbm_modbus_rtu_crc^=buf; //当前数据异或CRC低字节,在C51里可以直接处理。
|
||
for(j=0;j<8;j++){ //计算每个字节的每一位。
|
||
if(ecbm_modbus_rtu_crc&0x01){ //判断右移前最低位是否为1。
|
||
ecbm_modbus_rtu_crc=(ecbm_modbus_rtu_crc>>1)^0xA001;//如果为1则右移并异或表达式。
|
||
}else{
|
||
ecbm_modbus_rtu_crc>>=1; //否则直接右移一位。
|
||
}
|
||
}
|
||
}
|
||
/*-------------------------------------------------------
|
||
检测功能码函数。
|
||
-------------------------------------------------------*/
|
||
emu8 ecbm_modbus_rtu_check_fun_num(emu8 fun_num){
|
||
switch(fun_num){
|
||
/*-------------------------------------------------
|
||
0x02|读离散量输入 |物理离散量输入 | |
|
||
----+-------------+------------------| |
|
||
0x01|读线圈 | | |
|
||
----+--------------| | 比特访问 |
|
||
0x05|写单个线圈 |内部比特或物理线圈 | |
|
||
----+--------------| | |
|
||
0x0F|写多个线圈 | | |
|
||
----+--------------+-----------------+-------------|
|
||
0x04|读输入寄存器 |输入寄存器 | |
|
||
----+--------------+-----------------| |
|
||
0x03|读多个寄存器 | | |
|
||
----+--------------| | |
|
||
0x06|写单个寄存器 | | |
|
||
----+--------------| | |
|
||
0x10|写多个寄存器 |内部储存器或物理 | 16比特访问 |
|
||
----+--------------|输出寄存器 | |
|
||
0x17|读/写多个寄存器| | |
|
||
----+--------------| | |
|
||
0x16|屏蔽写寄存器 | | |
|
||
----+--------------| | |
|
||
0x18|读FIFO队列 | | |
|
||
-------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD01_EN
|
||
case 0x01://读线圈
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD02_EN
|
||
case 0x02://读离散量输入
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD05_EN
|
||
case 0x05://写单个线圈
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD04_EN
|
||
case 0x04://读输入寄存器
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD03_EN
|
||
case 0x03://读多个寄存器
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD06_EN
|
||
case 0x06://写单个寄存器
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
case 0x10://写多个寄存器
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD_ALL_EN
|
||
{return fun_num;}break;//支持的功能码就返回本身。
|
||
#endif
|
||
default:{return 0x80+fun_num;}break;//不支持的功能码就返回0x80+功能码。
|
||
}
|
||
}
|
||
/*-------------------------------------------------------
|
||
写比特数据函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
void ecbm_modbus_cmd_write_bit(emu16 addr,emu8 dat){
|
||
emu8 temp;
|
||
temp=addr%8;
|
||
if(dat){
|
||
ecbm_modbus_rtu_bit_buf[addr/8]|= (0x01<<temp);
|
||
}else{
|
||
ecbm_modbus_rtu_bit_buf[addr/8]&=~(0x01<<temp);
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
读比特数据函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
void ecbm_modbus_cmd_read_bit(emu16 addr,emu8 * dat){
|
||
emu8 temp;
|
||
temp=addr%8;
|
||
if((ecbm_modbus_rtu_bit_buf[addr/8])&(0x01<<temp)){
|
||
*dat=0x01;
|
||
}else{
|
||
*dat=0x00;
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
写寄存器数据函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
void ecbm_modbus_cmd_write_reg(emu16 addr,emu16 dat){
|
||
ecbm_modbus_rtu_reg_buf[addr]=dat;
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
读寄存器函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
void ecbm_modbus_cmd_read_reg(emu16 addr,emu16 * dat){
|
||
*dat=ecbm_modbus_rtu_reg_buf[addr];
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
1号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD01_EN
|
||
void ecbm_modbus_rtu_cmd_0x01(void){
|
||
emu8 temp8,t1,c1,i,j,qw;
|
||
emu16 temp16;
|
||
ecbm_modbus_rtu_crc= 0xFFFF;
|
||
if((ecbm_modbus_rtu_data_count>=1)&&(ecbm_modbus_rtu_data_count<=0x07D0)){ //读取的个数要在1个以上,且不能大于2000。
|
||
if(((emu32)ecbm_modbus_rtu_data_count+(emu32)ecbm_modbus_rtu_address)<=65536UL){ //判断地址+个数有没有超限。
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
if( //遇到以下问题,说明写入肯定会失败。
|
||
(ecbm_modbus_rtu_address<ECBM_MODBUS_RTU_BIT_START_ADDR)|| //输入地址比起始地址还小的,
|
||
(ecbm_modbus_rtu_address+ecbm_modbus_rtu_data_count)>(ECBM_MODBUS_RTU_BIT_BUF_SIZE*8+ECBM_MODBUS_RTU_BIT_START_ADDR)//输入的地址+输入的数量超过本机定义的数量。
|
||
){
|
||
ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x81);
|
||
ecbm_modbus_rtu_crc16(0x04);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x81); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
#else
|
||
if(0){ //如果是不用内置数组缓存的话,只要地址在范围内,无论是多少都是被允许的。
|
||
#endif
|
||
}else{
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
t1=(emu8)(ecbm_modbus_rtu_data_count/8); //统计要读取的数据能凑够多少个字节。
|
||
if(ecbm_modbus_rtu_data_count%8)t1++; //剩下的不足8位的数据也要一个字节来传输。
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
temp16=ecbm_modbus_rtu_address-ECBM_MODBUS_RTU_BIT_START_ADDR; //获取数据起始地址。
|
||
#else
|
||
temp16=ecbm_modbus_rtu_address; //获取数据起始地址。
|
||
#endif
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x01);
|
||
ecbm_modbus_rtu_crc16(t1);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x01); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data(t1); //发送数据长度。
|
||
for(i=0;i<t1;i++){ //从起始位置开始组装数据。
|
||
temp8=0; //清零变量。
|
||
if(ecbm_modbus_rtu_data_count>=8){ //如果剩余要读的数据多于8个比特。
|
||
c1=8; //那么本轮循环先读8比特数据。
|
||
}else{ //否则,
|
||
c1=(emu8)ecbm_modbus_rtu_data_count; //就有多少读多少。
|
||
}
|
||
for(j=0;j<c1;j++){
|
||
ecbm_modbus_cmd_read_bit(temp16++,&qw);//将地址送到读取函数中,获取对应的比特值。
|
||
temp8|=(qw<<j); //组装数据。
|
||
}
|
||
ecbm_modbus_rtu_crc16(temp8); //计算CRC。
|
||
ecbm_modbus_rtu_set_data(temp8); //发送组装好的数据。
|
||
ecbm_modbus_rtu_data_count-=(emu16)c1; //计算剩下要读的数据个数。
|
||
}
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果地址+个数超过2000。
|
||
ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x81);
|
||
ecbm_modbus_rtu_crc16(0x02);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x81); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果个数本身就超过2000了。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x81);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x81); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
2号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD02_EN
|
||
void ecbm_modbus_rtu_cmd_0x02(void){
|
||
emu8 temp8,t1,c1,i,j,qw;
|
||
emu16 temp16;
|
||
ecbm_modbus_rtu_crc= 0xFFFF;
|
||
if((ecbm_modbus_rtu_data_count>=1)&&(ecbm_modbus_rtu_data_count<=0x07D0)){ //读取的个数要在1个以上,且地址不能大于2000。
|
||
if(((emu32)ecbm_modbus_rtu_data_count+(emu32)ecbm_modbus_rtu_address)<=65536UL){ //判断地址+个数有没有超限。
|
||
// if(0){//如果内部没有定义那么多的比特位。
|
||
// ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
// if(ecbm_modbus_rtu_broadcast_en){
|
||
// ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
// ecbm_modbus_rtu_crc16(0x82);
|
||
// ecbm_modbus_rtu_crc16(0x04);
|
||
// ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
// ecbm_modbus_rtu_set_data(0x82); //发送0x80+功能码回复。
|
||
// ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
// }
|
||
// }else{
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
t1=(emu8)(ecbm_modbus_rtu_data_count/8); //统计要读取的数据能凑够多少个字节。
|
||
if(ecbm_modbus_rtu_data_count%8)t1++; //剩下的不足8位的数据也要一个字节来传输。
|
||
temp16=ecbm_modbus_rtu_address; //获取数据起始地址。
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x02);
|
||
ecbm_modbus_rtu_crc16(t1);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x02); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data(t1); //发送数据长度。
|
||
for(i=0;i<t1;i++){ //从起始位置开始组装数据。
|
||
temp8=0; //清零变量。
|
||
if(ecbm_modbus_rtu_data_count>=8){ //如果剩余要读的数据多于8个比特。
|
||
c1=8; //那么本轮循环先读8比特数据。
|
||
}else{ //否则,
|
||
c1=(emu8)ecbm_modbus_rtu_data_count; //就有多少读多少。
|
||
}
|
||
for(j=0;j<c1;j++){
|
||
ecbm_modbus_cmd_read_io_bit(temp16++,&qw);//将地址送到读取函数中,获取对应的比特值。
|
||
temp8|=(qw<<j); //组装数据。
|
||
}
|
||
ecbm_modbus_rtu_crc16(temp8); //计算CRC。
|
||
ecbm_modbus_rtu_set_data(temp8); //发送组装好的数据。
|
||
ecbm_modbus_rtu_data_count-=(emu16)c1; //计算剩下要读的数据个数。
|
||
}
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
// }
|
||
}else{ //如果地址+个数超过2000。
|
||
ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x82);
|
||
ecbm_modbus_rtu_crc16(0x02);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x82); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果个数本身就超过2000了。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x82);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x82); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
3号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD03_EN
|
||
void ecbm_modbus_rtu_cmd_0x03(void){
|
||
emu16 temp16,i;
|
||
ecbm_modbus_rtu_crc=0xffff;
|
||
if((ecbm_modbus_rtu_data_count>=1)&&(ecbm_modbus_rtu_data_count<=0x007D)){ //读取的个数要在1个以上,且地址不能大于125。
|
||
if(((emu32)ecbm_modbus_rtu_data_count+(emu32)ecbm_modbus_rtu_address)<65536UL){ //判断地址+个数有没有超限。
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
if( //遇到以下问题,说明写入肯定会失败。
|
||
(ecbm_modbus_rtu_address<ECBM_MODBUS_RTU_REG_START_ADDR)|| //输入地址比起始地址还小的,
|
||
(ecbm_modbus_rtu_address+ecbm_modbus_rtu_data_count)>(ECBM_MODBUS_RTU_REG_BUF_SIZE+ECBM_MODBUS_RTU_REG_START_ADDR)//输入的地址+输入的数量超过本机定义的数量。
|
||
){
|
||
ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x83);
|
||
ecbm_modbus_rtu_crc16(0x04);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x83); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
#else
|
||
if(0){
|
||
#endif
|
||
}else{
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_data_count*2);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x03); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_data_count*2);//发送回复字节数。
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
ecbm_modbus_rtu_address-=ECBM_MODBUS_RTU_REG_START_ADDR;
|
||
#endif
|
||
for(i=0;i<ecbm_modbus_rtu_data_count;i++){
|
||
ecbm_modbus_cmd_read_reg(ecbm_modbus_rtu_address+i,&temp16);//从寄存器变量里把数据取出来。
|
||
ecbm_modbus_rtu_crc16((emu8)(temp16>>8)); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16((emu8)(temp16));
|
||
ecbm_modbus_rtu_set_data((emu8)(temp16>>8));//发送数据。
|
||
ecbm_modbus_rtu_set_data((emu8)(temp16));
|
||
}
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{
|
||
ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x83);
|
||
ecbm_modbus_rtu_crc16(0x02);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x83); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果个数本身就超过125了。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x83);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x83); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
4号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD04_EN
|
||
void ecbm_modbus_rtu_cmd_0x04(void){
|
||
emu16 temp16,i;
|
||
ecbm_modbus_rtu_crc=0xffff;
|
||
if((ecbm_modbus_rtu_data_count>=1)&&(ecbm_modbus_rtu_data_count<=0x007D)){ //读取的个数要在1个以上,且地址不能大于125。
|
||
if(((emu32)ecbm_modbus_rtu_data_count+(emu32)ecbm_modbus_rtu_address)<65536UL){ //判断地址+个数有没有超限。
|
||
// if(0){//如果内部没有定义那么多的寄存器。
|
||
// ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
// if(ecbm_modbus_rtu_broadcast_en){
|
||
// ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
// ecbm_modbus_rtu_crc16(0x84);
|
||
// ecbm_modbus_rtu_crc16(0x04);
|
||
// ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
// ecbm_modbus_rtu_set_data(0x84); //发送0x80+功能码回复。
|
||
// ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
// }
|
||
// }else{
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x04);
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_data_count*2);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x04); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_data_count*2);//发送回复字节数。
|
||
for(i=0;i<ecbm_modbus_rtu_data_count;i++){
|
||
ecbm_modbus_cmd_read_io_reg(ecbm_modbus_rtu_address+i,&temp16);//从寄存器变量里把数据取出来。
|
||
ecbm_modbus_rtu_crc16((emu8)(temp16>>8)); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16((emu8)(temp16));
|
||
ecbm_modbus_rtu_set_data((emu8)(temp16>>8));//发送数据。
|
||
ecbm_modbus_rtu_set_data((emu8)(temp16));
|
||
}
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
// }
|
||
}else{
|
||
ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x84);
|
||
ecbm_modbus_rtu_crc16(0x02);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id);//发送地址。
|
||
ecbm_modbus_rtu_set_data(0x84); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果个数本身就超过125了。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x84);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x84); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
5号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD05_EN
|
||
void ecbm_modbus_rtu_cmd_0x05(void){
|
||
ecbm_modbus_rtu_crc=0xffff;
|
||
if((ecbm_modbus_rtu_data_count==0x0000)||(ecbm_modbus_rtu_data_count==0xFF00)){//判断输出值是否合法。
|
||
// if((ecbm_modbus_rtu_address>=0)&&(ecbm_modbus_rtu_address<=65535)){//其实能传进来的地址都符合这个范围,所以在这里优化掉了。
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
if( //遇到以下问题,说明写入肯定会失败。
|
||
(ecbm_modbus_rtu_address<ECBM_MODBUS_RTU_BIT_START_ADDR)|| //输入地址比起始地址还小的,
|
||
(ecbm_modbus_rtu_address>=(ECBM_MODBUS_RTU_BIT_BUF_SIZE*8+ECBM_MODBUS_RTU_BIT_START_ADDR))//输入地址比总的设计地址还大的,
|
||
){
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x85);
|
||
ecbm_modbus_rtu_crc16(0x04);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x85); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
#else
|
||
if(0){ //如果是不用内置数组缓存的话,只要地址在范围内,无论是多少都是被允许的。
|
||
#endif
|
||
}else{
|
||
#if ECBM_MODBUS_RTU_BIT_BUF_EN
|
||
ecbm_modbus_cmd_write_bit(ecbm_modbus_rtu_address-ECBM_MODBUS_RTU_BIT_START_ADDR,(emu8)(ecbm_modbus_rtu_data_count>>8));
|
||
#else
|
||
ecbm_modbus_cmd_write_bit(ecbm_modbus_rtu_address,(emu8)(ecbm_modbus_rtu_data_count>>8));
|
||
#endif
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x05);
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_address>>8));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_data_count>>8));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x05); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address>>8)); //发送地址回复。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count>>8));//发送计数回复。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
// }else{
|
||
// ecbm_modbus_rtu_fun_err_num=0x02; //异常码02。
|
||
// if(ecbm_modbus_rtu_broadcast_en){
|
||
// ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
// ecbm_modbus_rtu_crc16(0x85);
|
||
// ecbm_modbus_rtu_crc16(0x02);
|
||
// ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
// ecbm_modbus_rtu_set_data(0x85); //发送0x80+功能码回复。
|
||
// ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
// }
|
||
// }
|
||
}else{ //如果不合法。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x85);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x85); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
6号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD06_EN
|
||
void ecbm_modbus_rtu_cmd_0x06(void){
|
||
ecbm_modbus_rtu_crc=0xffff;
|
||
// if((ecbm_modbus_rtu_data_count>=0x0000)&&(ecbm_modbus_rtu_data_count<=0xFFFF)){//其实能传进来的数据都符合这个范围,所以在这里优化掉了。
|
||
// if((ecbm_modbus_rtu_address>=0)&&(ecbm_modbus_rtu_address<=65536UL)){//其实能传进来的地址都符合这个范围,所以在这里优化掉了。
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
if( //遇到以下问题,说明写入肯定会失败。
|
||
(ecbm_modbus_rtu_address<ECBM_MODBUS_RTU_REG_START_ADDR)|| //输入地址比起始地址还小的,
|
||
(ecbm_modbus_rtu_address)>=(ECBM_MODBUS_RTU_REG_BUF_SIZE+ECBM_MODBUS_RTU_REG_START_ADDR)//输入的地址+输入的数量超过本机定义的数量。
|
||
){
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x86);
|
||
ecbm_modbus_rtu_crc16(0x04);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x86); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
#else
|
||
if(0){
|
||
#endif
|
||
}else{
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
ecbm_modbus_cmd_write_reg(ecbm_modbus_rtu_address-ECBM_MODBUS_RTU_REG_START_ADDR,ecbm_modbus_rtu_data_count);//把数据写入寄存器。
|
||
#else
|
||
ecbm_modbus_cmd_write_reg(ecbm_modbus_rtu_address,ecbm_modbus_rtu_data_count);//把数据写入寄存器。
|
||
#endif
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x06);
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_address>>8));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_data_count>>8));
|
||
ecbm_modbus_rtu_crc16((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x06); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address>>8));//发送地址。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count>>8));//发送个数。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
// }else{
|
||
// ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
// if(ecbm_modbus_rtu_broadcast_en){
|
||
// ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
// ecbm_modbus_rtu_crc16(0x86);
|
||
// ecbm_modbus_rtu_crc16(0x02);
|
||
// ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
// ecbm_modbus_rtu_set_data(0x86); //发送0x80+功能码回复。
|
||
// ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
// }
|
||
// }
|
||
// }else{ //如果不合法。
|
||
// ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
// if(ecbm_modbus_rtu_broadcast_en){
|
||
// ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
// ecbm_modbus_rtu_crc16(0x86);
|
||
// ecbm_modbus_rtu_crc16(0x03);
|
||
// ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
// ecbm_modbus_rtu_set_data(0x86); //发送0x80+功能码回复。
|
||
// ecbm_modbus_rtu_set_data(0x03); //异常码03。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
// ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
// }
|
||
// }
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
16号功能码处理函数。
|
||
-------------------------------------------------------*/
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
void ecbm_modbus_rtu_cmd_0x10(void){
|
||
emu8 i;
|
||
ecbm_modbus_rtu_crc=0xffff;
|
||
if((ecbm_modbus_rtu_data_count>=0x0001)&&(ecbm_modbus_rtu_data_count<=0x007B)){ //输入的数据个数得符合要求。
|
||
if(((emu32)ecbm_modbus_rtu_address+(emu32)ecbm_modbus_rtu_data_count)<65536UL){ //地址不能超过65536。
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
if( //遇到以下问题,说明写入肯定会失败。
|
||
(ecbm_modbus_rtu_address<ECBM_MODBUS_RTU_REG_START_ADDR)|| //输入地址比起始地址还小的,
|
||
(ecbm_modbus_rtu_address+ecbm_modbus_rtu_data_count)>(ECBM_MODBUS_RTU_REG_BUF_SIZE+ECBM_MODBUS_RTU_REG_START_ADDR)//输入的地址+输入的数量超过本机定义的数量。
|
||
){
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_fun_err_num=0x04; //记录异常码04。
|
||
ecbm_modbus_rtu_crc16 (ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16 (0x90);
|
||
ecbm_modbus_rtu_crc16 (0x04);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x90); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x04); //异常码04。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
#else
|
||
if(0){
|
||
#endif
|
||
}else{//12511
|
||
#if ECBM_MODBUS_RTU_REG_BUF_EN
|
||
ecbm_modbus_rtu_address-=ECBM_MODBUS_RTU_REG_START_ADDR;
|
||
#endif
|
||
for(i=0;i<ecbm_modbus_rtu_cmd_count;i++){
|
||
ecbm_modbus_cmd_write_reg(ecbm_modbus_rtu_address+i,ecbm_modbus_rtu_cmd_buf[i]); //把数据写入寄存器。
|
||
}
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16 (ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16 (0x10);
|
||
ecbm_modbus_rtu_crc16 ((emu8)(ecbm_modbus_rtu_address>>8));
|
||
ecbm_modbus_rtu_crc16 ((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_crc16 ((emu8)(ecbm_modbus_rtu_data_count>>8));
|
||
ecbm_modbus_rtu_crc16 ((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x10); //发送功能码回复。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address>>8));//发送地址。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_address));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count>>8));//发送个数。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_data_count));
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{
|
||
ecbm_modbus_rtu_fun_err_num=0x02; //记录异常码02。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16 (ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16 (0x90);
|
||
ecbm_modbus_rtu_crc16 (0x02);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x90); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x02); //异常码02。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}else{ //如果不合法。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //记录异常码03。
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x90);
|
||
ecbm_modbus_rtu_crc16(0x03);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x90); //发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(0x03); //异常码03。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc));//发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
/*-------------------------------------------------------
|
||
modbus接收处理函数。
|
||
22-07-09:串口收到数据后回调用这里
|
||
-------------------------------------------------------*/
|
||
void ecbm_modbus_rtu_receive(void){
|
||
emu8 dat;//11162
|
||
ecbm_modbus_rtu_timeout=1;
|
||
dat=ecbm_modbus_rtu_get_data();//220709:从串口BUFF寄存器中取数据
|
||
switch(ecbm_modbus_rtu_status){
|
||
case ECBM_MODBUS_RTU_READY:{ //就绪,等待接收数据。
|
||
if((dat==ecbm_modbus_rtu_id)||(dat==0)||(dat==0xff)){ //如果收到的ID和本机的匹配。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_FUN_NUM;//切换到功能码识别
|
||
if((dat==0)||(dat==0xff)){
|
||
ecbm_modbus_rtu_broadcast_en=0;//写入通信模式,为了简化代码,采用直接赋值。
|
||
}else{
|
||
ecbm_modbus_rtu_broadcast_en=1;
|
||
}
|
||
ecbm_modbus_rtu_fun_code=0; //清零功能码缓存。
|
||
ecbm_modbus_rtu_fun_err_num=0; //清零异常码缓存。
|
||
ecbm_modbus_rtu_uart_crc=0xffff;//重置CRC初值。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc;
|
||
ecbm_modbus_rtu_crc16(dat); //计算CRC。
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}else{ //如果ID不匹配,进入相应的错误界面。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_ID_ERR;
|
||
}
|
||
}break;
|
||
case ECBM_MODBUS_RTU_FUN_NUM:{ //正在接收功能码。
|
||
if(dat>127){ //判断功能码是否合法,
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_FUN_NUM_ERR; //不合法就跳到功能码错误。
|
||
ecbm_modbus_rtu_fun_err_num=0x01; //异常码01。
|
||
}else{ //如果合法,
|
||
ecbm_modbus_rtu_fun_code=ecbm_modbus_rtu_check_fun_num(dat);//判断是不是本机支持的功能码。
|
||
if(ecbm_modbus_rtu_fun_code>127){
|
||
ecbm_modbus_rtu_fun_code&=~0x80;
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_FUN_NUM_VOID; //不存在的功能码就跳到功能码空。
|
||
ecbm_modbus_rtu_fun_err_num=0x01; //异常码01。
|
||
}else{
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_ADDRH; //如果是存在的功能码,就考虑开始接收数据了。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc;
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}
|
||
}
|
||
}break;
|
||
case ECBM_MODBUS_RTU_ADDRH:{ //接收地址的高8位。
|
||
ecbm_modbus_rtu_address=(emu16)dat<<8; //组装地址。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_ADDRL; //到下一步。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_ADDRL:{ //接收地址的低8位。
|
||
ecbm_modbus_rtu_address+=(emu16)dat; //组装地址。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DATA_COUNTH;//到下一步。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_DATA_COUNTH:{ //接收数据/个数的高8位。
|
||
ecbm_modbus_rtu_data_count=(emu16)dat<<8; //组装数据/个数。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DATA_COUNTL;//到下一步。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_DATA_COUNTL:{ //接收数据/个数的低8位。
|
||
ecbm_modbus_rtu_data_count+=(emu16)dat; //组装数据/个数。
|
||
if(ecbm_modbus_rtu_fun_code==0x10){
|
||
ecbm_modbus_rtu_cmd_count=0;
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_BYTE_COUNT;//到字节读取。
|
||
}else{
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_CRCL;//到CRC。
|
||
}
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_CRCL:{ //接收CRC的低8位。
|
||
ecbm_modbus_rtu_crc_buf=(emu16)dat; //组合CRC。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_CRCH; //到下一步。
|
||
}break;
|
||
case ECBM_MODBUS_RTU_CRCH:{ //接收CRC的高8位。
|
||
ecbm_modbus_rtu_crc_buf+=(emu16)dat<<8; //组合CRC。
|
||
if(ecbm_modbus_rtu_crc_buf==ecbm_modbus_rtu_uart_crc){//判断接收的CRC和计算的CRC是否相等。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DO; //相等的话就到执行步骤。
|
||
}else{ //否则,
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_CRC_ERR;//就跳到CRC错误界面。
|
||
}
|
||
}break;
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
case ECBM_MODBUS_RTU_BYTE_COUNT:{ //接收数据字节数。
|
||
ecbm_modbus_rtu_cmd_count=dat;
|
||
if((ecbm_modbus_rtu_cmd_count==0)||(ecbm_modbus_rtu_cmd_count!=(emu8)(ecbm_modbus_rtu_data_count*2))){//如果数量不合。
|
||
ecbm_modbus_rtu_fun_err_num=0x03; //字节数对不上,异常码03。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_BYTE_ERR;//调到对应的处理界面。
|
||
}else{
|
||
ecbm_modbus_rtu_cmd_count=0; //复用该变量。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DATAH;//调到对应的处理界面。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}
|
||
}break;
|
||
case ECBM_MODBUS_RTU_DATAH:{
|
||
ecbm_modbus_rtu_cmd_buf[ecbm_modbus_rtu_cmd_count]=((emu16)dat)<<8;
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DATAL; //到低8位。
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_DATAL:{
|
||
ecbm_modbus_rtu_cmd_buf[ecbm_modbus_rtu_cmd_count]+=((emu16)dat);
|
||
ecbm_modbus_rtu_cmd_count++;
|
||
if(ecbm_modbus_rtu_cmd_count==(emu8)ecbm_modbus_rtu_data_count){
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_CRCL;//到CRC。
|
||
}else{
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_DATAH;//到下一个数据的高8位。
|
||
}
|
||
ecbm_modbus_rtu_crc=ecbm_modbus_rtu_uart_crc; //计算CRC。
|
||
ecbm_modbus_rtu_crc16(dat);
|
||
ecbm_modbus_rtu_uart_crc=ecbm_modbus_rtu_crc;
|
||
}break;
|
||
#endif
|
||
}
|
||
}
|
||
/*-------------------------------------------------------
|
||
modbus主循环处理函数。
|
||
-------------------------------------------------------*/
|
||
void ecbm_modbus_rtu_run(void){
|
||
switch(ecbm_modbus_rtu_status){
|
||
case ECBM_MODBUS_RTU_FUN_NUM_VOID:// debug("不支持该功能码\r\n");
|
||
case ECBM_MODBUS_RTU_FUN_NUM_ERR:{// debug("功能码错误\r\n");
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc=0xFFFF;
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x80+ecbm_modbus_rtu_fun_code);
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_fun_err_num);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x80+ecbm_modbus_rtu_fun_code);//发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_fun_err_num); //异常码。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_WAIT;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_ID_ERR:{//ID错误。
|
||
//这里可以做些处理,但默认留空。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_WAIT;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_CRC_ERR:{//CRC错误。
|
||
//这里可以做些处理,比如发送个重发信号,但默认留空。
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_WAIT;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_DO:{//动作执行。
|
||
#if ECBM_MODBUS_RTU_CMD_ALL_EN
|
||
#if ECBM_MODBUS_IO_EN
|
||
ecbm_modbus_rtu_set_io(ECBM_MODBUS_WRITE);//220709:控制使能脚写
|
||
#endif
|
||
switch(ecbm_modbus_rtu_fun_code){//根据功能码来选择对应的动作。
|
||
#if ECBM_MODBUS_RTU_CMD01_EN
|
||
case 0x01:ecbm_modbus_rtu_cmd_0x01();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD02_EN
|
||
case 0x02:ecbm_modbus_rtu_cmd_0x02();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD03_EN
|
||
case 0x03:ecbm_modbus_rtu_cmd_0x03();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD04_EN
|
||
case 0x04:ecbm_modbus_rtu_cmd_0x04();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD05_EN
|
||
case 0x05:ecbm_modbus_rtu_cmd_0x05();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD06_EN
|
||
case 0x06:ecbm_modbus_rtu_cmd_0x06();break;
|
||
#endif
|
||
#if ECBM_MODBUS_RTU_CMD10_EN
|
||
case 0x10:ecbm_modbus_rtu_cmd_0x10();break;
|
||
#endif
|
||
}
|
||
#endif
|
||
#if ECBM_MODBUS_IO_EN
|
||
ecbm_modbus_rtu_set_io(ECBM_MODBUS_READ);//220709:控制使能脚
|
||
#endif
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_READY;
|
||
}break;
|
||
case ECBM_MODBUS_RTU_BYTE_ERR:{
|
||
if(ecbm_modbus_rtu_broadcast_en){
|
||
ecbm_modbus_rtu_crc=0xFFFF;
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_id); //计算CRC,下同。
|
||
ecbm_modbus_rtu_crc16(0x80+ecbm_modbus_rtu_fun_code);
|
||
ecbm_modbus_rtu_crc16(ecbm_modbus_rtu_fun_err_num);
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_id); //发送地址。
|
||
ecbm_modbus_rtu_set_data(0x80+ecbm_modbus_rtu_fun_code);//发送0x80+功能码回复。
|
||
ecbm_modbus_rtu_set_data(ecbm_modbus_rtu_fun_err_num); //异常码。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc)); //发送CRC。
|
||
ecbm_modbus_rtu_set_data((emu8)(ecbm_modbus_rtu_crc>>8));
|
||
}
|
||
ecbm_modbus_rtu_status=ECBM_MODBUS_RTU_WAIT;
|
||
}break;
|
||
}
|
||
}
|