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); //dataASCII转换成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)//dataASCII转换成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)) //deviceID错
{
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); //deviceID错
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; //serial port1方式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;
}
}
}
}
}
这是一个用于処理Modbus通信的エンベデッド·インCCode Example,包含了シリアル通信、データチェック、データ長さ检验和データ変換等功能。以下是对这段代码的简要説明:
StrRxd構造体用于存储受信処理的相关变量和データ。init_proc_rxd函数用于初期化シリアル通信变量。它清零了一些バッファ和标志变量,以准备受信データ。read_sys_rxd函数用于从受信バッファ。中読み取り一バイト単位。的データ,并将其存储在sys_rxd.rd_byte中。data_check函数用于チェック和检验。它計算受信データ的チェック和并与受信データ的チェック字段进行比较,以确保データ完全性。lenghchk函数用于データ長さ检验。它比较受信到的データ長さ字段与实际データ長さ,以确保データ長さ正确。data_change函数用于将ASCII格式的データ変換为HEX格式的データ,以便进一步処理。process_rxd函数用于処理受信到的データ。它根据プロトコルの仕様チェックデータ的版本、アドレス和命令,然后执行相应的操作。init_serial函数用于初期化シリアル通信。它設定了シリアルポート的ボーレート、タイマータイマー。等参数。serial_uart函数是シリアルポート受信中断服务程序。它在シリアルポート接データの受信时触发,将データストア在受信バッファ。中,并触发相应的処理函数。
这段代码実装了一个简单的Modbus通信プロトコル解析器,用于受信和処理Modbus RTUフレーム。请注意,此サンプル中的代码是为特定硬件和通信要求编写的,因此需要根据あなたの硬件和应用程序要求进行适当的修改。此外,它还包含了一些中断処理,如シリアルポート受信中断和タイマータイマー。中断,以サポート异步通信。这个コード例是一个起点,您可以根据需要进行扩展和优化。
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; //address,マスター
sys_txd.combuf[3] = M_CID; //deviceID
//------以上是包头---------
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; //address,マスター
sys_txd.combuf[3] = M_CID; //deviceID
//----------以上是包头
//-----------------------------------------------------------------
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; //address,マスター
sys_txd.combuf[3] = M_CID; //deviceID
//----------以上是包头
//-----------------------------------------------------------------
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();
}
/******************************************/
这段代码是用于処理Modbus通信中的データパッキング和送信的相关函数。以下是对每个函数的简要説明:
lchksum函数用于計算長さチェック和(length checksum),以确保データ長さ字段正确。它接受一个参数data_len,計算并戻る長さチェック和。package函数用于将データパッキング成ASCIIコード形式。它将HEX格式的データ変換为ASCIIコード,并在每个HEXバイト之间插入合适的分隔符。最终的データストア在sys_txd.combuf中。chksum函数用于計算チェック和。它計算除了起始标志、チェック和字段和结束标志之外的すべてのデータ的チェック和,将其追加到データ中。com函数用于送信データ。它経由シリアルポート将データ送信出去,并クリア已送信的データ,以便下一次使用。txd_sta函数用于送信系统告警信息。它設定了一个特定的命令cid2(0x44),表示送信告警信息。然后,它設定データ長さ、告警信息和其他相关字段,最后调用package、chksum和com函数送信データ。txd_man函数用于送信厂家信息。它設定了一个特定的命令cid2(0x51),表示送信厂家信息。然后,它設定データ長さ、厂家信息和其他相关字段,最后调用package、chksum和com函数送信データ。txd_uni函数用于送信系统通信信息。它接受一个参数cid2,表示通信命令。根据不同的cid2,它設定了相应的命令并送信相应的データ。
这些函数一起构建了データ送信的流程,用于送信不同タイプ的Modbusフレーム。请注意,此サンプル中的代码是为特定应用程序编写的,因此需要根据あなたの要求进行适当的修改。此外,该コード例还包括一些シリアル通信和データ変換的功能,以サポートModbusCommunication。
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;
#endif
这是一个C语言头文件(MODBUSSTR.H),定义了用于Modbus通信的データ構造和相关タイプ别名。以下是这个头文件中定义的主要内容:
- 头文件保护宏定义
#ifndef MODBUSSTR_H和#define MODBUSSTR_H,以确保文件只被包含一次。 - 一些タイプ别名的定义,among them
uchar、uint、uint8和uint16分别代表符号なし。文字、符号なし。整数和不同宽度的符号なし。整数。 StrRxd構造体定义,用于受信バッファ。的相关データ構造。这个構造体包括以下成员:
pool[255]:用于存储受信的データ的バッファ,最大長さ为255バイト。front:头指针,指向バッファ的开头。rear:尾指针,指向バッファ的末尾。rd_byte:用于暂存読み取り的データ。frm_num:バッファ中的フレーム数量。add_buf[16]:用于存放受信バッファ。的アドレス,可以存放16个フレームアドレス,奇数位是首アドレス,偶数位是尾アドレス。rec_buf[255]:用于存储去除包头和包尾后的データ,只保留一フレーム有效データ。start_0x7e:用于标志是否受信到フレーム头标志。end_0x0d:用于标志是否受信到フレーム尾标志。
StrTxd構造体定义,用于送信バッファ的相关データ構造。这个構造体包括以下成员:
pool[255]:用于存储送信的データ的ASCIIコード形式的バッファ,最大長さ为255バイト。combuf[255]:用于存储送信的データ的HEX形式的バッファ,最大長さ为255バイト。txd_len:送信データの長ささ。
这个头文件定义了用于Modbus通信的データ構造,可以在应用程序中包含此头文件以アクセス这些データ構造和タイプ别名。这有助于更好地组织和管理Modbus通信中的データ。
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);
这段代码是一个包含了一些宏定义、データ構造的头文件 "ModBusStr.h" 和其他的相关头文件 "reg51.h",以及定义了一些全局变量和函数原型。
以下是代码中的一些重要元素:
- 头文件包含:
"reg51.h":这是用于 8051 系列单片机的標準头文件,提供了与该系列芯片相关的レジスタ和宏定义。"ModBusStr.h":这是你自己作成的头文件,包含了 Modbus 通信相关的データ構造和タイプ别名。
- 宏定义:
OK和ERROR:定义了2つ常量,分别为 1 和 0,通常用于表示函数执行成功和失敗。RIGHT和WRONG:定义了2つ常量,通常用于表示某些条件或操作的成功和失敗。POOLLEN:定义了バッファ的最大長さ为 255。INIT_COMMAND、START_COMMAND、END_COMMAND和ALARM_COMMAND:定义了一些命令常量,表示不同的操作。FRAME_START和FRAME_END:定义了フレーム的起始和结束标志。VER和ADDR:定义了版本号和アドレス。M_CID:定义了デバイス的识别码。
- 外部全局变量声明:
StrRxd xdata sys_rxd和StrTxd xdata sys_txd:声明了2つ外部全局变量,sys_rxd和sys_txd,这些变量是在其他源文件中定义的,用于存储 Modbus 通信相关的データ。
- 外部函数原型声明:
void init_proc_rxd(void)、void process_rxd(void)和void init_serial(void):这些函数原型声明用于初期化受信処理、通信処理和シリアルポート初期化。uint8 lchksum(uint8 data_len)、void txd_sta(void)、void txd_man(void)和void txd_uni(uint8 cid2):这些函数原型声明用于計算長さチェック和、送信系统告警信息、送信厂家信息和送信系统通信信息。
这段代码组织了 Modbus 通信相关的データと函数,并経由头文件将这些定义和声明提供给其他源文件使用。源文件可以包含这个头文件来アクセス这些定义和声明,从而実装 Modbus 通信功能。
MainTest
#include "ModBus.h"
void main(void)
{
init_serial();//初期化シリアルポート
init_proc_rxd();//初期化シリアル通信变量
while(1)
{
process_rxd();//通信処理函数 受信バッファ。中的データ 入処理バッファ
}
}
这是一个8051单片机上的主程序サンプル,用于执行Modbus通信処理。在主函数中,它按照以下步骤进行操作:
- 包含
ModBus.h头文件,该文件应该包含すべての必需的定义、全局变量和函数原型以サポートModbusCommunication。 - 调用
init_serial()函数,用于初期化シリアル通信,这是設定和准备与其他デバイス通信的重要一步。 - 调用
init_proc_rxd()函数,用于初期化シリアル通信变量。这一步通常是为了确保通信变量处于正确的初始ステータス。 - 进入一个无限循环(
while(1)),在循环中不断执行以下操作:
- 调用
process_rxd()函数,这个函数用于通信処理,受信バッファ。中的データ并进行処理。通常,这是一个持续监听和処理来自其他デバイス的Modbus通信リクエスト的过程。
整1つの手続き将不断运行,待機中来自其他デバイス的通信リクエスト,然后执行相应的操作。这个サンプル中主要用于Modbus通信的初期化和処理,实际的通信逻辑和レスポンス将在 process_rxd() 函数実現しました。

Leave a Reply