- #include<modbus.h>
- bit Search_Counta;//首次寻优标志 1
- bit Search_Countb;//首次寻优标志 2
- unit8 Count; //寻优计数值 (错误在这里!!!!!!!!)
- unit8 ReceCount; //串行口1的接收数据计数值
- unit8 SendCount; //串行口1发送数据计数值
- unit16 Init_Value=0; //寻优初值
- uint16 Term_Value=50; //寻优终值
- uint8 Search_Steps=50;//寻优步数
- uint8 idata resvbuf[16],Sendbuf[64];//串行口 1 的接收缓冲区和发送缓冲区
- uint16 xdata Re Wrbuf[32]; //可读写缓冲区
- uint16 xdata Register[32]; //寄存器缓冲区
- uint16 D_Val; //占空比的数字量
- bit Error; //错误标志位
- uint8 bdata Coil1=0xff;//8 位线圈状态
- sbit Coil1_bit0=Coil1^0;
- sbit Coil1_bit1=Coil1^1;
- sbit Coil1_bit2=Coil1^2;
- sbit Coil1_bit3=Coil1^3;
- sbit Coil1_bit4=Coil1^4;
- sbit Coil1_bit5=Coil1^5;
- sbit Coil1_bit6=Coil1^6;
- sbit Coil1_bit7=Coil1^7;
- void Init System(); //初始化函数
- void Delay(void); //延时函数
- void Check Message(void);//功能码判断函数
- void Send Data();//发送数据函数
- void Read Coil(void);//读线圈函数
- void Read Registers(void);//读寄存器函数
- void Force Singal Coil(void);//强置单线圈函数
- void Set One Register Val(void);//预置单寄存器函数
- uint8 Get SWVal(uint16 Address);
- bit Set Coil Val(uint16 Address,bit Val);
- bit Set Register Val(uint16 Address1,uint16 Val1);
- uint16 crccheck(uint8 *puch Msg, uint8 us Data Len);
- void Delay_us(uint8 t);
- void Write_TLC(uint16 dat);
- void Self_optimization();
- //CRC 校验查表码值
- const uint8 code auch CRCHi[] ={
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41,
- 0x00, 0x C1, 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0,
- 0x80, 0x41, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1,
- 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0, 0x80, 0x41,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1,
- 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40,
- 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1,
- 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40,
- 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0,
- 0x80, 0x41, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41,
- 0x00, 0x C1, 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41,
- 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40,
- 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0, 0x80, 0x41, 0x00, 0x C1,
- 0x81, 0x40, 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41,
- 0x00, 0x C1, 0x81, 0x40, 0x01, 0x C0, 0x80, 0x41, 0x01, 0x C0,
- 0x80, 0x41, 0x00, 0x C1, 0x81, 0x40};
- const uint8 code auch CRCLo[] = {
- 0x00, 0x C0, 0x C1, 0x01, 0x C3, 0x03, 0x02, 0x C2, 0x C6, 0x06,
- 0x07, 0x C7, 0x05, 0x C5, 0x C4, 0x04, 0x CC, 0x0C, 0x0D, 0x CD,
- 0x0F, 0x CF, 0x CE, 0x0E, 0x0A, 0x CA, 0x CB, 0x0B, 0x C9, 0x09,
- 0x08, 0x C8, 0x D8, 0x18, 0x19, 0x D9, 0x1B, 0x DB, 0x DA, 0x1A,
- 0x1E, 0x DE, 0x DF, 0x1F, 0x DD, 0x1D, 0x1C, 0x DC, 0x14, 0x D4,
- 0x D5, 0x15, 0x D7, 0x17, 0x16, 0x D6, 0x D2, 0x12, 0x13, 0x D3,
- 0x11, 0x D1, 0x D0, 0x10, 0x F0, 0x30, 0x31, 0x F1, 0x33, 0x F3,
- 0x F2, 0x32, 0x36, 0x F6, 0x F7, 0x37, 0x F5, 0x35, 0x34, 0x F4,
- 0x3C, 0x FC, 0x FD, 0x3D, 0x FF, 0x3F, 0x3E, 0x FE, 0x FA, 0x3A,
- 0x3B, 0x FB, 0x39, 0x F9, 0x F8, 0x38, 0x28, 0x E8, 0x E9, 0x29,
- 0x EB, 0x2B, 0x2A, 0x EA, 0x EE, 0x2E, 0x2F, 0x EF, 0x2D, 0x ED,
- 0x EC, 0x2C, 0x E4, 0x24, 0x25, 0x E5, 0x27, 0x E7, 0x E6, 0x26,
- 0x22, 0x E2, 0x E3, 0x23, 0x E1, 0x21, 0x20, 0x E0, 0x A0, 0x60,
- 0x61, 0x A1, 0x63, 0x A3, 0x A2, 0x62, 0x66, 0x A6, 0x A7, 0x67,
- 0x A5, 0x65, 0x64, 0x A4, 0x6C, 0x AC, 0x AD, 0x6D, 0x AF, 0x6F,
- 0x6E, 0x AE, 0x AA, 0x6A, 0x6B, 0x AB, 0x69, 0x A9, 0x A8, 0x68,
- 0x78, 0x B8, 0x B9, 0x79, 0x BB, 0x7B, 0x7A, 0x BA, 0x BE, 0x7E,
- 0x7F, 0x BF, 0x7D, 0x BD, 0x BC, 0x7C, 0x B4, 0x74, 0x75, 0x B5,
- 0x77, 0x B7, 0x B6, 0x76, 0x72, 0x B2, 0x B3, 0x73, 0x B1, 0x71,
- 0x70, 0x B0, 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 timer0_INT(void) interrupt 1 using 1 //定时/计数器 0 中断
- {
- TR0=0;
- Error=1;
- if((resvbuf[0]==IN_Address)&&(Rece Count>=8))// 判断接收到的设备地址是否与上位机的地址相等,并成功接收上位机发送的指令
- Error=0;
- }
- void Uart1_INT(void) interrupt 4 using 3 //串口 1 中断
- {
- if(RI) //RI 为接收中断标志位,为 1 表示一个数据已经收到。
- {
- RI=0;
- resvbuf[Rece Count++]=SBUF;
- TR0=0;
- TH0=(65536-3688)/256;
- TL0=(65536-3688)%256; //定时器 0 定时 4ms
- TR0=1;
- }
- if(TI) ////TI 为发送中断标志位,为 1 表示一个数据已经发送完毕。
- {
- TI=0;
- }
- }
- /********************************************
- Function:CRC 校验子函数
- ********************************************/
- uint16 crccheck(uint8 *puch Msg, uint8 us Data Len)
- {
- uint8 uch CRCHi = 0x FF ;
- uint8 uch CRCLo = 0x FF ;
- uint8 uIndex ;
- while (usDataLen--)
- {
- uIndex = uchCRCHi^*puchMsg++ ;
- uchCRCHi = uch CRCLo ^ auch CRCHi[u Index] ;
- uchCRCLo = auch CRCLo[u Index] ;
- }
- return (uch CRCHi << 8 | uch CRCLo) ; //生成校验码,高位在前,低位在后。
- }
- /********************************************
- Function
- :延时子函数
- ********************************************/
- void Delay(void)
- {
- uint16 i;
- for(i=0;i<3600;i++)
- {
- _nop_();
- }
- }
- //初始化函数
- void Init System()
- {
- Rece Count=0;
- Rece2Count=0;
- Count = 0;
- Search_Counta = 0;
- Search_Countb = 0;
- DA_Val = 0;
- Register[9] = 0;//初始化时占空比输出为 0
- Re Wrbuf[21] = 0;//初始工作时控制信号为 0
- Re Wrbuf[22] = 0;//初始工作时电流为 0
- Re Wrbuf[23] = 0;//初始工作时电流为 0
- TMOD=0x21;//定时器 1 工作方式 2,作为波特率发生器,定时器 0 工作方式1
- SCON=0x50;//串行口 1 工作方式 1,允许接收
- BRT=0xfd; //串行口 2 波特率 [url=mailto:9600@11.0592MHz]9600@11.0592MHz[/url]
- TH1=0xfd;
- TL1=0xfd;//串行口 1 波特率 [url=mailto:9600@11.0592MHz]9600@11.0592MHz[/url]
- IT0 = 0; //设置外部中断 0 为低电平触发
- IE=0x93;//EA=1,ES=1,ET0=1,EX0 = 1
- AUXR=0x10;//AUXR:辅助寄存器。BRTR=1,允许独立波特率发生器运行。
- S2SMOD=0,串口 2 的波特率不加倍.
- //EXTRAM=0,允许使用内部扩展的 1024 字节扩展 RAM。
- TR1=1;//启动定时器 1
- CJ();
- }
- /********************************************
- Function
- :单片机应答(发送数据)子函数
- ********************************************/
- void Send Data()
- {
- uint8 i;
- uint16 crctemp;
- Sendbuf[0]=resvbuf[0]; //发送数据的第一个字节为上位机的地址
- Sendbuf[1]=resvbuf[1]; //发送数据的第二个字节为功能码
- crctemp=crccheck(Sendbuf,Send Count-2);//计算发送的校验码
- Sendbuf[Send Count-2]=crctemp&0xff;
- Sendbuf[Send Count-1]=crctemp>>8; //发送消息时,CRC 低位在前、高位在后
- for(i=0;i<Send Count;i++)
- {
- SBUF=Sendbuf[i];
- Delay();
- }
- }
- /**********************************
- 函数功能:Modbus 功能判断函数
- **********************************/
- void Check Message(void)
- {
- uint16 crctemp,temp;
- crctemp=crccheck(resvbuf,Rece Count-2); //生成校验码
- temp=resvbuf[Rece Count-1];//接收到的校验码的高字节
- temp=temp<<8|resvbuf[Rece Count-2];
- if(temp!=crctemp) //判断接收到的校验码和生成的校验码是否一致
- {
- Error=1; //校验码不一致,错误标志位置 1.
- }
- Rece Count=0; //单片机接收数据(上位机发送的数据)无效,接收字节变量清零。
- if(!Error)//校验码一致
- {
- ES=0;//关串口 1 中断
- ET0=0;//关定时器 0 中断
- switch(resvbuf[1]) //判断功能码
- {
- case 2: Read Coil();break;
- case 3: Read Registers();break;
- case 5: Force Singal Coil();break;
- case 6: Set One Register Val();break;
- default: Error=1;
- }
- ET0=1;
- ES=1;
- }
- }
- /**********************************
- 函数功能:读取位函数
- Sendbuf[i+3]表示 P0.0-P0.7 的开关状态
- 若为高电平,则表明端口对应的开关断开;
- 若为低电平,则表明端口对应的开关闭合;
- **********************************/
- void Read Coil(void)
- {
- uint16 Start Address;//寄存器起始地址
- uint16 temp Address;
- uint8 Coil Num,i,Byte Num,j;
- uint8 Coil Val;
- bit exit=0; //是否读完输入开关状态标志位(exit=1 表示读完了)
- Start Address=resvbuf[2]; //起始地址高 8 位
- Start Address=Start Address|resvbuf[3];//起始地址低 8 位
- temp Address=Start Address;
- Coil Num=resvbuf[5];//读取的位数
- Byte Num=Coil Num/8; //折算成字节
- if(Coil Num%8!=0)
- Byte Num++;
- Sendbuf[2]=Byte Num;//返回的字节数
- for(i=0;i<Byte Num;i++)
- {
- Sendbuf[i+3]=0;//返回的数据 1 初始值为 0
- for(j=0;j<8;j++)
- {
- Coil Val=Get SWVal(Start Address);
- Sendbuf[i+3]|=Coil Val<<j;//读取每一位的状态
- Start Address++;
- if(Start Address>=temp Address+Coil Num)//判断是否读完 Coil Num个线圈状态
- {
- exit=1;
- break;//读完退出
- }
- }
- if(exit==1)
- break;
- }
- Send Count=5+Byte Num;//发送的字节数(发送的地址码、功能码、从机返回的字节数、CRC 校验码共占 5 个字节)
- Send Data();
- }
- /**********************************
- 函数功能:获取开关状态函数。8 路数字量输入 Address1=上位机中设置的寄存
- 器地址减 1.在上位机中增加通道:寄存器类型设置成【1 区】输入继电器,寄存
- 器地址依次设置成 1-8
- **********************************/
- uint8 Get SWVal(uint16 Address1)
- {
- uint8 Coil Val,Switch=0xff;
- Switch=P0;
- switch(Address1&0x0f)
- {
- case 0: Coil Val=Switch>>1&0x01;break; // P0.0 的开关状态
- case 1: Coil Val=Switch>>2&0x01;break; // P0.1 的开关状态
- case 2: Coil Val=Switch>>3&0x01;break; // P0.2 的开关状态
- case 3: Coil Val=Switch>>4&0x01;break; // P0.3 的开关状态
- case 4: Coil Val=Switch>>5&0x01;break; // P0.4 的开关状态
- case 5: Coil Val=Switch>>6&0x01;break; // P0.5 的开关状态
- case 6: Coil Val=Switch>>7&0x01;break; // P0.6 的开关状态
- case 7: Coil Val=Switch>>8&0x01;break; // P0.7 的开关状态
- default: break;
- }
- return Coil Val;
- }
- /**********************************
- 函数功能:读取寄存器函数
- **********************************/
- void Read Registers(void)
- {
- uint16 Start Address;
- uint8 Byte Count,i;
- Start Address=resvbuf[2];
- Start Address=Start Address<<8|resvbuf[3];
- Byte Count=resvbuf[5]*2; //一个寄存器数据占 2 个字节
- Sendbuf[2]=resvbuf[5]*2; //上位机寄存器为 16 位占用两个字节 ?
- Sendbuf[2]=resvbuf[5]*2
- for(i=0;i<Byte Count;i+=2)//一个寄存器数据占 2 个字节
- {
- Sendbuf[i+4]=Re Wrbuf[Start Address]&0xff;
- Sendbuf[i+3]=Re Wrbuf[Start Address]>>8; //高位在前、低位在后
- Start Address++;
- }
- Send Count=Byte Count+5;
- Send Data();
- if(resvbuf[3] == 0x00)
- CJ(); //读电能采集模块数据
- }
- /**********************************
- 函数功能:强制单线圈函数
- **********************************/
- void Force Singal Coil(void)
- {
- uint16 Address,On Off;
- bit temp,Coil Val;
- Address=resvbuf[2]<<8|resvbuf[3];
- On Off=resvbuf[4]<<8|resvbuf[5];
- if(On Off==0x0000)
- {
- Coil Val=0;
- temp=Set Coil Val(Address,Coil Val);
- }
- else if(On Off==0x FF00)
- {
- Coil Val=1;
- temp=Set Coil Val(Address,Coil Val);
- }
- if(temp==1) //成功返回原命令
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count=8;
- Send Data();
- }
- else
- Error=1;
- }
- /**********************************
- 函数功能:设置位值函数
- 6 路数字量输出,Address=上位机中设置的寄存器地址减 1.
- 上位机中增加通道:寄存器类型设置成【0 区】输出继电器,操作方式设置成只
- 写 , 寄 存 器 地 址 依 次 设 置 成 1-6 , 即 可 强 制 Q55-Q0(P2.0-P2.5)
- 的 状 态 。
- **********************************/
- bit Set Coil Val(uint16 Address,bit Val)
- {
- bit result=1;
- switch(Address&0x0f)
- {
- case 0: Coil1_bit0=Val;break; //强制 P2.0(Q5)的状态
- case 1: Coil1_bit1=Val;break; //强制 P2.1(Q4)的状态
- case 2: Coil1_bit2=Val;break; //强制 P2.2(Q3)的状态
- case 3: Coil1_bit3=Val;break; //强制 P2.3(Q2)的状态
- case 4: Coil1_bit4=Val;break; //强制 P2.4(Q1)的状态
- case 5: Coil1_bit5=Val;break; //强制 P2.5(Q0)的状态
- case 6: Self_optimization();break; //自寻优开始
- default: result=0;break;
- }
- return result;
- }
- /**********************************
- 函数功能:设置单寄存器函数
- **********************************/
- void Set One Register Val(void)
- {
- uint16 R_Address,Register Val;
- bit temp1;
- R_Address=resvbuf[2];
- R_Address=R_Address<<8|resvbuf[3];
- R_Address=R_Address-90; //要设置的寄存器地址
- Register Val=resvbuf[4];
- Register Val=Register Val<<8|resvbuf[5];//要设置的寄存器值
- temp1=Set Register Val(R_Address,Register Val);
- if((temp1 == 1)&&(R_Address == 9)) //成功返回原命令
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count = 8;
- Send Data();
- D_Val = Register[9];
- Write_TLC(D_Val); //输出 D 值
- }
- else if((temp1 == 1)&&(R_Address == 10))
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count = 8;
- Send Data();
- Harm_Times = Register[10]&0x FF;
- }
- else if((temp1 == 1)&&(R_Address == 11))
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count = 8;
- Send Data();
- Init_Value = Register[11];
- Search_Counta = 0;
- }
- else if((temp1 == 1)&&(R_Address == 12))
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count = 8;
- Send Data();
- Term_Value = Register[12];
- Search_Countb = 0;
- }
- else if((temp1 == 1)&&(R_Address == 13))
- {
- Sendbuf[2]=resvbuf[2];
- Sendbuf[3]=resvbuf[3];
- Sendbuf[4]=resvbuf[4];
- Sendbuf[5]=resvbuf[5];
- Send Count = 8;
- Send Data();
- Search_Steps = Register[13]&0x FF;
- }
- else //否则置错误位
- Error=1;
- }
- /**********************************
- 函数功能:设置寄存器值函数
- **********************************/
- bit Set Register Val(uint16 Address1,uint16 Val1)
- {
- uint8 Addr;
- bit result1=1;
- Addr=Address1&0xff; //Register[]数组的大小为 32 个字节
- Register[Addr]=Val1;
- return result1;
- }
- void Delay_us(uint8 t)
- {
- uint8 i;
- for(i=0;i<12*t;i++)
- _nop_();
- }
复制代码
|