单片机modbus下位机程序怎么编写

单片机modbus下位机程序怎么编写,第1张

这个是MODBUS控制电磁阀的一个程序。其中还有AD采集的部分。对CRC校验用查表的方法。至于怎样把校验的结果拆分成高低位字节,再发送,看程序吧。

#include"reg51.h"

#include"intrins.h"

#define uchar unsigned char

#define uint unsigned int

#define Pressure P0

////////////////

/////////////////////

uchar addr

uchar  Pressure_updata

uchar  Pressure_lowdata

/////////////////

sbit    Dcf_open=P1^0//电磁阀开启

sbit    Dcf_close=P1^1//电磁阀关闭

bit   dr

bit   Dcf_state=1

bit   Halfsecond=0

bit   Onesecond=0

//////////////////////////////

sbit   Mydress_set=P2^5

sbit    P_uplimite =P2^6

sbit   P_lowlimite=P2^7

sbit   Stor=P3^2

sbit    myint=P3^3

sbit   ADC_wr     =P3^6

sbit   ADC_rd     =P3^7

sbit   xuantong   =P1^7

sbit   addrset=P1^2

sbit   upset=P1^3

sbit   lowset=P1^4

/////////////////////////

uchar code   Myreturnstateopen[3] ={0x01,0x01,0x00}

uchar code   Myreturnstateclose[3]={0x01,0x01,0x01}

uchar code   Myreturnopen[3] ={0x01,0x01,0x10}

uchar code   Myreturnclose[3]={0x01,0x01,0x20}

uchar receive_count=0

uchar mysend[6],aq[8]

uchar Adc_value

unsigned  long   Mycount=0

uchar jishi=0 //定时一秒计数

uint crc=0,myaw=0

uint crc16(unsigned char *puchMsg, unsigned int usDataLen)

bit  yifasong=0

void Beginsend( uchar Me )

bit check_modbus()

void Open_dcf()

void Close_dcf()

void timer0()

void uart_init(void)

void delay(uint z)

void Read_adc()

void  Tosend()

/////////

/*************延时*****************/

void delay(uint z)

{

  uchar y

while(z--)

for(y=113y>0y--)

}

/************串口初始化*****************/

void uart_init(void)   interrupt 4    using 1

{

if(RI)

           {  

                  aq[receive_count]=SBUF

    RI=0

receive_count++

if(0==receive_count%8)

{

yifasong=0

receive_count=0

}

                       

                    RI=0

              }

}

/**************定时器0初始化**************/

void timer0()  interrupt 1    using 1

{

 TH0=0x4b

TL0=0x63

jishi++

if (0==jishi%10) {

 Halfsecond=1

aq[0]=0aq[1]=0aq[2]=0aq[3]=0aq[4]=0aq[5]=0aq[6]=0aq[7]=0receive_count=0

}

   

}  

void Read_adc()

{  

  ADC_rd=1

   ADC_wr=1

   _nop_()

    _nop_()

   _nop_()

   _nop_()

   myint=1

   P0=0xff       

ADC_wr=0

    _nop_()

   _nop_()

   _nop_()

   _nop_()

       ADC_wr=1                       

while( myint==1)   

      ADC_rd=0                   

     _nop_()

     _nop_()

     _nop_()

    _nop_()

    _nop_()

   

    Adc_value=P0                  //读出的数据赋与addate

    ADC_rd=1

}

void Open_dcf()

{

 Dcf_open=0   delay(1200)Dcf_open=1 Dcf_state=1

}

void Close_dcf()

{

 Dcf_close=0  delay(1200)Dcf_close=1Dcf_state=0

}

void Read_Pressure()  

{  

   Read_adc()  

if (Dcf_state)

   {

     if((Adc_value<Pressure_lowdata)|| (Adc_value>Pressure_updata))

         {

              delay(1200)

                    if((Adc_value<Pressure_lowdata)|| (Adc_value>Pressure_updata)) {   Close_dcf()}

           }

      else

          {                 }

    }

 

else

  {

    if((Adc_value>Pressure_lowdata)&&(Adc_value<Pressure_updata))

       {        delay(1200)

                    if((Adc_value>Pressure_lowdata)&&(Adc_value<Pressure_updata))   {  Open_dcf()}

  }

  else        

   }

}

void initialize()

{

TMOD=0x20

SCON=0x50//串口通讯方式1

TH1=0xfd//波特率9600

TL1=0xfd

TH0=0x4b

TL0=0x63

TI=0//发送中断标志位清零

RI=0//接收中断标志位清零

Mydress_set=1P_lowlimite=1P_uplimite=1xuantong=1

Mydress_set=0delay(20)addrset=1delay(20)addr=P0

delay(20)

addrset=0Mydress_set=1delay(200)P0=0xff

P_lowlimite=0delay(20)lowset=1delay(20)Pressure_lowdata=P0

delay(20)

lowset=0P_lowlimite=1P0=0xff           

 P_uplimite=0delay(20)upset=1Pressure_updata=P0delay(20)upset=0P_uplimite=1P0=0xff

 xuantong=0

}

