?? f280x_modbusprotocol.c
字號(hào):
//###########################################################################
//
// FILE: F280x_ModbusProtocol.c
//
// TITLE: F280x ModbusProtocol Application Functions.
//
//###########################################################################
//
// Ver | dd mmm yyyy | Who | Description of changes
// =====|=============|======|===============================================
// 1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha)
// | | | Changed USER0-USER11 to USER1-USER12 to match the CPU guide
//###########################################################################
#include "F280x_Application.h" // F280x Headerfile Include File
#include "F280x_EMC.h" // F280x Examples Include File
#include "F280x_CommDefault.h" // F280x Examples Include File
/*CRC 高位字節(jié)值表*/
const unsigned int auchCRCHi[] = {
0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041,
0x00C1, 0x8140, 0x00C1, 0x8140, 0x01C0,
0x8041, 0x01C0, 0x8041, 0x00C1, 0x8140,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x00C1,
0x8140, 0x01C0, 0x8041, 0x01C0, 0x8041,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x00C1,
0x8140, 0x00C1, 0x8140, 0x01C0, 0x8041,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140,
0x01C0, 0x8041, 0x01C0, 0x8041, 0x00C1,
0x8140, 0x01C0, 0x8041, 0x00C1, 0x8140,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140,
0x01C0, 0x8041, 0x00C1, 0x8140, 0x01C0,
0x8041, 0x01C0, 0x8041, 0x00C1, 0x8140,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041,
0x00C1, 0x8140, 0x00C1, 0x8140, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041,
0x01C0, 0x8041, 0x00C1, 0x8140, 0x01C0,
0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140,
0x01C0, 0x8041, 0x01C0, 0x8041, 0x00C1,
0x8140, 0x00C1, 0x8140, 0x01C0, 0x8041,
0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
0x8041, 0x00C1, 0x8140
} ;
/*CRC低位字節(jié)值表*/
const unsigned int auchCRCLo[] = {
0x00C0, 0xC101, 0xC303, 0x02C2, 0xC606,
0x07C7, 0x05C5, 0xC404, 0xCC0C, 0x0DCD,
0x0FCF, 0xCE0E, 0x0ACA, 0xCB0B, 0xC909,
0x08C8, 0xD818, 0x19D9, 0x1BDB, 0xDA1A,
0x1EDE, 0xDF1F, 0xDD1D, 0x1CDC, 0x14D4,
0xD515, 0xD717, 0x16D6, 0xD212, 0x13D3,
0x11D1, 0xD010, 0xF030, 0x31F1, 0x33F3,
0xF232, 0x36F6, 0xF737, 0xF535, 0x34F4,
0x3CFC, 0xFD3D, 0xFF3F, 0x3EFE, 0xFA3A,
0x3BFB, 0x39F9, 0xF838, 0x28E8, 0xE929,
0xEB2B, 0x2AEA, 0xEE2E, 0x2FEF, 0x2DED,
0xEC2C, 0xE424, 0x25E5, 0x27E7, 0xE626,
0x22E2, 0xE323, 0xE121, 0x20E0, 0xA060,
0x61A1, 0x63A3, 0xA262, 0x66A6, 0xA767,
0xA565, 0x64A4, 0x6CAC, 0xAD6D, 0xAF6F,
0x6EAE, 0xAA6A, 0x6BAB, 0x69A9, 0xA868,
0x78B8, 0xB979, 0xBB7B, 0x7ABA, 0xBE7E,
0x7FBF, 0x7DBD, 0xBC7C, 0xB474, 0x75B5,
0x77B7, 0xB676, 0x72B2, 0xB373, 0xB171,
0x70B0, 0x5090, 0x9151, 0x9353, 0x5292,
0x9656, 0x5797, 0x5595, 0x9454, 0x9C5C,
0x5D9D, 0x5F9F, 0x9E5E, 0x5A9A, 0x9B5B,
0x9959, 0x5898, 0x8848, 0x4989, 0x4B8B,
0x8A4A, 0x4E8E, 0x8F4F, 0x8D4D, 0x4C8C,
0x4484, 0x8545, 0x8747, 0x4686, 0x8242,
0x4383, 0x4181, 0x8040
};
//const Uint16 bd_485_delay[]={26667,13333,6667,3333,1666,833,417};//延時(shí)1個(gè)字符時(shí)限
const Uint16 bd_485_delay[]={36667,18333,9167,4583,2292,1146,573};//延時(shí)1個(gè)字符時(shí)限
void GetSoe(Uint16 no);
//-------------------------------------------------------------------
//
//Modbus網(wǎng)絡(luò)協(xié)議子程序
//
//CRC校驗(yàn)函數(shù)
Uint16 CRC16(Uchar * p_crc_msg, Uint16 crc_len)
{
unsigned char crc_lo=0xff;
unsigned char crc_hi=0xff;
unsigned char crc_index;
unsigned int crc_value;
while(crc_len--)
{
crc_index=crc_hi^((*p_crc_msg++)&0xff);//080409crc_index=crc_hi^*p_crc_msg++;
//crc_hi=crc_lo^auchCRCHi[crc_index];
//crc_lo=auchCRCLo[crc_index];
if(crc_index==crc_index/2*2)
{//偶數(shù)位取其高字節(jié)
crc_hi=crc_lo^(auchCRCHi[crc_index/2]>>8);
crc_lo=auchCRCLo[crc_index/2]>>8;
}
else
{//奇數(shù)位取其低字節(jié)
crc_hi=crc_lo^(auchCRCHi[crc_index/2]&0xff);
crc_lo=auchCRCLo[crc_index/2]&0xff;
}
}
crc_value=crc_hi<<8|crc_lo;
return crc_value;
}
//Modbus協(xié)議初始化
void InitSerModbus(Uchar flag)
{
if(flag==0x55)//因保存定值的退出不再進(jìn)行初始化
return;
SerModbus.Access=0;
SerModbus.Busy=0;
SerModbus.receive_count=0;
SerModbus.send_count=0;
SerModbus.send_head=0;
SerModbus.crc_len=0;
SerModbus.enable_flag=0,
SerModbus.start_flag=0;
SerModbus.end_flag=0;
SerModbus.ck_count=0;
SerModbus.ck_point=0;
SerModbus.ck_flag=0;
SerModbus.event_report=0;
SerModbus.receive_flag=0;//接收幀計(jì)時(shí)
SerModbus.send_flag=0;//發(fā)送幀計(jì)時(shí)
SerModbus.r_timer=0;//接收幀計(jì)時(shí)
SerModbus.s_timer=0;//發(fā)送幀計(jì)時(shí)
/*
soe_no=0;
soe_id=0;
soe_count=0;
soe_flag=0;
*/
}
//Modbus異常應(yīng)答返回
void ErrorResponse(Uchar err)
{//err-異常碼 1-非法功能,2-非法數(shù)據(jù)地址,3-非法數(shù)據(jù)值
///unsigned char com_type;
unsigned int crc_result;
SerModbus.Busy=0xff;//置通訊狀態(tài)忙標(biāo)志
SerModbus.send_msg[1]=SerModbus.send_msg[1]|0x80;
SerModbus.send_msg[2]=err;//異常碼
SerModbus.crc_len=3;
crc_result=CRC16((Uchar *)&SerModbus.send_msg[0],SerModbus.crc_len);
SerModbus.send_msg[3]=crc_result&0xff;
SerModbus.send_msg[4]=(crc_result>>8)&0xff;
SerModbus.send_count=SerModbus.crc_len+2;
SerModbus.s_timer=0;//發(fā)送記時(shí)清零
SerModbus.send_flag=0xff;//置發(fā)送標(biāo)志
//com_type=COM_SER;
//ComSendCtrl(com_type);//通訊口發(fā)送控制
ComSendCtrl(Com.port_typ);
}
//Modbus接收通信幀控制
void ModbusFrameCtrl(void)
{
Uint16 crc_result,crc_receive;
//發(fā)送幀處理
if(SerModbus.send_flag)
{
//if(SerModbus.s_timer>(Uint32)bd_485_delay[dzbd]*7*SAMPLEPOINT/20000+1)
if(SerModbus.s_timer>((Uint32)bd_485_delay[dzbd]*7*SAMPLEPOINT>>14)-1)
{//判斷發(fā)送間隔停頓時(shí)限大于7字符時(shí)限
SerModbus.enable_flag=0;
SerModbus.send_flag=0;//發(fā)送標(biāo)志清零
SerModbus.send_count=0;
SerModbus.send_head=0;
SerModbus.Access=0;//釋放命令
SerModbus.Busy=0;
Ser.port_right=0;//釋放通訊口
com1_reset_cnt=0;
com1_de=0;//關(guān)閉422發(fā)送使能端
}
}
//接收幀處理
if(SerModbus.receive_flag && SerModbus.start_flag)
{
//if(SerModbus.r_timer>(Uint32)bd_485_delay[dzbd]*4*SAMPLEPOINT/20000+1)
if(SerModbus.r_timer>((Uint32)bd_485_delay[dzbd]*4*SAMPLEPOINT>>14)-1)
{//判斷接收間隔停頓時(shí)限大于3.5字符時(shí)限
SerModbus.start_flag=0;
SerModbus.receive_flag=0;
SerModbus.end_flag=0x55;//置幀結(jié)束標(biāo)志
}
}
if(SerModbus.end_flag!=0x55)
{//幀接收處理過程中
return;
}
//幀接收完成
Ser.port_right=0x55;//控制串口通訊口
if(SerModbus.receive_count>2)
SerModbus.crc_len=SerModbus.receive_count-2;//CRC16校驗(yàn)長(zhǎng)度
else
SerModbus.crc_len=0;
SerModbus.receive_count=0;
SerModbus.enable_flag=0;
SerModbus.receive_flag=0;
SerModbus.start_flag=0;
SerModbus.end_flag=0;
SerModbus.send_msg[0]=dzid;
SerModbus.send_msg[1]=SerModbus.receive_msg[1];
//地址域解析
if((SerModbus.receive_msg[0]!=dzid && SerModbus.receive_msg[0]!=0) || SerModbus.crc_len==0)
{//幀接收解析地址域不匹配
Ser.port_right=0;
return;
}
//CRC16校驗(yàn)
crc_result=CRC16((Uchar *)&SerModbus.receive_msg[0],SerModbus.crc_len);
crc_receive=SerModbus.receive_msg[SerModbus.crc_len]*256+SerModbus.receive_msg[SerModbus.crc_len+1];
if(crc_result!=crc_receive)
{//CRC校驗(yàn)不成功,非法數(shù)據(jù)
Ser.port_right=0;
return;
}
SerModbus.Access=0xff;//校驗(yàn)成功置命令啟動(dòng)標(biāo)志
}
void RemoteCtrl()//開出監(jiān)視控制
{
Uint16* p_kc_time;
if (SerModbus.ck_flag==0 || bittst((Uint16 * )&SerModbus.event_report,0)==0)
{
return;
}
p_kc_time=(Uint16*)&dzkc1_t;
if(SerModbus.ck_point<2) SerModbus.ck_point=2;
if (SerModbus.ck_count>(*(p_kc_time+SerModbus.ck_point-2))*MACROSAMPLE_TIMES)
{
bitclr(&kc_value,SerModbus.ck_point);
SerModbus.ck_count=0;
SerModbus.ck_flag=0;
SerModbus.ck_point=0;
bitclr((Uint16 * )&SerModbus.event_report,0);
}
else
SerModbus.ck_count++;
}
//Modbus消息控制
void SerModbusCtrl(void)
{
Uchar broad_flag,opcode,flag;
Uint16 offset,s_addr,d_num,ctrl_point,byte,id,crc_result,value,i,j,k;
Uint16* p_addr;
ModbusFrameCtrl();//MODBUS通訊幀控制
RemoteCtrl();//開出監(jiān)視控制
//--無接收命令或者通訊忙狀態(tài)程序立即返回
if ((SerModbus.Access!=0xff || Ser.port_right!=0x55) || SerModbus.Busy==0xff)
{ //--無接收命令或者通訊忙狀態(tài)程序立即返回
return;
}
SerModbus.Busy=0xff;//置通訊狀態(tài)忙標(biāo)志
SerModbus.send_count=0;
//com_type=Com.port_typ;
//com_type=COM_SER;
broad_flag=0;
if(SerModbus.receive_msg[0]==0)
{//廣播命令
broad_flag=0xff;
}
opcode=SerModbus.receive_msg[1];//解析功能碼
if (opcode<1 || opcode>24)
{//功能碼異常
ErrorResponse(1);
return;
}
switch(opcode)
{
case 1://Read Coil Status
SerModbus.send_count=SerModbus.crc_len+2;
break;
case 2://Read Input Status--遙信量
///offset=SerModbus.receive_msg[2]*256+SerModbus.receive_msg[3];
///d_num=SerModbus.receive_msg[4]*256+SerModbus.receive_msg[5];
s_addr=SerModbus.receive_msg[2]*256+SerModbus.receive_msg[3];
d_num=SerModbus.receive_msg[4]*256+SerModbus.receive_msg[5];
j=0; while((s_addr<DigitalComm[j].start_addr || s_addr>=DigitalComm[j+1].start_addr) && j<DIGITAL_NO-1){j++;}//檢索起始地址--地址范圍:Start_pre<=x && x<Start_next
offset = s_addr-DigitalComm[j].start_addr;//起始地址偏移量
//召喚數(shù)據(jù)地址檢測(cè)
if (d_num<1 || ((d_num-1)>>4)+6 > MACROCOMM_S_NO)
{
ErrorResponse(3);//非法數(shù)據(jù)值
return;
}
//響應(yīng)數(shù)據(jù)幀
//數(shù)據(jù)類型為BYTE--8bit
SerModbus.send_msg[2]=((d_num-1)>>3)+1;//字節(jié)數(shù)目
for(i=0;i<SerModbus.send_msg[2];i++)
{
//響應(yīng)數(shù)據(jù)區(qū)域索引
/*
for(k=0;k<8;k++)
{
if (offset>=DigitalComm[j].data_num)
{
if ((offset+DigitalComm[j].start_addr)>=DigitalComm[j+1].start_addr && j<DIGITAL_NO-1)
{
offset = 0;j++;
if (bittst(DigitalComm[j].p_addr,offset))
bitset((Uint16*)&value,k);//狀態(tài)量置1
else
bitclr((Uint16*)&value,k);//狀態(tài)量清0
}
else bitclr((Uint16*)&value,k);//狀態(tài)量清0
}
else
{
if (bittst(DigitalComm[j].p_addr,offset))
bitset((Uint16*)&value,k);//狀態(tài)量置1
else
bitclr((Uint16*)&value,k);//狀態(tài)量清0
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -