📄 modbus.c
字号:
#include ".\STC89c5x.H"
//串口通讯设置相关参数
#define IP_VALUE 0x10 //串行中断高优先级
#define TMOD_VALUE 0x21 //T0十六位定时器,T1 波特率发生器
#define SCON_VALUE 0x50 //方式1,10位,能接收
#define PCON_VALUE 0x00 //单倍波特率
#define BAUD_VALUE 0xFA //22.1184MHz晶振,波特率设定植为9600
#define TH0_VALUE 0xB8 //T0定时10mS判断信息帧结束
#define TL0_VALUE 0
#define T2CON_VALUE 0x00 //T2 act as 16 bit timer
#define RCAP2H_VALUE 0x6F //定时20ms
#define UART_COMPLETE 1
#define MOD_ADDR 1
#define UART_LEN 128
unsigned char bdata cy_flag;//程序处理标志单元
sbit cy_uartcomplete=cy_flag^3;//串口接受完一组数据
#define BIT_NUM 80
#define WORD_NUM 150
unsigned char cy_bitdata[BIT_NUM/8];//位存储区,可读可写
unsigned int iy_wdata[WORD_NUM];//字存储区,可读可写
unsigned char data cy_uartnumber;
unsigned char cy_receive_buf[UART_LEN];
sbit RTS_485=P3^5;
sbit RUN_FLAG=P3^2;//运行状态指示灯
void uart_timer_set(void)
{
TCON=0x00;
PCON=PCON_VALUE; //波特率选择
IP=IP_VALUE; //设置各中断优先级
TMOD=TMOD_VALUE; //设置各定时器的工作方式
T2CON=T2CON_VALUE;
SCON=SCON_VALUE; //设置串行工作方式
TH1=TL1=BAUD_VALUE; //设定波特率的值
TH0=TH0_VALUE;
TL0=TL0_VALUE;
TR1=1;
TR0=TI=RI=0;
}
//-----------------------------------------------------------------------------
union crc //check crc 2 byte;
{
unsigned int word;
struct
{
unsigned char hi;
unsigned char lo;
}bytes;
};
union crc crc_chec;
void crc_chec_fuc(unsigned char datain)
{
unsigned char i;
crc_chec.bytes.lo=crc_chec.bytes.lo^datain;
for(i=0;i<8;i++)
{
if((crc_chec.word & 0x0001)==1)
{
crc_chec.word=crc_chec.word>>1;
crc_chec.word=crc_chec.word^0xa001;
}
else
crc_chec.word=crc_chec.word>>1;
}
}
void start_crc_chec(void)
{
unsigned char i;
crc_chec.word=0xffff;
for(i=0;i<(cy_uartnumber-2);i++)
crc_chec_fuc(cy_receive_buf[i]);
}
void generic_crc(unsigned char cyz_num)
{
unsigned char i;
crc_chec.word=0xffff;
for(i=0;i<cyz_num;i++)
crc_chec_fuc(cy_receive_buf[i]);
cy_receive_buf[cyz_num+1]=crc_chec.bytes.hi;
cy_receive_buf[cyz_num]=crc_chec.bytes.lo;
}
//发送一个字节
void uart_send(unsigned char s)
{
SBUF=s;
while(TI!=1);
TI=0;
}
//发送一帧数据
void frame_send(unsigned char t)//发送数据桢
{
unsigned char i;
for(i=0;i<t;i++)
uart_send(cy_receive_buf[i]);
}
//-----------------------------------------------------------------------------
void uart_run(void)
{
unsigned char cy_q,cy_s,x,y,x_num,y_num;
if(cy_uartcomplete==UART_COMPLETE)
{
start_crc_chec();
if((crc_chec.bytes.hi==cy_receive_buf[cy_uartnumber-1])\
&&(crc_chec.bytes.lo==cy_receive_buf[cy_uartnumber-2])) //crc
{
EA=0;
RTS_485=!RTS_485;
switch(cy_receive_buf[1])
{
case 1://读位
if((cy_receive_buf[2]==0)&&(cy_receive_buf[4]==0)&&(cy_receive_buf[3]<BIT_NUM)\
&&(cy_receive_buf[5]<BIT_NUM)&&((cy_receive_buf[3]+cy_receive_buf[5])<BIT_NUM)) ////地址分析
{
x=cy_receive_buf[3]/8;//the byte no.x
y=cy_receive_buf[3]%8;//the byte no.x & y bit
x_num=cy_receive_buf[5]/8;
y_num=cy_receive_buf[5]%8;
if ((y_num!=0)||(y!=0))
x_num++;
for(cy_s=0;cy_s<x_num;cy_s++)
cy_receive_buf[cy_s+3]=cy_bitdata[cy_s+x];
for(cy_s=0;cy_s<x_num;cy_s++)
{
crc_chec.bytes.lo=cy_receive_buf[cy_s+3];
crc_chec.bytes.hi=cy_receive_buf[cy_s+4];
crc_chec.word=crc_chec.word>>y;
cy_receive_buf[cy_s+3]=crc_chec.bytes.lo;
}
if(y_num!=0)
{
cy_s=0xff;
cy_s=cy_s>>(8-y_num);
cy_receive_buf[x_num+2]=cy_receive_buf[x_num+2]&cy_s;
}
if(y!=0)
x_num--;
cy_receive_buf[2]=x_num;//the number of the bytes
cy_uartnumber=3+x_num;
generic_crc(cy_uartnumber); generic_crc(cy_uartnumber);
cy_uartnumber=cy_uartnumber+2;
frame_send(cy_uartnumber);//发送数据
}
case 3://读寄存器
if((cy_receive_buf[2]==0)&&(cy_receive_buf[4]==0)&&(cy_receive_buf[3]<WORD_NUM)\
&&(cy_receive_buf[5]<WORD_NUM)&&((cy_receive_buf[3]+cy_receive_buf[5])<WORD_NUM)) ////地址分析
{
cy_receive_buf[2]=cy_receive_buf[5]*2;
cy_uartnumber=3;
cy_q=cy_receive_buf[3]+cy_receive_buf[5];
for(cy_s=cy_receive_buf[3];cy_s<cy_q;cy_s++)
{
cy_receive_buf[cy_uartnumber]=iy_wdata[cy_s]/0x100;
cy_uartnumber++;
cy_receive_buf[cy_uartnumber]=iy_wdata[cy_s]%0x100;
cy_uartnumber++;
}
generic_crc(cy_uartnumber);
cy_uartnumber=cy_uartnumber+2;
frame_send(cy_uartnumber);//发送数据
}
break;
case 5://写单个位
if((cy_receive_buf[2]==0)&&(cy_receive_buf[3]<BIT_NUM))////地址分析
{
x=cy_receive_buf[3]/8;//the byte no.x
y=cy_receive_buf[3]%8;//the byte no.x & y bit
if(cy_receive_buf[4]==0)
{
x_num=0xfe;
for(cy_s=0;cy_s<y;cy_s++)
x_num=(x_num<<1)|0x01;
cy_bitdata[x]=cy_bitdata[x]&x_num;
}
else{
x_num=0x01;
x_num=x_num<<y;
cy_bitdata[x]=cy_bitdata[x]|x_num;
}
frame_send(8);//发送数据
}
break;
break;
case 6://写单个寄存器
if((cy_receive_buf[2]==0)&&(cy_receive_buf[3]<WORD_NUM)) //地址分析
{
iy_wdata[cy_receive_buf[3]]=cy_receive_buf[4]*0x100+cy_receive_buf[5];//更改指定数据
frame_send(cy_uartnumber);//发送数据
}
break;
case 15://写多个位
break;
case 16://写多个寄存器
if((cy_receive_buf[2]==0)&&(cy_receive_buf[4]==0)&&(cy_receive_buf[3]<WORD_NUM)\
&&(cy_receive_buf[5]<WORD_NUM)&&((cy_receive_buf[3]+cy_receive_buf[5])<WORD_NUM)) ////地址分析
{
for(cy_s=0;cy_s<cy_receive_buf[6];cy_s++)
{
iy_wdata[cy_receive_buf[3]]=cy_receive_buf[cy_s+7]*0x100+cy_receive_buf[cy_s+8];//更改指定数据
cy_s++;
generic_crc(6);
frame_send(8);
}
}
break;
}
RTS_485=!RTS_485;
EA=1;
}
cy_uartcomplete=0;
cy_uartnumber=0;
ES=1;
}
}
//-----------------------------------------------------------------------------
void uart_int(void) interrupt 4 using 2
{
cy_receive_buf[cy_uartnumber]=SBUF;
RI=0;
TH0=TH0_VALUE;
TL0=TL0_VALUE;
TR0=1;
cy_uartnumber++;
if((cy_uartnumber>=128)||((cy_uartnumber==1)&&(cy_receive_buf[0]!=MOD_ADDR)))
cy_uartnumber=0;
}
//-----------------------------------------------------------------------------
void timer0(void) interrupt 1 using 3
{
TR0=0;
ES=0;
cy_uartcomplete=UART_COMPLETE;
RUN_FLAG=1;
}
main()
{
uart_timer_set();
ES=1;
ET0=1;
EA=1;
while(1)
{
uart_run();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -