⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus.c

📁 MODBUS驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[148]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[143]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[138]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[133]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[128]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[123]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   if(uart1_aa[118]==0x31) alert_value_mid=alert_value_mid+1;
   alert_value_mid=alert_value_mid<<1;
   }
//CRC校验子函数,入口:数据指针+数据段长度
unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen)
   {
    unsigned char uchCRCHi = 0xFF ; /* 高CRC初始化*/
    unsigned char uchCRCLo = 0xFF ; /* 低CRC初始化*/
    unsigned uIndex ;  /* 用来查表 */
    
    while (usDataLen--) /* 整个数据缓冲区,不带数据的CRC两个字节 */
    {
     uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
     uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
     uchCRCLo = auchCRCLo[uIndex] ;
    }
    return (uchCRCHi << 8 | uchCRCLo) ;
}
//RTU格式化输出
//入口:本地址缓冲区+原来数据地址缓冲区+数据段长度
void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth)
{
    unsigned short  crc_tmp;
    crc_tmp = crc(src_buf, lenth);   //原地址加数据段做CRC计算
     
    *(src_buf+lenth) = crc_tmp >> 8 ;  //把CRC高位防置在随后的地址
    *(src_buf+lenth+1) = crc_tmp & 0xff;  //放CRC低位
    lenth++;                             //把数据指针指向最后
    lenth++;
 
    while ( lenth--)                   //搬动整个缓冲区到发送缓冲区  
    {
       *dst_buf = *src_buf;
       dst_buf++;
       src_buf++;	
     }
}
//读继电器状态响应   
//读的格式为:板本机地址    读功能码    读的高位地址   读的低位地址    字节长度高    字节长度低   CRC校验,共8个字节
//响应格式为:本机地址      功能码      有效数据长度   开关位8位数据     CRC校验码
int rtu_read_coil_status ( unsigned char board_adr,int start_address,int lenth) 
   {
    unsigned char tmp[100], tmp_lenth;
    unsigned int temp_start;
    unsigned char temp1,temp2;
    
    tmp_lenth = lenth;
    temp_start = start_address;
    
    if(tmp_lenth<=8)  
        {
         tmp[2]=1;
         }
       else 
         {
          tmp[2]=2;
          }
          
    alert_value_mid=alert_value_mid>>temp_start; 
         
    tmp[0] = board_adr;
    tmp[1] = READ_COIL;
    temp1= alert_value_mid/256;
    temp2= alert_value_mid;
    
    if(tmp[2]==1)
         {
         tmp[3] = temp2;         //给出实际的数据1个字节,可代表8个继电器     
         tmp_lenth = 4;
         } 
     else 
         {
         tmp[3] = temp1;         //给出实际的数据1个字节,可代表8个继电器     
         tmp[4] = temp2;
         tmp_lenth = 5;
         }
    
    construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
    return (tmp_lenth+2);
    }
//读取数据输入状态状态
int rtu_read_input_status ( unsigned char board_adr,int start_address,int lenth) 
   {
    unsigned char tmp[100], tmp_lenth;
    unsigned int temp_start;
    unsigned char temp1,temp2;
    
    tmp_lenth = lenth;
    temp_start = start_address;
    
    if(tmp_lenth<=8)  
        {
         tmp[2]=1;
         }
       else 
         {
          tmp[2]=2;
          }
          
    alert_value_mid=alert_value_mid>>temp_start; 
         
    tmp[0] = board_adr;
    tmp[1] = READ_COIL;
    temp1= alert_value_mid/256;
    temp2= alert_value_mid;
    
    if(tmp[2]==1)
         {
         tmp[3] = temp2;         //给出实际的数据1个字节,可代表8个继电器     
         tmp_lenth = 4;
         } 
     else 
         {
         tmp[3] = temp1;         //给出实际的数据1个字节,可代表8个继电器     
         tmp[4] = temp2;
         tmp_lenth = 5;
         }
    
    construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
    return (tmp_lenth+2);
    }
