首页 > 新闻中心 > > 正文

ATmega16的Modbus通讯技术

更新时间: 2006-02-23 15:36:25来源: 粤嵌教育浏览量:3036

基于ATmega16的Modbus通讯技术计算机、单片机(M16)收、发自如。

unsigned int cal_crc(unsigned char *ptr, unsigned int len) 
             {  
              unsigned int crc=0xffff;  
              unsigned char i;  
              while(len!=0)
           {  
            crc^=*ptr;
               for(i=0;i<8;i++)
            {  
                if((crc&0x0001)==0) crc=crc>>1;
             else 
            {
              crc=crc>>1;
              crc^=0xa001; 
            }                    
               } 
            len-=1;
            ptr++; 
              }  
              return crc;
             }  
          
void fenli(unsigned int data,unsigned int data1)
     {
     send_data[data1]=(unsigned char)(data);
     send_data[data1+1]=(unsigned char)(data>>8);
    }

unsigned int zhuhe(unsigned char data1,unsigned char data)
    {
    unsigned int t;
    t=data1;
    t=(t<<8)+data;
    return t;
   }
   
void send_run(void)
    {
    if(send_sp>num_send-1)
    {
     send_sp=0;
     flag_send=0;
    }
    else
    {
     UDR=send_data[send_sp];
     send_sp++;   
    }
    num_stop=0;
   }
   
void error(unsigned char data)
     {
     unsigned char add;
     num_send=5;
     send_data[1]=0x11;
     send_data[2]=data;
     add=cal_crc(send_data,3);
     fenli(add,3);
    }
    
void data_act(void)
     {
     unsigned int add,i,n;
     send_data[0]=address;
     add=zhuhe(recieve_data[2],recieve_data[3]);
     add=add*2-2; /*µØÖ·*/
     if(add>49) error(2);
     else
     {
      if(recieve_data[1]==3)
      {
      n=zhuhe(recieve_data[4],recieve_data[5]); /*³¤¶È*/   
      num_send=6+n;
      send_data[1]=recieve_data[1];  /*¹¦ÄÜ*/
      send_data[2]=recieve_data[4];
      send_data[3]=recieve_data[5];  /*³¤¶È*/
      for(i=0;i<n;i++)
      send_data[i+4]=variable_data[i+add];
      n=4+n;
      i=cal_crc(send_data,n);
      fenli(i,n);
     }
     else if(recieve_data[1]==6)
     {      
      num_send=num_recieve;
      for(i=1;i<num_recieve;i++)
      send_data[1]=recieve_data[1];   
     }
     else error(1);
     }
    }
    
unsigned char crc_recieve(unsigned char data)
       {
       unsigned int crc0,crc1;
      crc0=cal_crc(recieve_data,num_recieve);
      crc1=zhuhe(recieve_data[data-1],recieve_data[data-2]);
      if(crc0=crc1) return 1;
      else return 0;
      }
   
    
void time1compatt(void)                  
    {   
     unsigned char flag;
     if(flag_send==2) send_run();
     num_stop+=1;
     if(num_stop>3)
     {         
      if(flag_send==1)
      { 
       flag=crc_recieve(num_recieve);
      if(flag==1)
      {
       data_act();
       flag_send=2;
       num_recieve=0;
      }
      }
      num_stop=0;                 
     }
    }
    
#pragma interrupt_handler usrt_resieve:12    
void usrt_resieve(void)                  
    {   
     recieve_data[num_recieve]=UDR;
     num_recieve+=1;
     num_stop=0;
     flag_send=1;
    }

 


 

     单片机与PC机通讯调试步骤: 
     1:确定PC机通讯没问题,方法:把PC机串口的数据发送脚与数据接收脚连在一起,看接收的数据是不是发送的数据
     2:确认接线的正确性
     3:PC机与单片机双方协议一定

     我建议你:一不一步来
     1:先发送一个字节数据,看对不对
     2:在发送一串数据,看对不对
     3:你发送,对方应答,你再接收,看对不对
     4:才做校验。


免费预约试听课