void main(void)

{

IE=0x92

   TR0=1TR1=1

        // WDTRST=0x1E

           // WDTRST=0xE1//初始化看门狗

   

       initialize()

 

       Stor=0

for()  { // WDTRST=0x1E

            //WDTRST=0xE1//喂狗指令

 if (Halfsecond==1)  {

                    Halfsecond=0

                     Read_Pressure()

      }

      //够一秒开始转换

if(receive_count==0&&(yifasong==0))

              {   Stor=0 

  dr= check_modbus()

                       if (dr&&addr==aq[0])

                         {                     if(aq[1]==0x05)

                                                   

                                                            switch ( aq[3])

                                                              {

                                           case  0x00     :    

                                                               

                 if(!Dcf_state)      Open_dcf()

              Beginsend(0)           break

                                                             case  0x01     :                                                                

                                                             

                                                            if(Dcf_state)      Close_dcf()

                                                     

                                                          Beginsend(1)         

                                                               break

                             

                                                                 default  :            

                                          }

             

                                    else if(aq[1]==0x01)

                                                   

                      {

                 if(Dcf_state)

{   Beginsend(2)

                                                                           }

                        else  

                 

                                                                      {   Beginsend(3) 

                                                                            }

                          }

                                  else

                }

                     else

           

               }

       }    

}

void Beginsend(uchar Me )

{

uchar i

ES=0Stor=1

TI=0

mysend[0]=addr

switch(Me)

{

case 0:

       { for(i=1i<4i++)

              {

 

              mysend[i] =  Myreturnopen[i-1]

               }

i=0

}break

case 1:

{for(i=1i<4i++)

              {

 

              mysend[i] =   Myreturnclose[i-1]

               } i=0}break

case 2:

     {   for(i=1i<4i++)

              {

 

              mysend[i] = Myreturnstateopen[i-1]

               } i=0}break

case 3:

{for(i=1i<4i++)

              {

 

               mysend[i] =  Myreturnstateclose[i-1]

}i=0}break

default : }

myaw=crc16(mysend,4)

mysend[4] =myaw&0x00ff

mysend[5] =(myaw>>8)&0x00ff

for(i=0i<6i++)

      {

   

    SBUF=mysend[i]

   

while(TI!=1)

TI=0

       }

Stor=0

ES=1

yifasong=1

}

bit check_modbus()

{

uchar m,n  

 

crc=crc16(aq,6)

 m=crcn=crc>>8&0x00ff

if(aq[6]==m&&aq[7]==n)

return    1

else

return    0

}

uint crc16(uchar *puchMsg, uint usDataLen)

{

uchar uchCRCHi = 0xFF //* 高CRC字节初始化

uchar uchCRCLo = 0xFF //* 低CRC 字节初始化

unsigned long uIndex // CRC循环中的索引

while (usDataLen--) // 传输消息缓冲区

{

uIndex = uchCRCHi ^ *puchMsg++ // 计算CRC

uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]

uchCRCLo = auchCRCLo[uIndex]

}

return (uchCRCHi  | uchCRCLo<<8)

}

/***********************CRC校验*************************/

// CRC 高位字节值表

刚好我在弄crc校验。给你一段代码。我也是冲网上抄过来的。验证过了。

unsigned short crc16

static uchar code auchCRCHi[256] = {

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 低位字节值表

static uchar code auchCRCLo[256] = {

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

}

//CRC校验的函数

unsigned short CRC16(unsigned char *puchMsg, unsigned short usDataLen)

{

unsigned char uchCRCHi = 0xFF /* 高CRC字节初始化 */

unsigned char uchCRCLo = 0xFF /* 低CRC 字节初始化 */

unsigned uIndex /* CRC循环中的索引 */

while (usDataLen--) /* 传输消息缓冲区 */

{

uIndex = uchCRCHi ^ *puchMsg++ /* 计算CRC */

uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]

uchCRCLo = auchCRCLo[uIndex]

}

return (uchCRCHi <<8 | uchCRCLo)

}

调用方式:dd=CRC16(tmp,x);

远距离通信,不能正常接受,这是常有的事。

发送函数,必须多次发送,只有当收到正确的回信后,才停止发送,并返回正确传送标志。

发送函数,发送了一定的次数后,都没有收到回信,则返回错误的标志。

上层函数,根据标志,在屏幕上加以提示,指示 *** 作者进行下一步的 *** 作。

另外,在中断函数中,加上了长延时,delay(2000),也是个败笔,可能会错过很多应该接受的东西。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7826660.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存