RXD
#include "ModBus.h"
/******************************************************************/
StrRxd xdata sys_rxd; //定义接收处理结构体
/******************************************************************/
/*******公有函数***************************************************/
void init_proc_rxd(void); //初始化串口通信变量
void process_rxd(void); //通信处理函数
void init_serial(void); //初始化串口
/*******私有函数***************************************************/
uint8 read_sys_rxd(void); //读接收缓冲区
uint8 data_check(void); //校验和检验
uint8 lenghchk(void); //数据长度检验
void data_change(void); //数据ASCII转换成HEX
/******************************************************************/
void init_proc_rxd(void)//初始化串口通信变量
{
uint8 idata i;
for( i = 0;i < POOLLEN;i++ )
{
//读
sys_rxd.pool[i] = 0;//接收数据缓冲区
sys_rxd.rec_buf[i] = 0;//去除包头包尾后的数据保留区,这里只保留一帧有效数据
//写
sys_txd.pool[i] = 0;//发送数据ASCII缓冲区
sys_txd.combuf[i] = 0;//发送数据HEX缓冲区
}
for( i = 0;i < 16;i++ )
{
sys_rxd.add_buf[i] = 0;//用于存放接收缓冲的地址,可以存放16个帧地址,奇数位是首地址,偶数位是尾地址
}
sys_rxd.front = 0;
sys_rxd.rear = 0;
sys_rxd.frm_num = 0;//缓冲区中的帧数量
sys_rxd.rd_byte = 0;//暂存读数据
sys_rxd.start_0x7e = 0;
sys_rxd.end_0x0d = 0;
sys_txd.txd_len = 0;//发送数据长度
}
/*****************************************************************/
uint8 read_sys_rxd(void)//读接收缓冲区
{
if( sys_rxd.rear == sys_rxd.front )
{
return WRONG;
}
else
{
sys_rxd.rd_byte = sys_rxd.pool[sys_rxd.front];
sys_rxd.front = (sys_rxd.front+1) % POOLLEN;
return RIGHT;
}
}
/*****************************************************************/
uint8 data_check(void)//校验和检验
{
uint8 add_len,temp;
uint8 i,j,k,fram_temp;
uint16 chk_sum,chk_sum_temp;
fram_temp = sys_rxd.frm_num;//如何防止在处理数据的同时新的中断使该值变化
add_len = 0;
if( fram_temp )//接收的一帧完整数据
{
fram_temp -= 1;
j = sys_rxd.add_buf[fram_temp * 2];
k = sys_rxd.add_buf[fram_temp * 2 + 1];
if(k > j)
{
add_len = k-j;
}
else
{
add_len = (POOLLEN - j ) + k;//地址确认
}
sys_rxd.front = j;
chk_sum = 0;
for( i = 0;i < add_len - 4;i++ ) //4 byte is check sum
{
read_sys_rxd(); //the poionter is add1
if( sys_rxd.rd_byte == FRAME_START )
{
sys_rxd.rd_byte = 0;
}
chk_sum += sys_rxd.rd_byte;
}
chk_sum = (~chk_sum) + 1;
chk_sum_temp = 0;
for(i=0;i<4;i++)
{
read_sys_rxd();
temp = sys_rxd.rd_byte;//rd_byte 暂存读数据
if(temp > 0x40)
{
temp -= 0x37; // get the hex valume
}
else
{
temp -= 0x30;
}
chk_sum_temp += temp;
if( i < 3 )
{
chk_sum_temp = chk_sum_temp << 4;
}
}
if( chk_sum_temp == chk_sum )
{
return RIGHT;
}
else
{
return WRONG;
}
}
else
{
return WRONG;
}
}
/*****************************************************************/
uint8 lenghchk(void) //数据长度检验
{
uint8 link_sum,link_sum_temp;
uint8 add_len;
uint8 j,k,fram_temp;
if( sys_rxd.rec_buf[4] != lchksum(sys_rxd.rec_buf[5]) )
{
return WRONG;
}
fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
if ( fram_temp == 0 )
{
return WRONG;
}
fram_temp--;
j = sys_rxd.add_buf[fram_temp*2];
k = sys_rxd.add_buf[fram_temp*2+1];
if(k>j)
{
add_len = k-j;
}
else
{
add_len = ( POOLLEN - j ) + k;
}
link_sum_temp = (add_len - 17);
link_sum = sys_rxd.rec_buf[5];
if(link_sum != link_sum_temp)
{
return WRONG;
}
else
{
return RIGHT;
}
}
/*****************************************************************/
void data_change(void)//数据ASCII转换成HEX
{
uint8 add_len;
uint8 i,j,k,temp1,fram_temp;
uint8 temp;
fram_temp = sys_rxd.frm_num; //如何防止在处理数据的同时新的中断使该值变化
if ( fram_temp == 0 )
{
return;
}
fram_temp--;
j = sys_rxd.add_buf[fram_temp*2];
k = sys_rxd.add_buf[fram_temp*2+1];
if(k>j)
{
add_len = k-j;
}
else
{
add_len = ( POOLLEN - j ) + k;
}
add_len = add_len / 2 + 1; //cup down 2 byte chksum
sys_rxd.front = j;
for(i = 0;i < add_len;i++ )
{
read_sys_rxd(); //the poionter is add1
if (sys_rxd.rd_byte == 0x0d)
{
sys_rxd.rec_buf[i] = 0xaa;
sys_rxd.rec_buf[i+1]=0x55;
return;
}
if (sys_rxd.rd_byte == 0x7e)
{
read_sys_rxd();
}
temp = sys_rxd.rd_byte;
if(temp>0x40)
{
temp-=0x37;
}
else
{
temp -=0x30;
}
temp = temp<<4;//高4位
read_sys_rxd();//the poionter is add1
temp1 = sys_rxd.rd_byte;
if(temp1>0x40)
{
temp1-=0x37;
}
else
{
temp1-=0x30;
}
sys_rxd.rec_buf[i] = temp+temp1; // include ver/adr/cid1/cid2/length/info
}
}
/*****************************************************************/
void process_rxd(void) //接收缓冲区中的数据 入处理缓冲区
{
while(sys_rxd.frm_num)
{
if(data_check() == WRONG)
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x02); //校验和错误
return;
}
data_change();
if( (sys_rxd.rec_buf[1] == ADDR ) ) //地址正确
{
if( lenghchk() ==WRONG ) //长度校验
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x03); //长度校验错误
return;
}
if(sys_rxd.rec_buf[0] != VER)
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num --;
txd_uni(0x01); //版本错
return;
}
if( (sys_rxd.rec_buf[2] != M_CID)) //设备ID错
{
sys_rxd.add_buf[sys_rxd.frm_num*2] = 0;
sys_rxd.add_buf[sys_rxd.frm_num*2+1] =0;
sys_rxd.frm_num--;
txd_uni(0xe1); //设备ID错
return;
}
switch(sys_rxd.rec_buf[3])
{
case 0x44:
txd_sta();
break;
case 0x4f:
txd_uni(0x4f); //发送通讯协议版本号
break;
case 0x50:
txd_uni(0x50); //发送设备地址
break;
case 0x51:
txd_man(); //发送设备厂家信息
break;
case 0x60:
txd_uni(0x60); //系统初始化
break;
default:
txd_uni(0x04); //无效命令
break;
}
}
sys_rxd.frm_num--;
}
}
/*****************************************************************/
void init_serial(void)//初始化串口
{
//串行口波特率等设置
TMOD=0x21; // T1 mode 2 T0,mode 1 //GATE C/T M1 M0 GATE C/T M1 M0
TL1=0xfa; // 0xfa=4800 bps 0xfd=9600 bps 0xe8 = 1200 0xf4 = 2400
TH1=0xfa;
TH0=-(10000/256);
TL0=-(10000%256);
PCON=0; //波特率不变等设置
SCON=0x50; //串口1方式1,允许接收
IT0=1; //外部中断0下降沿有效
IT1=1; //外部中断1下降沿有效
TR0=1; //启动定时器0
TR1=1; //启动定时器1
ET0=1; //开放定时器0中断
ES=1; //串行中断
EX0=0; //外部中断0
EX1=1; //外部中断1
EA=1; //开总中断
// RS485EN = 0;
}
/*****************************************************************/
void serial_uart(void) interrupt 4
{
uchar idata temp;
uchar idata num;
if(RI)
{
RI = 0;
temp = SBUF;
if( sys_rxd.start_0x7e && (temp != FRAME_END) )
{
sys_rxd.pool[sys_rxd.rear] = temp;
sys_rxd.rear = (sys_rxd.rear + 1) % POOLLEN;
return;
}
else
{
if( (temp ^ FRAME_START)==0 ) //如果接收到包起始位
{
if( (sys_rxd.start_0x7e) && (sys_rxd.end_0x0d) )
{
sys_rxd.rear = sys_rxd.add_buf[num];
}
else
{ //第一次接收到起始位
sys_rxd.start_0x7e = 1;
sys_rxd.end_0x0d = 1;
num = sys_rxd.frm_num * 2; //新的一帧的起始地址下标
sys_rxd.add_buf[num] = sys_rxd.rear; //起始地址保存
}
sys_rxd.pool[sys_rxd.rear] = temp;
sys_rxd.rear=(sys_rxd.rear+1) % POOLLEN;
return;
}
else
{
if( sys_rxd.start_0x7e && ( temp == FRAME_END ) )
{
sys_rxd.end_0x0d = 0;
sys_rxd.start_0x7e = 0;
sys_rxd.pool[sys_rxd.rear] = temp;
sys_rxd.rear = (sys_rxd.rear+1) % POOLLEN;
num = sys_rxd.frm_num*2+1;//结束地址位
if(sys_rxd.rear==0) //对于POOLLEN不是255的时候,如果直接-1做尾地址。肯定造成尾地址错误。因为 0-1=255
{
sys_rxd.add_buf[num] = POOLLEN - 1;//在写进后的地址已加上1
}
else
{
sys_rxd.add_buf[num] = sys_rxd.rear-1;//在写进后的地址已加上1
}
sys_rxd.frm_num++;//增加一帧//成功才加一位
sys_rxd.frm_num = sys_rxd.frm_num % 16;
return;
}
}
}
}
}
This is an embedded C code example for handling Modbus communication, which includes functions such as serial communication, data verification, data length checking, and data conversion. Here is a brief explanation of this code: The
StrRxdStructures are used to store variables and data related to receiving and processing.init_proc_rxdThe function is used to initialize serial communication variables. It cleared some buffer and flag variables in preparation for receiving data.read_sys_rxdfunction is used to read one byte of data from the receive buffer and store it insys_rxd.rd_byte. Thedata_checkfunction is used for checksum verification. It calculates the checksum of the received data and compares it with the checksum field of the received data to ensure data integrity. Thelenghchkfunction is used for data length verification. It compares the received data length field with the actual data length to ensure that the data length is correct. Thedata_changefunction is used to convert ASCII format data to HEX format data for further processing. Theprocess_rxdfunction is used to process the received data. It checks the version, address, and command of data according to protocol specifications, and then performs corresponding operations. Theinit_serialfunction is used to initialize serial communication. It is configured with parameters such as baud rate and timer for the serial port. Theserial_uartfunction is a serial port receive interrupt service program. It triggers when data is received through the serial port, stores the data in the receive buffer, and triggers the corresponding processing function. This code implements a simple Modbus communication protocol parser for receiving and processing Modbus RTU frames. Please note that the code in this example is written for specific hardware and communication requirements, so it needs to be appropriately modified according to your hardware and application requirements. In addition, it also includes some interrupt handling, such as serial port receive interrupts and timer interrupts, to support asynchronous communication. This code example is a starting point that you can extend and optimize as needed.
This code implements a simple Modbus communication protocol parser for receiving and processing Modbus RTU frames. Please note that the code in this example is written for specific hardware and communication requirements, so it needs to be appropriately modified according to your hardware and application requirements. In addition, it also includes some interrupt handling, such as serial port receive interrupts and timer interrupts, to support asynchronous communication. This code example is a starting point that you can extend and optimize as needed.
TXD
#include "ModBus.h"
//--------公有函数和变量-------
StrTxd xdata sys_txd;
/****************************************/
uint8 lchksum(uint8 data_len); //求LENTH_SUM函数
void txd_sta(void); //发送系统告警信息
void txd_man(void); //发送厂家信息
void txd_uni(uint8 cid2); //发送系统通信信息
/******************************************/
void package(void); //数据打包成ASCII码
void chksum (void); //求校验和
void com(void); //公共的发送函数
/******************************************/
uint8 lchksum(uint8 data_len)//求LENTH_SUM函数
{
uint8 sum,temp1;
sum = 0;
if (data_len)
{
sum = data_len & 0x0f;
temp1 = (data_len & 0xf0)>>4;
sum += temp1;
sum = sum %16;
sum = (~sum)+1;
sum = sum <<4;
}
return sum;
}
/******************************************/
void package(void)//数据打包成ASCII码
{
uint8 i;
uint8 temp1,temp2;
sys_txd.pool[0] = FRAME_START;
for(i = 1;i < POOLLEN; i++)
{
if( (sys_txd.combuf[i] == 0xaa ) && (sys_txd.combuf[i+1] == 0x55 ) ) //结束标志
{
sys_txd.pool[i*2-1] = FRAME_END;
break;
}
else
{
temp1 = sys_txd.combuf[i];
temp2 = temp1 & 0x0f;
temp1 = temp1 & 0xf0;
temp1 = temp1>>4;
sys_txd.pool[i*2-1] = (temp1>0x09)?(temp1+0x37):(temp1+0x30);
sys_txd.pool[i*2] = (temp2>0x09)?(temp2+0x37):(temp2+0x30);
}
}
}
/******************************************/
void chksum (void)//求校验和
{
uint8 i;
uint8 sumh,suml,temp;
uint16 sum = 0;
for(i = 1;i < POOLLEN;i++ )
{
if( sys_txd.pool[i] == FRAME_END )
{
temp = i;
break;
}
else
{
sum += sys_txd.pool[i]; //溢出部分不用考虑
}
}
sum = (~sum) + 1;//取反+1
sumh = (uint8)(sum/256);//高8位
suml = (uint8)sum;
i = temp;
temp = (sumh&0xf0)>>4;
temp = (temp>0x09)?(temp+0x37):(temp+0x30);
sys_txd.pool[i] = temp;
temp = (sumh & 0x0f);
temp = (temp>0x09)?(temp+0x37):(temp+0x30);
sys_txd.pool[i+1] = temp;
temp = (suml&0xf0)>>4;
temp = (temp>0x09)?(temp+0x37):(temp+0x30);
sys_txd.pool[i+2] = temp;
temp = (suml&0x0f);
temp = (temp>0x09)?(temp+0x37):(temp+0x30);
sys_txd.pool[i+3] = temp;
sys_txd.pool[i+4] = FRAME_END;
sys_txd.txd_len = i+4;
return;
}
/******************************************/
void com(void)//公共的发送函数
{
uint8 i;
uint8 j;
EA = 0;
// RS485EN = 1; //使用485通信的时候使用
for( i = 0;i <= sys_txd.txd_len;i++ )
{
SBUF = sys_txd.pool[i];
while(TI==0);
TI = 0;
if( sys_txd.pool[i] == FRAME_END )
{
for( j=0;j <= sys_txd.txd_len;j++ )
{
sys_txd.pool[i] = 0; //对已经发送的数据清0
}
}
}
// RS485EN = 0;
// RI = 0; //注意,如果485的接收使能一直有效,必须要这一行解决
EA = 1;
}
/******************************************/
void txd_sta(void)//发送系统告警信息
{
sys_txd.combuf[0] = FRAME_START; //起始标志
sys_txd.combuf[1] = VER; //版本号
sys_txd.combuf[2] = ADDR; //地址,主机
sys_txd.combuf[3] = M_CID; //设备ID
//------以上是包头---------
sys_txd.combuf[4] = 0x44; //Cid2=0x44,表示发送所有的告警状态
//------length---------
sys_txd.combuf[5] = lchksum(20); //length checksum//////////////////////
sys_txd.combuf[6] = 20; //length id
/********************************************/
sys_txd.combuf[7] = 20; //这里放告警信息
sys_txd.combuf[8] = 20; //
sys_txd.combuf[9] = 20; //
sys_txd.combuf[10] = 20; //
/********************************************/
sys_txd.combuf[11] = 0xaa; //end ;
sys_txd.combuf[12] = 0x55; //数据打包成ASCII码
package(); //////////////////////////////
chksum(); //除起始和校验和以及结束之外的ASCII码求校验和
com();
}
/******************************************************/
void txd_man(void)//发送厂家信息
{
//-----------------------------------------------------------------
sys_txd.combuf[0] = FRAME_START; //起始标志
sys_txd.combuf[1] = VER; //版本号
sys_txd.combuf[2] = ADDR; //地址,主机
sys_txd.combuf[3] = M_CID; //设备ID
//----------以上是包头
//-----------------------------------------------------------------
sys_txd.combuf[4] =0x51;
sys_txd.combuf[5] =lchksum(0x40);
sys_txd.combuf[6] =0x40;
sys_txd.combuf[7] = 'L'; //L
sys_txd.combuf[8] = 'I'; //I
sys_txd.combuf[9] = 'N'; //N
sys_txd.combuf[10] = 'E'; //E
sys_txd.combuf[11] = 0;
sys_txd.combuf[12] = 0x00;
sys_txd.combuf[13] = 0x00;
sys_txd.combuf[14] = 0x00;
sys_txd.combuf[15] = 0x00;
sys_txd.combuf[16] = 0x00;
sys_txd.combuf[17] = 0x01; //1 版本
sys_txd.combuf[18] = 0x00; //0
sys_txd.combuf[19] = 0x41; //A 厂家
sys_txd.combuf[20] = 0x41; //A
sys_txd.combuf[21] = 0x41; //A
sys_txd.combuf[22] = 0x41; //A
sys_txd.combuf[23] = 0x41; //A
sys_txd.combuf[24] = 0x41; //A
sys_txd.combuf[25] = 0x41; //A
sys_txd.combuf[26] = 0x41; //A
sys_txd.combuf[27] = 0x41; //A
sys_txd.combuf[28] = 0x41; //A
sys_txd.combuf[29] = 0x00;
sys_txd.combuf[30] = 0x00;
sys_txd.combuf[31] = 0x00;
sys_txd.combuf[32] = 0x00;
sys_txd.combuf[33] = 0x00;
sys_txd.combuf[34] = 0x00;
sys_txd.combuf[35] = 0x00;
sys_txd.combuf[36] = 0x00;
sys_txd.combuf[37] = 0x00;
sys_txd.combuf[38] = 0x00;
sys_txd.combuf[39] = 0xaa;
sys_txd.combuf[40] = 0x55;
package(); //数据打包成ASCII码
chksum(); //除起始和校验和以及结束之外的ASCII码求校验和
com();
}
/******************************************/
void txd_uni(uint8 cid2)//发送系统通信信息
{
//-----------------------------------------------------------------
sys_txd.combuf[0] = FRAME_START; //起始标志
sys_txd.combuf[1] = VER; //版本号
sys_txd.combuf[2] = ADDR; //地址,主机
sys_txd.combuf[3] = M_CID; //设备ID
//----------以上是包头
//-----------------------------------------------------------------
sys_txd.combuf[4] = cid2;
sys_txd.combuf[5] = lchksum(0x00); //length checksum 0x00
sys_txd.combuf[6] = 0x00; //length id 00
sys_txd.combuf[7] = 0xaa; //length id=00,所以,没有info
sys_txd.combuf[8] = 0x55;
package(); //数据打包成ASCII码
chksum(); //除起始和校验和以及结束之外的ASCII码求校验和
com();
}
/******************************************/
This code is used to handle the functions related to data packaging and transmission in Modbus communication. The following is a brief description of each function:
lchksumThe function is used to calculate the length checksum (length checksum) to ensure that the data length field is correct. It takes a parameterdata_len, calculates and returns a length checksum. Thepackagefunction is used to package data into ASCII code format. It converts HEX format data into ASCII code and inserts appropriate separators between each HEX byte. The final data is stored insys_txd.combuf. Thechksumfunction is used to calculate the checksum. It calculates the checksum of all data except for the start flag, checksum field, and end flag, and adds it to the data. ThecomThe function is used to send data. It sends data out through the serial port and clears the already sent data for the next use.txd_staThe function is used to send system alarm information. It sets a specific commandcid2(0x44) , Indicates sending alarm information. Then, it sets the data length, alarm information and other related fields, and finally callspackage,chksumAndcomFunction sends data.txd_manThe function is used to send manufacturer information. It sets a specific commandcid2(0x51) , Indicates sending manufacturer information. Then, it sets the data length, manufacturer information and other related fields, and finally calls thepackage,chksumAndcomFunction sends data.txd_uniThe function is used to send system communication information. It accepts a parametercid2, represents a communication command. Depending on thecid2It sets corresponding commands and sends corresponding data.
These functions together construct the data transmission process for sending different types of Modbus frames. Please note that the code in this example is written for a specific application, so it needs to be modified appropriately according to your requirements. In addition, the code example also includes some serial communication and data conversion functions to support Modbus communication.
ModBusStr
#ifndef MODBUSSTR_H
#define MODBUSSTR_H
//==============================================
#define uchar unsigned char
#define uint unsigned int
#define uint8 unsigned char
#define uint16 unsigned int
//接收缓冲区结构变量
typedef struct str_rxd_pool
{
uint8 pool[255]; //接收数据缓冲区
uint8 front; //头指针
uint8 rear; //尾指针
uint8 rd_byte; //暂存读数据
uint8 frm_num; //缓冲区中的帧数量
uint8 add_buf[16]; //用于存放接收缓冲的地址,可以存放16个帧地址,奇数位是首地址,偶数位是尾地址
uint8 rec_buf[255]; //去除包头包尾后的数据保留区,这里只保留一帧有效数据
uint8 start_0x7e; //接收到帧头标志
uint8 end_0x0d; //接收到帧尾标志
}StrRxd;
//===============================================
//发送缓冲区结构变量
typedef struct str_txd_pool
{
uint8 pool[255]; //发送数据ASCII缓冲区
uint8 combuf[255]; //发送数据HEX缓冲区
uint8 txd_len; //发送数据长度
}StrTxd;
#endifThis is a C language header file (MODBUSSTR.H) that defines data structures and related type aliases for Modbus communication. The following is the main content defined in this header file:
- Header file protection macro definition
#ifndef MODBUSSTR_HAnd#define MODBUSSTR_HTo ensure that the file is only included once. - Some definitions of type aliases, including
uchar,uint,uint8Anduint16Representing unsigned characters, unsigned integers, and unsigned integers of different widths. StrRxdStructure definition, used to receive the relevant data structures of the buffer. This structure includes the following members:
pool[255]: a buffer used to store received data, with a maximum length of 255 bytes.front: Head pointer, pointing to the beginning of the buffer.rear: Tail pointer, pointing to the end of the buffer.rd_byte: Used for temporarily storing read data.frm_num: The number of frames in the buffer.add_buf[16]: Used to store the address of the receive buffer, which can hold 16 frame addresses, with odd bits being the first address and even bits being the last address.rec_buf[255]: Used to store data after removing packet headers and tails, retaining only one frame of valid data.start_0x7e: Used to indicate whether the frame header flag has been received.end_0x0d: Used to indicate whether the frame tail flag has been received.
StrTxdStructure definition, used to send data structures related to the buffer. This structure includes the following members:
pool[255]: a buffer in ASCII format used to store sent data, with a maximum length of 255 bytes.combuf[255]: A HEX format buffer used to store sent data, with a maximum length of 255 bytes.txd_len: The length of the transmitted data. This header file defines the data structures used for Modbus communication and can be included in applications to access these data structures and type aliases. This helps to better organize and manage data in Modbus communication. This code is a header file containing some macro definitions, data structures, and other related header files, as well as defining some global variables and function prototypes.
This header file defines the data structures used for Modbus communication and can be included in applications to access these data structures and type aliases. This helps to better organize and manage data in Modbus communication.
ModBus
#include "reg51.h"
#include "ModBusStr.h"
#define uchar unsigned char
#define uint unsigned int
#define uint8 unsigned char
#define uint16 unsigned int
#define OK 1
#define ERROR 0
#define RIGHT 1
#define WRONG 0
#define POOLLEN 255 //缓冲区大小
#define INIT_COMMAND 0x20
#define START_COMMAND 0x21
#define END_COMMAND 0x22
#define ALARM_COMMAND 0x23
#define FRAME_START 0x7e //帧开始标志
#define FRAME_END 0x0d //帧结束标志
#define VER 0x10
#define ADDR 0x01
#define M_CID 0x25 //设备识别码,0x25代表直流电源柜
extern StrRxd xdata sys_rxd;
extern StrTxd xdata sys_txd;
extern void init_proc_rxd(void);
extern void process_rxd(void);
extern void init_serial(void);
extern uint8 lchksum(uint8 data_len);
extern void txd_sta(void);
extern void txd_man(void);
extern void txd_uni(uint8 cid2);
This code is a header file that contains some macro definitions and data structures"ModBusStr.h"And other related header files"reg51.h", as well as defining some global variables and function prototypes.
The following are some important elements in the code:
- The header file contains:
"reg51.h": This is a standard header file for 8051 series microcontrollers, providing register and macro definitions related to this series of chips."ModBusStr.h": This is a header file that you created yourself, containing data structures and type aliases related to Modbus communication.
- Macro Definition:
OKAndERROR: It defines two constants, 1 and 0, which are usually used to indicate the success or failure of function execution.RIGHTAndWRONG: Two constants are defined, typically used to represent the success and failure of certain conditions or operations.POOLLEN: The maximum length of the buffer is defined as 255.INIT_COMMAND,START_COMMAND,END_COMMANDAndALARM_COMMAND: Defined some command constants to represent different operations.FRAME_STARTAndFRAME_END: Defined the start and end flags for frames.VERAndADDR: Defined version number and address.M_CID: Defined the identification code of the device.
- External Global Variable Declaration:
StrRxd xdata sys_rxdAndStrTxd xdata sys_txd: Declares two external global variables,sys_rxdAndsys_txd, which are defined in other source files and used to store Modbus communication related data.
- External Function Prototype Declaration:
void init_proc_rxd(void),void process_rxd(void)Andvoid init_serial(void): These function prototype declarations are used for initializing receive processing, communication processing, and serial port initialization.uint8 lchksum(uint8 data_len),void txd_sta(void),void txd_man(void)andvoid txd_uni(uint8 cid2): These function prototypes are declared for calculating length checksum, sending system alarm information, sending manufacturer information, and sending system communication information.
This code organizes the data and functions related to Modbus communication, and provides these definitions and declarations to other source files for use through header files. The source file can contain this header file to access these definitions and declarations, thereby enabling Modbus communication functionality.
MainTest
#include "ModBus.h"
void main(void)
{
init_serial();//初始化串口
init_proc_rxd();//初始化串口通信变量
while(1)
{
process_rxd();//通信处理函数 接收缓冲区中的数据 入处理缓冲区
}
}
This is an example of the main program on an 8051 microcontroller, used to perform Modbus communication processing. In the main function, it operates according to the following steps:
- contains the
ModBus.hheader file, which should contain all necessary definitions, global variables, and function prototypes to support Modbus communication. - Call the
init_serial()function to initialize serial communication, which is an important step in setting up and preparing for communication with other devices. - Call the
init_proc_rxd()function to initialize serial communication variables. This step is usually taken to ensure that the communication variables are in the correct initial state. - enters an infinite loop (
while(1)) where the following operations are continuously performed:
- calls the
process_rxd()function, which is used for communication processing, receiving data from the buffer and processing it. Usually, this is a process of continuously monitoring and processing Modbus communication requests from other devices.
The entire program will run continuously, waiting for communication requests from other devices, and then perform the corresponding operations. This example is mainly used for initialization and processing of Modbus communication, and the actual communication logic and response will beprocess_rxd()function.

Leave a Reply