//读取采样保持器
//读格式:本机地址+功能码+读高位地址+读地位地址+数据段长度高位+数据段长度低位+CRC校验码
//返回格式:本机地址+功能码+有效数据长度 +数据1+数据2+++++++
int rtu_read_hldreg ( unsigned char board_adr,int start_address,int lenth) 
{
    unsigned char tmp[100], tmp_lenth;
    unsigned char i,j,k;
    unsigned int temp;
    
    tmp_lenth=lenth;
    
    tmp[0] = board_adr;
    tmp[1] = READ_HLD_REG;
    tmp[2] = tmp_lenth;
    
    j=start_address;
    k=2;
    for(i=j;i<tmp_lenth;i++)
      {
       temp=uart1_value[i];
       k++;
       tmp[k] = temp >> 8 ;
       k++;
       tmp[k] = uart1_value[i];
       }
    tmp_lenth = k+1;
    construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
    return (tmp_lenth+2);
}
//读取采样保持器
//读格式:本机地址+功能码+读高位地址+读地位地址+数据段长度高位+数据段长度低位+CRC校验码
//返回格式:本机地址+功能码++有效数据长度+数据1+数据2+++++++
int rtu_read_anloginput( unsigned char board_adr,int start_address,int lenth) 
{
    unsigned char tmp[100], tmp_lenth;
    unsigned char i,j,k;
    unsigned int temp;
    
    tmp_lenth=lenth;
    
    tmp[0] = board_adr;
    tmp[1] = READ_HLD_REG;
    tmp[2] = tmp_lenth;
    
    j=start_address;
    k=2;
    for(i=j;i<tmp_lenth;i++)
      {
       temp=uart1_value[i];
       k++;
       tmp[k] = temp >> 8 ;
       k++;
       tmp[k] = uart1_value[i];
       }
    tmp_lenth = k+1;
    construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
    return (tmp_lenth+2);
}
//RTU数据分析
//入口,接收缓冲区的大小,长度
int rtu_data_anlys(unsigned char fr_lenth)
   {
    unsigned short crc_result, crc_tmp;
    unsigned char tmp1;
    unsigned int tmp2,tmp3,tmp4;
    unsigned char *source_p;
    unsigned char temp;
    
    source_p = uart0_bb;
    temp = *source_p;
    if(board_address!=temp) return;
    
    crc_tmp = *(source_p + rtu_number_long-2);                // 由接收缓冲区计算出 crc  第一字节   
    crc_tmp = crc_tmp * 256 + *( source_p+rtu_number_long-1); // 得到实际  CRC 值
    crc_result = crc(source_p, fr_lenth-2);            // 计算 CRC 值
    
   
    if ( crc_tmp != crc_result ) // 对比 CRC 校验正确
      {
       return -1;
       }
       
    source_p=uart1_aa;
    tmp1=*source_p;
    tmp3=(*(source_p+2)*256)+*(source_p+3);
    tmp4=(*(source_p+4)*256)+*(source_p+5);
    switch ( *(source_p+1) ) // 功能码
        {
        case READ_COIL:                   /*读取继电器状态 */
            tmp2=rtu_read_coil_status (tmp1,tmp3,tmp4);
            rtu_out_active(tmp2);	
            break;

        case READ_DI: /*读取开关量输入*/
            tmp2=rtu_read_input_status(tmp1,tmp3,tmp4);
            rtu_out_active(tmp2);	
            break;

        case READ_HLD_REG:  /*读取保持寄存器*/
            tmp2=rtu_read_hldreg(tmp1,tmp3,tmp4);
            rtu_out_active(tmp2);	
            break ;

        case READ_AI:      /*读取模拟量输入*/
            tmp2=rtu_read_anloginput (tmp1,tmp3,tmp4);
            rtu_out_active(tmp2);	
            break;

        case PROTOCOL_EXCEPTION:
        return -1*PROTOCOL_ERR;   
       
        default:
        return -1*PROTOCOL_ERR;
       }
    return 0;
}
void rtu_out_active(unsigned char number)	
     {
      unsigned char i;
      P1OUT  = 0;                        // P1.0 与自身异或
      for(i=0;i<number;i++)
         {
         TXBUF0 = com_out_aa[i];
         while((UTCTL0&0x01)==0);
         }
      P1OUT  = 0xff;                        // P1.0 与自身异或
     }
void timer_Init(void)
     {
      WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
      BCSCTL1 |= BIT6;        //XTS=1 高速模式
      TACTL = TASSEL0 + TACLR;              // SMCLK, clear TAR
      CCTL0 = CCIE;                         // CCR0 interrupt enabled
      CCR0 = modbus_delay;
      P1DIR |= 0xff;                        // P1.0 output
      TACTL |= MC0;                         // Start Timer_A in continuous mode
      _EINT();                              // Enable interrupts
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -