📄 modbus.c
字号:
#include"pic18.h"
#define crl RB1
unsigned char checkerror,recetimeout,localaddr=0x01;
unsigned char rececount=0,rececount_temp=0, flag_time0=0;
unsigned char send_buf[64];
unsigned char rece_buf[64];
unsigned char sendposi,sendcount;
unsigned int crcdata;
void write_mul_register();
void interrupt HI_ISR();
void interrupt low_priority LOW_ISR();
void check_modbus();
void readregister();
void force_one_register();
void int_time0();
void write_mul_register();
int crc16(char *puchMsg, int usDataLen) ;
//void crc16(char *puchMsg, int usDataLen) ;
/* CRC 高位字节值表 */
const char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位字节值表*/
const char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
void int_mod()
{unsigned char i;
TRISC|=0X80;
TRISB&=0Xfd;
PORTC&=0X00;
crl=0;
TXSTA|=0X04;//高速
RCSTA|=0X90;//串口允许,接受允许
BAUDCON&=0X00;
SPBRG=0X67;
INTCON|=0XC0;
IPEN=1;//中断优先级使能
RCIP=0;//收发低优先级
RCIE=1;
CREN=1;
RCIF=0;
TMR0IF=0;
for(i=0;i<63;i++)
{send_buf[i]=0x00;
rece_buf[i]=0x00;}
}
void int_time0()
{ T0CON=0X47;//8位时钟,256分频
TMR0ON=0;
TMR0L=0Xc8;//3.5MS
TMR0IE=1;
INTCON2=0X04;//TMR0高优先级,其他都低
}
void interrupt HI_ISR()
{ if(TMR0IF)
{TMR0IF=0;
CREN=0;//清OERR
crl=1;//发状态
TMR0ON=0;
TMR0L=0Xc8;//3.5MS
rececount_temp=rececount;
rececount=0;//超时重新开始
checkerror=0;
flag_time0=1;//一帧接受完,等候数据处理
}
//--------send
}
void interrupt low_priority LOW_ISR()
{ if (RCIF==1)
{ RCIF=0;
rece_buf[rececount]=RCREG;
if((FERR==1)&&(OERR==1))//帧有误
{checkerror=2; }
rececount++;
rececount&=0X3F;//最多接受64个字节
TMR0ON=0;
TMR0L=0X38;
TMR0ON=1;
}
}
void check_modbus()
{unsigned char temp;
unsigned int crc_temp;
CREN=0;
if ((rececount_temp==0x08)&&(rece_buf[0]==localaddr))
{
crcdata=crc16(rece_buf,6);
crc_temp=(rece_buf[6]<<8)+(rece_buf[7]);
if((crcdata==crc_temp)&&(checkerror==0x00))//先低后高
{ if(rece_buf[1]==3) //function3
readregister();
else if(rece_buf[1]==6) //function6
force_one_register();
}
}
else if((rececount_temp>0x08)&&(rece_buf[0]==localaddr)&&(checkerror==0x00))
{
temp=(rece_buf[6])+7;//没加校验码
crcdata=crc16(rece_buf,temp);
crc_temp=rece_buf[temp];
crc_temp=(crc_temp<<8)+(rece_buf[temp+1]);
if((crcdata==crc_temp)&&(rece_buf[1]==0x10)) //function16
write_mul_register();
}
crl=0;//接受
sendposi=0;
CREN=1;
TXEN=0;
flag_time0=0;
}
void beginsend()
{ unsigned char zero;
CREN=0;
crl=1;//发状态
TXEN=1;
for (sendposi=0;sendposi<sendcount;sendposi++)
{ TXREG=send_buf[sendposi];
while(TRMT==0) continue;
}
crl=0;//接受
sendposi=0;
CREN=1;
TXEN=0;
flag_time0=0;
}
void readregister()
{ unsigned char readbyte,i;
readbyte=rece_buf[5]*2;
if(rece_buf[3]==0x30)//读开关状态
{// getregisterval();//-----
send_buf[0]=localaddr;
send_buf[1]=0x03;
send_buf[2]=readbyte;
for(i=0;i<readbyte;i++)
{ // send_buf[i+3]=valdata;//数据------
}
readbyte+=3;
crcdata=crc16(send_buf,readbyte);
send_buf[readbyte]=crcdata>>8;
++readbyte;
send_buf[readbyte]=(crcdata)&0xff;
sendcount=readbyte+1;
beginsend();
}
else if(rece_buf[3]==0x31)//读开关参数
{//getregisterval_canshu();//-----
send_buf[0]=localaddr;
send_buf[1]=0x03;
send_buf[2]=readbyte;
for(i=0;i<readbyte;i++)
{ //send_buf[i+3]=valdata_canshu;//数据------
}
readbyte+=3;
crcdata=crc16(send_buf,readbyte);
send_buf[readbyte]=crcdata>>8;
++readbyte;
send_buf[readbyte]=(crcdata)&0xff;
sendcount=readbyte+1;
beginsend();
}
}
void force_one_register()
{ send_buf[0]=localaddr;
send_buf[1]=0x06;
send_buf[2]=rece_buf[2];
send_buf[3]=rece_buf[3];
send_buf[4]=rece_buf[4];
send_buf[5]=rece_buf[5];
send_buf[6]=rece_buf[6];
send_buf[7]=rece_buf[7];
sendcount=8;
beginsend();
}
void write_mul_register()
{ unsigned char temp;
send_buf[0]=localaddr;
send_buf[1]=rece_buf[1];
send_buf[2]=rece_buf[2];
send_buf[3]=rece_buf[3];
send_buf[4]=rece_buf[4];
send_buf[5]=rece_buf[5];
crcdata=crc16(send_buf,6);
send_buf[6]=crcdata>>8;
send_buf[7]=crcdata&0xff;
sendcount=0x08;
beginsend();
}
int crc16(char *puchMsg, int usDataLen)
{
unsigned int uchCRCHi=0xFF ; /* 高CRC字节初始化 */
unsigned int uchCRCLo=0xFF ; /* 低CRC 字节初始化 */
unsigned int uIndex ; /* CRC循环中的索引 */
while (usDataLen--) /* 传输消息缓冲区 */
{
uIndex = uchCRCHi ^ *(puchMsg++) ; /* 计算CRC */
uchCRCHi = (uchCRCLo )^( auchCRCHi[uIndex]) ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi<<8)|(uchCRCLo) ;
}
main()
{int_mod();
int_time0();
while(1)
{if(flag_time0)
{
check_modbus();}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -