g0b1vetx-board/middleware/Freemodbus/modbus/modbus.c
2023-04-29 09:09:12 +08:00

895 lines
50 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
}