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

📄 com.c

📁 本代码以AVR单片机为主控制器
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************* (C) 2005  485表项目 ****************************************

   项     目: 485表项目
   编译环境 : IARAVR 编译器 4.12A

   模块名称 : com.c
   版    本 : V 1.0

   建立时间 : 2008-5-3 21:51

   修改时间 : 2008-5-3 16:47

   作    者 : 郝瑜云  

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

   功能描述 : 645通讯子程序
   程序结构 :                   Protlcol_DLT645_New()   645规约处理程序
                                        |
        ________________________________|_______________________________
       |                     ?                     ?                    |
DLT645Explain(COM1)     Com1Reset()           Com2Reset()       DLT645Explain(COM2)
       |                 串口复位               串口复位                 |
  CommDisplay()                                                    CommDisplay()
 串口1处理并指示                                                  串口2处理并指示

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

   修改 :   2005-11-29: 启用用新的串口通讯程序,查询式
            2005-11-29: 表地址编程只用密码保护
            2005-12-18: 使用结构指针操作通讯变量,有效降低RAM使用量,但ROM增加60字节

**************************************************************************************************/
#include    "Include.h"

/*
*************************************************************************************************
    函数 : void Protocol_New(void)
    功能 : 645 通讯串口处理程序

    输入 : 无
*************************************************************************************************
*/
void Protlcol_New(void)
{
    INT8U   all_length;
    //-------------------------------------------------------------------------
    if(Com1Var.CommEnd == 0xAA)                 // 串口1通讯处理
    {
        Com1Var.CommEnd = 0;
        all_length = Comm_Data_Check_DLT645(Com1Var.RxBuff);
        if(all_length>0)
        {
        //Com1Var.TxConst = 0;
            if(DLT645Explain(all_length))       //通讯数据处理
            {
              goto COM1_SEND;
            }
        }       
        Com1Reset();
    }
    if(CHKBIT(Com1Bits,ComRST))
    {
        Com1Reset();
    }
    //-------------------------------------------------------------------------
   // #ifdef  _COM2_HW_EN                         // 红外允许定义
    if(Com2Var.CommEnd == 0xAA)                 // 串口2通讯处理
    {
        Com2Var.CommEnd = 0;
        all_length = Comm_Data_Check_DLT645(Com2Var.RxBuff);
       
        if(all_length>0)
        {  
        
          //Com2Var.TxConst = 0;
          if(DLT645Explain(all_length))             // 通讯数据处理
            {
                goto COM2_SEND;
             }
        }
        Com2Reset();
    }
    if(CHKBIT(Com2Bits,ComRST))
    {
        Com2Reset();
    }
   // #endif
    //-------------------------------------------------------------------------
    return;
    COM1_SEND:
    CopyRam(ComVar.TxAllBuff,Com1Var.TxBuff,ComVar.TxConst);    // 传递发送数据
    Com1Var.TxConst = ComVar.TxConst;
    Com1Var.ComInitTimer = 0;       // 串口1初始化定时器清零
    Com1Var.TxPoint   = 0;          // 置发送起始指针
    SETBIT(Com1Bits,EnComTx);       // 允许发送数据
    SETBIT(ComBits,EnStatus);       // 通讯指示 
    //------------------------------// 发送返回数据
    Com1Var.ComTxStep    = 0;       // 发送节拍清零
    return;
    //-------------------------------------------------------------------------
 //   #ifdef  _COM2_HW_EN
    COM2_SEND:
    CopyRam(ComVar.TxAllBuff,Com2Var.TxBuff,ComVar.TxConst);
    Com2Var.TxConst   = ComVar.TxConst;  
    Com2Var.ComInitTimer = 0;       // 串口2初始化定时器清零
    TCCR2A = 0x00;
 //   CommDisplay();                // 通讯指示 红外通讯亮背光
    //------------------------------// 发送返回数据
    Com2Var.TxPoint        = 0;     // 置起始指针
    SETBIT(ComBits,EnStatus);       // 通讯指示 
    Com2Var.ComTxStep    = 0;       // 发送节拍清零
    //-----------------------------------------------------------------
    Com2Var.OverTimer = 0;          // 清零超时定时器
    SETBIT(Com2Bits,EnComTx);       // 允许发送数据// 发送返回数据
    //#endif
    //-------------------------------------------------------------------------
}


/*
***************************************************************************************************
    函  数 : void Comm_Data_Check_DLT645(void)
    功  能 : 串口接收数据帧检查函数

    输  入 : 无
***************************************************************************************************
*/
INT8U Comm_Data_Check_DLT645(INT8U *buff)
{
    INT8U   i,datalength,*buff_bak;
    
    buff_bak = buff;                                    // 执行645规约检测  检测有无帧头字节
    for(i=0;i<6;i++)
    {
        if(*buff == 0x68)
        {
            goto NEXT1_STEP;                            // i 即为数据起始地址
        }
        buff++;
    }
    return(0);
    NEXT1_STEP:                                         // 检测数据长度是否合法
  //  CLRBIT(PORTB,IO_ALARM );
    buff += _COM_DATA_LENGTH;
    datalength = *buff;
    buff = buff_bak + i + datalength + 11;
    if( datalength> 36) return(0);                      // 数据长度判断
    if( *buff == 0x16)                                  // 检测有无帧尾标志
    {
        datalength = datalength+12;                     // 计算数据总长度
        buff_bak += i;
        CopyRam(buff_bak,ComVar.RxBuff,datalength);     // 传递接收数据
        return(datalength);
    }
    return(0);
}
//*****************************************************************************
//       函数 : INT8U DLT645Explain(pointer)                                  *
//       功能 : DLT645通讯解释处理程序                                        *
//                                                                            *
//       输入 : rxcnt:串口缓冲区数据个数                                      *
//*****************************************************************************
INT8U DLT645Explain(INT8U rxcnt)
//ComVarDef *pointer;                 // 指向ComVarDef类型的指针
{
    INT8U   datalength;
    INT16U  cmd;
    INT16U  eep_address;
    INT8U   i,erro,consttmp[7];
   // float   temp;
    //-------------------------------------------------------------------------
    rxcnt -= 2;                      // 检测数据有效性
    if(ComVar.RxBuff[rxcnt]!=(DataAddCS(ComVar.RxBuff,rxcnt)))//检测累加和
    {
        return(0);
    }
    //-------------------------------------------------------------------------                      
    erro = 0;                                       // 测试表地址
    for(i=0;i<7;i++)                                            // 执行645规约检测  检测有无帧头字节
    {
        if(ComVar.RxBuff[i]!=0x99)  {erro = 0x55;}  // 判断是否为广播地址
    }
     if(erro == 0)   
    {
        goto MTR_ADDRESS_OK;
    }
    erro = 0;                                     // 判断真实表地址
   CopyEEPToRam(ADDRESS_C032E,EEPVar.I2cBuff+1,6); // 读入6字节表地址
     for(i=1;i<7;i++)                                // 如果表地址空位补A才能使用缩位
    {
        if((ComVar.RxBuff[i]!=0xAA)&(ComVar.RxBuff[i]!=0xBB))
        {
            if(ComVar.RxBuff[i]!=EEPVar.I2cBuff[i])
            {
                return(0);
            }
        }
    }
    //-------------------------------------------------------------------------
    MTR_ADDRESS_OK:
    RamFill(ComVar.TxAllBuff,0,40);                     // 发送缓冲区清零,使用缓冲区注意,已经清零了
    ComVar.TxAllBuff[0] = 0x68;                         // 填充发送帧头
    ComVar.TxAllBuff[7] = 0x68;
    CopyEEPToRam(ADDRESS_C032E,ComVar.TxAllBuff+1,6);   // 将表地址拷入发送缓冲                                         // 检测数据长度是否合法
    datalength = ComVar.RxBuff[9];                      // 取出数据长度
    DataDec33(ComVar.RxBuff+10,datalength);             // 数据-33处理
    CopyRam(ComVar.RxBuff+10,(INT8U *)&cmd,2);          // 取出命令码合并为INT
    eep_address = 0;                                    // 清除RAM和EEP操作数地址
    //---------------------------------------------------------
    //*********************************************************************
    switch(ComVar.RxBuff[_COM_CTR_CODE])                // 通讯模式    
        {
            //*****************************************************************
            case 0x01:                                          // 判断读模式
               CopyRam(ComVar.RxBuff+10,ComVar.TxAllBuff+10,2);   // 传递命令码
               ComVar.TxAllBuff[_COM_CTR_CODE] = 0x81;        // 置控制码:正常应答,无后续帧
                ComVar.TxConst = 8;                         // 重置发送数据个数
                //bcd_enable = 1;                                 // BCD 转换允许,由于大多数数据需HEX到BCD转换
                switch(cmd)
                {
                    case 0x5501:    // 读命令 5501  软件标识号
                       datalength  = 6;
                       ComVar.TxAllBuff[12]= _VERSION;
                    break;
                    case 0x9010:    // 读命令 9010  当前有功正向总电量
                        datalength  = 4;
                        goto BUILD_901F;
                   case 0x901F:    // 读命令 901F  当前有功正向总电量集合
                        datalength  = 20;
                        BUILD_901F:
                        BuildPower();
                        CopyRam(PowerVar.ActInPow,ComVar.TxAllBuff+12,4);
                        HEXToBCD8(ComVar.TxAllBuff+12,4);   // 将数据转成BCD码
                        CopyRam(ComVar.TxAllBuff+12,ComVar.TxAllBuff+24,4); // 复制总电量至平电量:安徽中天要求
                    break;
                    case 0xC030:    // 读命令 C030  表常数
                        //eep_address = ADDRESS_C030E;
                      i = ((_PulseConst/10)<<4)+(_PulseConst%10); 
                      ComVar.TxAllBuff[12]=0x00;
                      ComVar.TxAllBuff[13]=i;
                      ComVar.TxAllBuff[14]=0;
                      datalength  = 3;
                       // bcd_enable  = 0;         // 清零BCD转换标志
                    break;
                    case 0xC032:    // 读命令 C032  表地址
                        eep_address = ADDRESS_C032E;
                        datalength  = 6;
                       // bcd_enable  = 0;         // 清零BCD转换标志
                    break;
                   case 0xD400:                            //读命令 D400 显示域
                    eep_address = ADDRESS_D400E;
                    datalength  = 22;
                   break; 
                   case 0xC113:                            //循显时间
                     eep_address = ADDRESS_C113E;
                     datalength  = 1;
                   break;     
		   case 0xD406:                            // 读命令 D406  产品条形码号
                    eep_address = ADDRESS_D406E;
                    datalength  = 60;
                   break;
                   case 0xC098:                            // 读命令 C098  误差分频数
                     mIICReadPage( consttmp,0x06, 0xA0, 0x00);
                     CopyRam(consttmp,ComVar.TxAllBuff+12,6);
                     //eep_address = ADDRESS_C098E;
                    datalength  = 6;
                   break;
                   default:                                        // 发送错误帧: 代码 01 :非法数据
                        erro = 0x34;
                        goto SEND_645_ERRO;                         // 非法数据
                }
                //-------------------------------------------------------------
                if(eep_address!=0)                                  // 调入相应数据
                {
                    CopyEEPToRam(eep_address,ComVar.TxAllBuff+12,datalength);
                }
                //-------------------------------------------------------------
                ComVar.TxAllBuff[_COM_DATA_LENGTH] = datalength+2;  // 置数据长度:n字节
               // if(bcd_enable)
               // {
               //     HEXToBCD8((*pointer).Buff+12,datalength);       // 将数据转成BCD码
               // }
                DataAdd33(ComVar.TxAllBuff+10,(datalength+2));
                ComVar.TxConst = datalength+14;
                ComVar.TxAllBuff[ComVar.TxConst-2] = DataAddCS(ComVar.TxAllBuff,(datalength+12));   // 计算校验和
                ComVar.TxAllBuff[ComVar.TxConst-1] = 0x16;
                break;
            //*****************************************************************
            case 0x04:                                              // 判断编程模式
                if(PasswordCheck(12))
                {  
                    if((ComVar.ProgEn!=0xAA)&(ComVar.AdjustEn!=0xAA))       // 检测编程允许标志
                    {
                    goto INVALID_DATA;
                    }      
                    EEPVar.WriteProtectAA = 0xAA;
             
             //---------------------------------------
             switch(cmd)
             {
                  case 0xD400:
                      CopyRamToEEP(ADDRESS_D400E,ComVar.RxBuff+16,22);
                      ReadDispConst();         //读出显示域   
                  break;    
                  case 0xC113:                 //修改循显时间
                      CopyRamToEEP(ADDRESS_C113E,ComVar.RxBuff+16,1); 
                      ReadDispConst();         //读出循显时间
                  break;
                // case 0xC030:                 // 写命令 C030  表常数
                //        CopyRamToEEP(ADDRESS_C030E,ComVar.RxBuff+16,3);
                //        ReadPulseConst();      // 读出脉冲常数
                //  break;
                  case 0xC032:                 // 写命令 C032  电表号
                  case 0x230C:
                        CopyRamToEEP(ADDRESS_C032E,ComVar.RxBuff+16,6);
                        CopyRamToEEP(ADDRESS_230BE,ComVar.RxBuff+16,4);   //更新产品条形码中的资产号
                        CopyRam(ComVar.RxBuff+16,ComVar.TxAllBuff+1,6);
                  break;
                  case 0x230A:                //产品条形码1(低30字节)

⌨️ 快捷键说明

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