打印
[STM32C0]

【STM32C092RC 测评】解码DLT645-2007多功能三相电表

[复制链接]
73|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 龙鳞铁碎牙 于 2025-5-20 11:25 编辑

#有奖活动# #技术资源# #申请开发板# #每日话题# #申请原创#         大家平时在家用电时,每家每户都会接入一个电表,这个东西记录了每个家庭使用的电量读数,在农村每月或者每季度就有专门的人来村里催收电费,然而在城市里面,每家都有电表卡,当出现欠费后,就需要人员去充值缴费后,才能正常用电.
        这个电表说白了就是一个计量电能读数的一个装置,内部原理非常的简单,就是一个电表协议的收发,国内的电表协议非常的专一,一直以来都是DLT645协议,
这个协议分为两个版本,DLT645-1997和DLT645-2007,DLT645是一种应用在电表上的专用协议,你们平时家里使用的电能表就用的是DLT645协议,该协议分为两个版本,DLT645-1997和DLT645-2007,2007是1997的更新升级版,接收数据帧是一样的,只是发送数据帧格式上DID有点区别。
      具体区别如下:
1997的标识符编码是2位

2007的标识符编码是4位

发送时配合各自的控制码进行区别发送,接收是一模一样的!!! 这里我就只讲解DLT645-2007版本了,先看数据帧格式
1。串口数据格式采用11位格式,如下图

2。协议格式


以68H开头作为起始帧
紧接着是6位地址码A0~A5
地址域由 6 个字节构成,每字节 2 位 BCD 码,地址长度可达12位十进制数。每块表具有唯一的
通信地址,且与物理层信道无关。当使用的地址码长度不足 6 字节时,高位用“0”补足。
通信地址999999999999H为广播地址,只针对特殊命令有效,如广播校时和广播冻结等。广播命令
不要求从站应答。
地址域支持缩位寻址,即从若干低位起,剩余高位补AAH作为通配符进行读表操作,从站应答帧的
地址域返回实际通信地址。
地址域传输时低字节在前,高字节在后。



接着是数据长度L
L 为数据域的字节数。读数据时 L≤200,写数据时 L≤50,L=0 表示无数据域。
接着是数据DATA
数据域包括数据标识、密码、操作者代码、数据、帧序号等,其结构随控制码的功能而改变。传输时发送方按字节进行加 33H 处理,接收方按字节进行减 33H 处理。
接着是校验码CS。从第一个帧起始符开始到校验码之前的所有各字节的模 256 的和,即各字节二进制算术和,不计超过 256 的溢出值。
最后是结束码,固定为16H


标识一帧信息的结束,其值为 16H=00010110B。 注意的是,在主站发送帧信息之前,先发送4个字节FEH,以唤醒接收方。也就是先要接收到4个0XFE后,才能收到0x68H,然后接收后面的数据帧,直到16H完成一帧报文的接收。

通信波特率主要支持下面几个值:
不能弄错
数据标识

3。主站请求帧,控制码是01

从站正常应答 ,控制码是91

以上就是DLT645-2007的协议格式:下面我们开始进行项目搭建
打开cubumx
这个是板上的USB串口,USART2,PA2,PA3

我还需要一个串口用来打印调试,这里我试用USART3, PC10,PC11

就是这两个串口就可以了,下面开始解析DLT645协议
DLT645的数据格式如下:



void SerialInput(uint8_t RecData)
{  
   if(MSG_SERIAL.RecOver) return; // 停止接收?                        
   if((RecData==SOI)&&(MSG_SERIAL.RecCount==0))         
   {  MSG_SERIAL.SleepTime=0;
      MSG_SERIAL.SleepFlag=0;   
      MSG_SERIAL.RecBuf[0]=SOI;MSG_SERIAL.RecCount=1; // 启动接收
   }  
   else if((MSG_SERIAL.RecBuf[0]==SOI)&&(MSG_SERIAL.RecCount<REC_MAX)) // 如果已经接收到起始位
   {MSG_SERIAL.RecBuf[MSG_SERIAL.RecCount++]=RecData;} // 将数据添加到缓存区
   else {MSG_SERIAL.RecCount=0;}      
   if((RecData==EOI)&&(MSG_SERIAL.RecCount==(MSG_SERIAL.RecBuf[9]+12)))
   {
     MSG_SERIAL.RecOver=1;
     MSG_SERIAL.RecTimer=0;          // 清计时器
   } //  接收完成           
}

#define  REC_MAX   150    // 定义接收缓存区的大小
#define  SEND_MAX  150    // 定义发送缓存区的大小

#define  SOI       0x68       // 帧起始符
#define  ADR       0x68       // 帧起始符
#define  EOI       0x16       // 结束符

#define  SERIAL_TIME_ISR   5  // 定时器间隔 ms
#define  TIME_OUT   500       // 接收超时时间 ms
#define  TIME_SLEEP 10000     // 休眠超时时间

typedef struct
{
  uint8_t  RecBuf[REC_MAX];    // 接收缓存区
  uint8_t  RecCount;           // 接收的字节数
  uint8_t  SendBuf[REC_MAX];   // 发送缓存区
  uint8_t  SendCount;          // 要发送的字节数
  uint8_t  RecOver;            // 接收完成标志
  uint16_t RecTimer;           // 接收计时器
  uint16_t SleepTime;          // 休眠计时
  uint8_t  SleepFlag;          // 通讯休眠标志
} MSG;


校验和
// 校验
static uint8_t ChkSum(uint8_t *pData,uint8_t count)
{
   uint8_t chkSum=0;
   while(count--)
   {
      chkSum +=(*pData++);
   }
   return (chkSum);
}

// 接收数据校验
static uint8_t RcvChk(void)
{
  if(MSG_SERIAL.RecBuf[MSG_SERIAL.RecBuf[9]+10]==ChkSum(&MSG_SERIAL.RecBuf[0],MSG_SERIAL.RecBuf[9]+10))
  {return 1;}
  else
  {return 0;}  
}

// 清接收缓存区
static void ClrRcvBuf(void)
{        
        memset(MSG_SERIAL.RecBuf, 0, sizeof(MSG_SERIAL.RecBuf));
    MSG_SERIAL.RecCount=0; // 清接收数据计数器
        MSG_SERIAL.RecTimer=0; // 清计时器
        MSG_SERIAL.RecOver=0;  // 允许接
}
// 接收超时处理
static void SerialTimeOut(void)
{
   if(MSG_SERIAL.RecTimer>(TIME_OUT/SERIAL_TIME_ISR)) // 如果接收超时
   {
      MSG_SERIAL.RecCount=0;         // 清接收数据计数器
      MSG_SERIAL.RecTimer=0;         // 清计时器
          MSG_SERIAL.RecOver=0;          // 允许接
   }
   if(MSG_SERIAL.SleepFlag) return;
   if(MSG_SERIAL.SleepTime>(TIME_SLEEP/SERIAL_TIME_ISR))
   {
                 MSG_SERIAL.SleepFlag=1;
   }
}


// 由定时器调用
void SerialTimer(void)
{
        if(MSG_SERIAL.RecCount!=0)
    {
       MSG_SERIAL.RecTimer++;
    }
    if(MSG_SERIAL.RecCount==0)
    {
       MSG_SERIAL.SleepTime++;
    }
}

// 数据解码
void SerialDecode(void)
{
   SerialTimeOut();
   if(!MSG_SERIAL.RecOver) {return;} // 接收没有完成
   if(MSG_SERIAL.RecBuf[7]!=ADR) {return;} // 如果帧起始符错误
   if(!RcvChk()) {return;} // 如果校验错误
   SerialDecoding(&MSG_SERIAL.RecBuf[8]); //   
   ClrRcvBuf();          // 清缓存区  
}

// 串口发送数据
void SerialOutput(void)
{
   static uint8_t mSendCount=0;
   if(MSG_SERIAL.SendCount)
   {
          MSG_SERIAL.SendCount--;
      //UART_DR=MSG_SERIAL.SendBuf[mSendCount++]; // 发送数据  
   }
   else{mSendCount=0;TXIE_DIS;} // 停止发送                  
}

// 启动串口发送数据
void SerialStartSend(uint8_t *pData)
{
   uint8_t i;
   *(pData+*(pData+3)+3)=EOI;
   *(pData+*(pData+3)+2)=ChkSum(pData+3,*(pData+3));
   for(i=0;i<(*(pData+3)+4);i++){MSG_SERIAL.SendBuf=*(pData+i);}
   MSG_SERIAL.SendCount=*(pData+3)+4;
   //IFS0bits.U1TXIF=1;   
   TXIE_EN; // 使能串口发送中断
}

// 数据提取
static void SerialDecoding(uint8_t *pData)
{
#if 0
          printf(" LEN : %d\r\n",MSG_SERIAL.RecBuf[9]+12);
          for(uint8_t i = 0; i < MSG_SERIAL.RecBuf[9]+12; i++)
          printf("RecBuf[%02d] = 0x%02x\r\n",i,MSG_SERIAL.RecBuf);
          printf("\r\n\r\n");
#endif


   int msg_len;
   int type;
   int port;
   const uint8_t *msg;
   MSG *tx;


   uint8_t address[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
   uint8_t nx[4] = {0x33, 0x35, 0x44, 0x44};

   port = 0;
   type = *pData;
   tx = &MSG_SERIAL.SendBuf;
   msg_len = MSG_SERIAL.RecBuf[9];
   msg = &MSG_SERIAL.RecBuf[10];

   //PTenergy = 11;
   Read_PTenergy(nx);

     for(int i=0;i<4;i++)
        {
          nx += 0x33;
        }


   switch(type)
   {
        case 0x11:  // 电池电压(0x02),电流(0x03),电量(0x04),数据请求            
                switch (msg_len)
                {
                case 4:
                    printf("Type 0x%02X - len %d\n", type, msg_len);
                    dlt645_log_di(msg);
                    printf("\n");
                                dlt645_send_msg_91(port, tx, address, msg, nx, 4);
                                //dlt645_send_msg_91(port, tx, address, msg, nV, 2);
                                //dlt645_send_msg_91(port, tx, address, msg, nXX, 3);
                    break;
                case 5:
                    printf("Type 0x%02X - len %d\n", type, msg_len);
                    dlt645_log_di(msg);
                    printf(", N = 0x%02X\n");
                    break;
                case 10:
                    printf("Type 0x%02X - len %d\n", type, msg_len);
                    dlt645_log_di(msg);
                    printf(", N = 0x%02X, ", msg[4]);
                    dlt645_log_date(&msg[5], 5);
                    printf("\n");
                    break;
                }
                break;      
        case 0xff:  // 内部用命令
                         switch(*(pData+1))
             {
                case 0x00:  // 读取产品序列号
                                           break;
                case 0x01:  // 写入产品序列号
                       break;                     
                case 0x02:  // 电压数据电流数据  容量数据 请求
                                                                                                                                                                                                                           
                                           break;
                case 0x03:        //  电流数据请求                                                                        
                                            
                       break;
                                case 0x04:  //  电量数据请求
                                          
                                           break;
                                case 0x05:  //  状态数据请求
                      // SerialSendStates(0xff,0x05); // 发送状态数据
                                             break;
                case 0x06:  // 写入配置数据

                case 0x07:  // 配置数据请求

                       break;
                case 0x0f:  //  校准
                                                switch(*(pData+2))
                        {
                            case 0:  // 电压数据请求
                                                                    
                                                                        break;
                                                        case 1:  // 电压校准数据请求

                                                                    break;                     
                                                        case 2:  // 电压校准数据写入

                                                                    break;                    
                                                        case 3:  // 电流常量校准
                                                               
                                                                    break;
                                                        case 4:  // 电流放大倍数请求
                                                                                 
                                                                          break;  // 发送电流放大倍数
                                                        case 5:  // 电流放大倍数写入                 

                                                                         break;
                            case 6:  // 电量数据写入
                                                                                                                                
                                     break;                                                                                                               
                            default: break;
                                }
                            break;
                default: break;
             }
             break;
        default: break;
   }
}


/********************************** 具体功能函数 ***************************/

static __inline__ void dlt645_insert_address(uint8_t msg[], const uint8_t address[6])
{
    int i;

    for (i = 0;  i < 6;  i++)
        msg = address;
}

static __inline__ void dlt645_insert_di(uint8_t msg[], const uint8_t di[4])
{
    int i;

    for (i = 0;  i < 4;  i++)
        msg = di;
}

static __inline__ void dlt645_insert_date(uint8_t msg[], const rtc_t *date, int n)
{
    int i;

    i = 0;
    if (n == 6)
        msg[i++] = date->second;
    msg[i++] = date->minute;
    msg[i++] = date->hour;
    msg[i++] = date->day;
    msg[i++] = date->month;
    if (n > 4)
        msg[i++] = date->year;
}



static void  xtoa ( unsigned long val, char *buf, unsigned radix, int is_neg)
{
        char *p;                /* pointer to traverse string */
        char *firstdig;         /* pointer to first digit */
        char temp;              /* temp char */
        unsigned digval;        /* value of digit */

        p = buf;

        if (is_neg) {
            /* negative, so output '-' and negate */
            *p++ = '-';
            val = (unsigned long)(-(long)val);
        }

        firstdig = p;           /* save pointer to first digit */

        do {
            digval = (unsigned) (val % radix);
            val /= radix;       /* get next digit */

            /* convert to ascii and store */
            if (digval > 9)
                *p++ = (char) (digval - 10 + 'a');  /* a letter */
            else
                *p++ = (char) (digval + '0');       /* a digit */
        } while (val > 0);

        /* We now have the digit of the number in the buffer, but in reverse
           order.  Thus we reverse them now. */

        *p-- = '\0';            /* terminate string; p points to last digit */

        do {
            temp = *p;
            *p = *firstdig;
            *firstdig = temp;   /* swap *p and *firstdig */
            --p;
            ++firstdig;         /* advance to next two digits */
        } while (firstdig < p); /* repeat until halfway */
}


char * ultoa (unsigned long val, char *buf, int radix)
{
        xtoa(val, buf, radix, 0);
        return buf;
}


int serial_write(int port, const uint8_t buf[], int len)
{
    switch (port)
    {
    case 0:
        HAL_UART_Transmit(&huart3, buf, len, 0xFFFF);
        break;
    case 1:
        HAL_UART_Transmit(&huart3, buf, len, 0xFFFF);
        break;
    case 2:
        HAL_UART_Transmit(&huart3, buf, len, 0xFFFF);
        break;
    case 3:
        HAL_UART_Transmit(&huart3, buf, len, 0xFFFF);
        break;
    }
    return 0;
}


int dlt645_finalise_tx_message(int port, uint8_t msg[], int len, const uint8_t address[6])
{
    int i;
    uint8_t *s;

    if (len > MAX_DLT645_MSG_BODY)
        return FALSE;
    /* Add the header */
    for (i = 0;  i < 4;  i++)
        msg = 0xFE;
    msg[4] = 0x68;
    dlt645_insert_address(&msg[5], address);
    msg[11] = 0x68;
    /* The type should already be in byte 12 */
    msg[13] = len;
    msg[DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len] = 0;
    msg[DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len + 1] = 0x16;
    for (i = DLT645_PREAMBLE_BYTES;  i < DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len;  i++)
        msg[DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len] += msg;
    len = DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len + DLT645_MESSAGE_TRAILER_BYTES;
        if (len > DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + MAX_DLT645_MSG_BODY + DLT645_MESSAGE_TRAILER_BYTES)
        return false;
    serial_write(port, msg, len);
    return TRUE;
}


void dlt645_send_msg_11(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4])
{
    /* 68 A0 ... A5 68 11 04 DI0 ... DI3 CS 16 */
    msg[DLT645_TX_TYPE] = 0x11;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    dlt645_finalise_tx_message(port, msg, 4, address);
}

void dlt645_send_msg_11a(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int n)
{
    /* 68 A0 ... A5 68 11 05 DI0 ... DI3 N CS 16 */
    msg[DLT645_TX_TYPE] = 0x11;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    msg[DLT645_TX_START_BODY + 4] = n;
    dlt645_finalise_tx_message(port, msg, 5, address);
}

void dlt645_send_msg_11b(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int n, rtc_t *date)
{
    /* 68 A0 ... A5 68 11 0A DI0 ... DI3 N mm hh DD MM YY CS 16 */
    msg[DLT645_TX_TYPE] = 0x11;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    msg[DLT645_TX_START_BODY + 4] = n;
    dlt645_insert_date(&msg[DLT645_TX_START_BODY + 5], date, 5);
    dlt645_finalise_tx_message(port, msg, 10, address);
}

void dlt645_send_msg_91(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 91 L DI0 ... DI3 N1 ... NM CS 16 */
    msg[DLT645_TX_TYPE] = 0x91;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], n, m);
    dlt645_finalise_tx_message(port, msg, 4 + m, address);
}

void dlt645_send_msg_b1(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 B1 L DI0 ... DI3 N1 ... NM CS 16 */
    msg[DLT645_TX_TYPE] = 0xB1;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], n, m);
    dlt645_finalise_tx_message(port, msg, 4 + m, address);
}

void dlt645_send_msg_d1(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D1 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD1;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_12(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int seq)
{
    /* 68 A0 ... A5 68 12 05 DI0 ... DI3 SEQ CS 16 */
    msg[DLT645_TX_TYPE] = 0x12;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    msg[DLT645_TX_START_BODY] = seq;
    dlt645_finalise_tx_message(port, msg, 5, address);
}

void dlt645_send_msg_92(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 92 L DI0 ... DI3 N1 ... NM SEQ CS 16 */
    msg[DLT645_TX_TYPE] = 0x92;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], n, m);
    dlt645_finalise_tx_message(port, msg, 4 + m, address);
}

void dlt645_send_msg_b2(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 B2 L DI0 ... DI3 N1 ... NM SEQ CS 16 */
    msg[DLT645_TX_TYPE] = 0xB2;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], n, m);
    dlt645_finalise_tx_message(port, msg, 4 + m, address);
}

void dlt645_send_msg_d2(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D2 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD2;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_14(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t p[4], const uint8_t c[4], const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 14 L DI0 ... DI3 PA P0 P1 P2 C0 ... C3 N1 ... NM CS 16 */
    msg[DLT645_TX_TYPE] = 0x14;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 8], c, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 12], n, m);
    dlt645_finalise_tx_message(port, msg, 12 + m, address);
}

void dlt645_send_msg_94(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 94 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x94;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_d4(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D4 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD4;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_13(int port, uint8_t msg[])
{
    static const uint8_t address[6] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};

    /* 68 AA ... AA 68 13 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x13;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_93(int port, uint8_t msg[], const uint8_t address[6], const uint8_t addressx[])
{
    /* 68 A0 ... A5 68 93 06 A0 ... A5 CS 16 */
    msg[DLT645_TX_TYPE] = 0x93;
    dlt645_insert_address(&msg[DLT645_TX_START_BODY], addressx);
    dlt645_finalise_tx_message(port, msg, 6, address);
}

void dlt645_send_msg_15(int port, uint8_t msg[], const uint8_t address[6], const uint8_t addressx[])
{
    /* 68 A0 ... A5 68 15 06 A0 ... A5 CS 16 */
    msg[DLT645_TX_TYPE] = 0x15;
    dlt645_insert_address(&msg[DLT645_TX_START_BODY], addressx);
    dlt645_finalise_tx_message(port, msg, 6, address);
}

void dlt645_send_msg_95(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 95 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x95;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_08(int port, uint8_t msg[], const uint8_t address[6], rtc_t *date)
{
    /* 68 A0 ... A5 68 08 06 ss mm hh DD MM YY CS 16 */
    msg[DLT645_TX_TYPE] = 0x08;
    dlt645_insert_date(&msg[DLT645_TX_START_BODY], date, 6);
    dlt645_finalise_tx_message(port, msg, 6, address);
}

void dlt645_send_msg_16(int port, uint8_t msg[], const uint8_t address[6], rtc_t *date)
{
    /* 68 A0 ... A5 68 16 04 mm hh DD MM CS 16 */
    msg[DLT645_TX_TYPE] = 0x16;
    dlt645_insert_date(&msg[DLT645_TX_START_BODY], date, 4);
    dlt645_finalise_tx_message(port, msg, 4, address);
}

void dlt645_send_msg_16_999999(int port, uint8_t msg[], rtc_t *date)
{
    static const uint8_t address[6] = {0x99, 0x99, 0x99, 0x99, 0x99, 0x99};

    /* 68 99 ... 99 68 16 04 mm hh DD MM CS 16 */
    msg[DLT645_TX_TYPE] = 0x16;
    dlt645_insert_date(&msg[DLT645_TX_START_BODY], date, 4);
    dlt645_finalise_tx_message(port, msg, 4, address);
}

void dlt645_send_msg_96(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 96 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x96;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_d6(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D6 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD6;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_17(int port, uint8_t msg[], const uint8_t address[6], int z)
{
    /* 68 A0 ... A5 68 17 01 Z CS 16 */
    msg[DLT645_TX_TYPE] = 0x17;
    msg[DLT645_TX_START_BODY] = z;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_97(int port, uint8_t msg[], const uint8_t address[6], int z)
{
    /* 68 A0 ... A5 68 97 01 Z CS 16 */
    msg[DLT645_TX_TYPE] = 0x97;
    msg[DLT645_TX_START_BODY] = z;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_d7(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D7 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD7;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_18(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t p[4], const uint8_t pn[4])
{
    /* 68 A0 ... A5 68 18 0C DI0 .. DI3 PA0 PO0 P10 P20 PAN P0N P1N P2N CS 16 */
    msg[DLT645_TX_TYPE] = 0x18;
    dlt645_insert_di(&msg[DLT645_TX_START_BODY], di);
    memcpy(&msg[DLT645_TX_START_BODY + 4], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 8], pn, 4);
    dlt645_finalise_tx_message(port, msg, 12, address);
}

void dlt645_send_msg_98(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4])
{
    /* 68 A0 ... A5 68 98 04 PAN P0N P1N P2N CS 16 */
    msg[DLT645_TX_TYPE] = 0x98;
    memcpy(&msg[DLT645_TX_START_BODY], p, 4);
    dlt645_finalise_tx_message(port, msg, 4, address);
}

void dlt645_send_msg_d8(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D8 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD8;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_19(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4])
{
    /* 68 A0 ... A5 68 19 08 PA P0 P1 P2 C0 .. C3 CS 16 */
    msg[DLT645_TX_TYPE] = 0x19;
    memcpy(&msg[DLT645_TX_START_BODY], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 4], c, 4);
    dlt645_finalise_tx_message(port, msg, 8, address);
}

void dlt645_send_msg_99(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 99 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x99;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_d9(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 D9 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xD9;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_1a(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4])
{
    /* 68 A0 ... A5 68 1A 08 PA P0 P1 P2 C0 ... C3 CS 16 */
    msg[DLT645_TX_TYPE] = 0x1A;
    memcpy(&msg[DLT645_TX_START_BODY], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 4], c, 4);
    dlt645_finalise_tx_message(port, msg, 8, address);
}

void dlt645_send_msg_9a(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 9A 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x9A;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_da(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 DA 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xDA;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_1bx(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4])
{
    static const uint8_t di[4] =
    {
        0xFF, 0xFF, 0xFF, 0xFF
    };

    /* 68 A0 ... A5 68 1B 0C PA P0 P1 P2 C0 ... C3 FF FF FF FF CS 16 */
    msg[DLT645_TX_TYPE] = 0x1B;
    memcpy(&msg[DLT645_TX_START_BODY], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 4], c, 4);
    dlt645_insert_di(&msg[DLT645_TX_START_BODY + 8], di);
    dlt645_finalise_tx_message(port, msg, 12, address);
}

void dlt645_send_msg_1b(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4], const uint8_t di[4])
{
    /* 68 A0 ... A5 68 1B 0C PA P0 P1 P2 C0 ... C3 FF DI1 DI2 DI3 CS 16 */
    msg[DLT645_TX_TYPE] = 0x1B;
    memcpy(&msg[DLT645_TX_START_BODY], p, 4);
    memcpy(&msg[DLT645_TX_START_BODY + 4], c, 4);
    dlt645_insert_di(&msg[DLT645_TX_START_BODY + 8], di);
    dlt645_finalise_tx_message(port, msg, 12, address);
}

void dlt645_send_msg_9b(int port, uint8_t msg[], const uint8_t address[6])
{
    /* 68 A0 ... A5 68 9B 00 CS 16 */
    msg[DLT645_TX_TYPE] = 0x9B;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

void dlt645_send_msg_db(int port, uint8_t msg[], const uint8_t address[6], int err)
{
    /* 68 A0 ... A5 68 DB 01 ERR CS 16 */
    msg[DLT645_TX_TYPE] = 0xDB;
    msg[DLT645_TX_START_BODY] = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}



void dlt645_log_di(const uint8_t di[4])
{
    printf("DI = %02X %02X %02X %02X\r\n", di[0], di[1], di[2], di[3]);
}

void dlt645_log_date(const uint8_t date[4], int n)
{
    switch (n)
    {
    case 4:
        printf("Date = %02d/%02d %02d:%02d", date[3], date[2], date[1], date[0]);
        break;
    case 5:
        printf("Date = %04d/%02d/%02d %02d:%02d", date[4] + 2000, date[3], date[2], date[1], date[0]);
        break;
    case 6:
        printf("Date = %04d/%02d/%02d %02d:%02d:%02d", date[5] + 2000, date[4], date[2], date[1], date[0]);
        break;
    }
}

void dlt645_log_n(const uint8_t n[4], int m)
{
    int i;

    printf("N =");
    for (i = 0;  i < m;  i++)
        printf(" %02X", n);
}


void dlt645_log_p(const uint8_t p[4])
{
    printf("P = %02X %02X %02X %02X", p[0], p[1], p[2], p[3]);
}

void dlt645_log_c(const uint8_t c[4])
{
    printf("C = %02X %02X %02X %02X", c[0], c[1], c[2], c[3]);
}

void dlt645_log_address(const uint8_t address[6])
{
    printf("Address = %02X %02X %02X %02X %02X %02X", address[0], address[1], address[2], address[3], address[4], address[5]);
}


static void reverseArray(uint8_t *arr, uint16_t length)
{
    uint16_t left = 0;
    uint16_t right = length - 1;

    while (left < right)
    {
        // 交换元素
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;

        // 移动指针
        left++;
        right--;
    }
}



void num16_to_array2(uint16_t num,uint8_t *arr)
{
        uint8_t i=0;
        uint8_t num_h,num_l;

    if(num>9999)i=3;
        else if(num>99)i=2;
        else i=1;

        if(i==1)
        {
                arr[0]=0x00;
                arr[1]=((num/10)<<4|(num%10));
        }
        else if(i==2)
        {
                num_h=num/100;
                num_l=num%100;
                arr[0]=((num_h/10)<<4|(num_h%10));
                arr[1]=((num_l/10)<<4|(num_l%10));
        }
        else if(i==3)
        {
                printf("error!\r\n");
        }
}


void num24_to_array3(uint32_t num,uint8_t *arr)
{
        uint8_t i=0;
        uint32_t num_h,num_l,num_1,num_2;

        if(num>999999)i=4;
    else if(num>9999)i=3;
        else if(num>99)i=2;
        else i=1;

        if(i==1)
        {
                arr[0]=0x00;
                arr[1]=((num/10)<<4|(num%10));
        }
        else if(i==2)
        {
                num_h=num/100;
                num_l=num%100;
                arr[0]=((num_h/10)<<4|(num_h%10));
                arr[1]=((num_l/10)<<4|(num_l%10));
        }
        else if(i==3)
        {
                num_2=num/10000;//printf("num_2:%d\r\n",num_2);
                num_1=num%10000;//printf("num_1:%d\r\n",num_1);
                num_h=num_1/100;//printf("num_h:%d\r\n",num_h);
                num_l=num_1%100;//printf("num_l:%d\r\n",num_l);
                arr[0]=((num_2/10)<<4|(num_2%10));
                arr[1]=((num_h/10)<<4|(num_h%10));
                arr[2]=((num_l/10)<<4|(num_l%10));
        }
        else if(i==4)
        {
                printf("error!\r\n");
        }
}


void num32_to_array4(uint32_t num,uint8_t *arr)
{
        uint8_t i=0;
        uint32_t num_h,num_l,num_2,num_3,num_4,num_5;

        if(num>99999999)      i=5;
        else if(num>999999)   i=4;
    else if(num>9999)     i=3;
        else if(num>99)       i=2;
        else                  i=1;

        if(i==1)
        {
            arr[0]=0x00;
            arr[1]=0x00;
                arr[2]=0x00;
                arr[3]=((num/10)<<4|(num%10));
        }
        else if(i==2)
        {
                num_h=num/100;//printf("num_h:%d\r\n",num_h);
                num_l=num%100;//printf("num_l:%d\r\n",num_l);
                arr[0]=0x00;
            arr[1]=0x00;
                arr[2]=((num_h/10)<<4|(num_h%10));
                arr[3]=((num_l/10)<<4|(num_l%10));
        }
        else if(i==3)
        {
                num_3=num/10000;//printf("num_3:%d\r\n",num_3);
                num_2=num%10000;//printf("num_2:%d\r\n",num_2);
                num_h=num_2/100;//printf("num_h:%d\r\n",num_h);
                num_l=num_2%100;//printf("num_l:%d\r\n",num_l);
                arr[0]=0x00;
            arr[1]=((num_3/10)<<4|(num_3%10));
                arr[2]=((num_h/10)<<4|(num_h%10));
                arr[3]=((num_l/10)<<4|(num_l%10));
        }
        else if(i==4)
        {
                num_5=num/1000000;//printf("num_5:%d\r\n",num_5);
                num_4=num%1000000;//printf("num_4:%d\r\n",num_4);
                num_3=num_4/10000;//printf("num_3:%d\r\n",num_3);
                num_2=num_4%10000;//printf("num_2:%d\r\n",num_2);
                num_l=num_2/100;//printf("num_l:%d\r\n",num_l);
                num_h=num_2%100;//printf("num_h:%d\r\n",num_h);
                arr[0]=((num_5/10)<<4|(num_5%10));
            arr[1]=((num_3/10)<<4|(num_3%10));
                arr[2]=((num_l/10)<<4|(num_l%10));
                arr[3]=((num_h/10)<<4|(num_h%10));
        }
        else if(i==5)
        {
                printf("error!\r\n");
        }
}




uint32_t dec_to_bcd(uint32_t val)
{
    uint32_t data = 0;

    if (val < 100)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = val / 10;
        data = (byte1 << 4) + byte0;
    }
    else if (val < 10000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        data = (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    else if (val < 1000000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        uint8_t byte4 = (val / 10000) % 10;
        uint8_t byte5 = (val / 100000) % 10;
        data = (byte5 << 20) +
               (byte4 << 16) +
               (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    else if (val < 100000000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        uint8_t byte4 = (val / 10000) % 10;
        uint8_t byte5 = (val / 100000) % 10;
        uint8_t byte6 = (val / 1000000) % 10;
        uint8_t byte7 = (val / 10000000) % 10;
        data = (byte7 << 28) +
               (byte6 << 24) +
               (byte5 << 20) +
               (byte4 << 16) +
               (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    return data;
}



//字符串转相应无符号十进制数字
uint32_t Str_to_Uint32(const unsigned char *p,unsigned char len)
{
        int i;
        uint32_t res = 0L;        // 转化后的数字
        int pos = 1;                // 位数*10 *100 ...
        for (i = 0; i < len; ++i) {
                res += (p[len-1-i]-48)*pos;
                pos *= 10;
        }
        return res;
}

//无符号十进制数字转相应字符串数字
void Uint32_to_Str(uint32_t indata,char* outdata)
{
        char buf[10]="";
        uint8_t i=0;
        uint32_t temp = indata;
        while(temp){
                buf[i++] = (temp % 10) + '0';  //把temp的每一位上的数存入buf
                temp = temp / 10;
        }
        outdata = 0;            //末尾是结束符0
        for(int j=0,k=i-1;j<i;j++,k--)//002511
                outdata[j]=buf[k];
}








void hex_to_bcd(unsigned long dat,unsigned char *buf,unsigned char bytelength)
{
        unsigned char data[10]={'0','0','0','0','0','0','0','0','0','0'};
        unsigned char databak[20];
        unsigned char i;
        unsigned char n;
        unsigned char m;
        unsigned char *p;
        ultoa(dat,(signed char*)databak,10);
        m=strlen((signed char*)databak);
        p=data;
        for(i=m;i>0;i--)
        {
                *(p++)=databak[i-1];
        }
        switch(bytelength)
        {
                case 0: n = 8;break;
                case 1: n = 2;break;
                case 2: n = 4;break;
                case 4: n = 8;break;
        }
        for(i=0;i<n;i+=2)
         {
                  *(buf++)=(data&0x0f)|((data[i+1]&0x0f)<<4);
          }                        
}


unsigned char bcd_to_uint8_t(unsigned char *buf,unsigned char length)
{
        unsigned char dat;
  unsigned char a,b,c;        
  a=((*buf)&(0xf0))>>4;
  b=(*buf)&(0x0f);
  c=(*(buf+1))&(0x0f);
  if(length==1)
          {
                  dat=a*10+b;
          }
  else
          {
                  dat=(c*10+a)*10+b;
          }  
  return dat;
}

unsigned short bcd_to_u16(unsigned char *buf,unsigned char length)
{
        unsigned short dat;
  unsigned short a,b,c,d,e;
  a=(*(buf+2))&(0x0f);
  b=((*(buf+1))&(0xf0))>>4;
  c=(*(buf+1))&(0x0f);
  d=((*buf)&(0xf0))>>4;
  e=(*buf)&(0x0f);
  if(length==1)
          {
                  dat=d*10+e;        
          }
  else if(length==2)
          {
                  dat=((b*10+c)*10+d)*10+e;        
          }
  else
          {
                  dat=(((a*10+b)*10+c)*10+d)*10+e;
          }
  return dat;        
}


unsigned long bcd_to_uint32_t(unsigned char *buf,unsigned char length)
{
        unsigned long dat;
  unsigned long a,b,c,d,e,f,g,h,j,k;
  a=(*(buf+2))&(0x0f);
  b=((*(buf+1))&(0xf0))>>4;
  c=(*(buf+1))&(0x0f);
  d=((*buf)&(0xf0))>>4;
  e=(*buf)&(0x0f);
  f=((*(buf+2))&(0xf0))>>4;
  g=(*(buf+3))&(0x0f);
  h=((*(buf+3))&(0xf0))>>4;
  j=(*(buf+4))&(0x0f);
  k=((*(buf+4))&(0xf0))>>4;
  if(length==1)
          {
                  dat=d*10+e;        
          }
  else if(length==2)
          {
                  dat=((b*10+c)*10+d)*10+e;
          }
  else if(length==3)
          {
                  dat=((((f*10+a)*10+b)*10+c)*10+d)*10+e;        
          }
  else if(length==4)        
          {
                  dat=((((((h*10+g)*10+f)*10+a)*10+b)*10+c)*10+d)*10+e;         
          }
  else
          {
                  dat=((((((((k*10+j)*10+h)*10+g)*10+f)*10+a)*10+b)*10+c)*10+d)*10+e;         
          }   
  return dat;        
}




uint32_t PTenergy = 1234567;                      /*total current positive energy*/
uint32_t NTenergy;                      /*total current negative energy */
uint32_t PTenergy1;                     /*total current positive energy at fee-rate 1*/
uint32_t NTenergy1;                     /*total current negative energy at fee-rate 1*/
uint32_t PTenergy2;                     /*total current positive energy at fee-rate 2*/
uint32_t NTenergy2;                     /*total current negative energy at fee-rate 2*/



void get_energydata(uint8_t *buf,uint32_t data_to_be_read)
{
        uint8_t bak[8];
        uint8_t i;
        uint8_t k;
        ultoa(data_to_be_read,(char*)bak,10);
        k=strlen((char*)bak);
        if(k<8)
                {
                        for(i=0;i<k;i++)
                        {
                          *(buf+i)=bak[k-i-1];        
                        }
                }
        else
                {
                        for(i=0;i<7;i++)
                        {
                                *(buf+i)=bak[7-i];        
                        }
                }
}


void get_PTenergy(uint8_t *buf)   /*read current positive total energy, the data is char type,the lower bit is in front*/
{        
        get_energydata(buf,PTenergy);
}
void get_NTenergy(uint8_t *buf)    /*read current negative total energy,the data is char type,the lower bit is in front*/
{
        get_energydata(buf,NTenergy);
        
}

void get_PTenergy1(uint8_t *buf)        /*read current positive total energy of fee-rate 1*/
{
        get_energydata(buf,PTenergy1);
        
}

void get_NTenergy1(uint8_t *buf)       /*read current negative total energy of fee-rate 1*/
{
        get_energydata(buf,NTenergy1);
        
}


void get_PTenergy2(uint8_t *buf)       /*read current positive total energy of fee-rate 2*/
{
        get_energydata(buf,PTenergy2);
        
}


void get_NTenergy2 (uint8_t *buf)      /*read current negative total energy of fee-rate 2*/
{
        get_energydata(buf,NTenergy2);
        
}



uint8_t Read_PTenergy(uint8_t *buf)
{
        uint8_t i;
        uint8_t bak[8]={'0','0','0','0','0','0','0','0'};
        get_PTenergy(bak);
        for(i=7;i>0;i--)
        {
                bak=bak[i-1];
        }
         bak[0]=0x30;
         for(i=0;i<7;i=i+2)
         {
                 *buf=((bak-0x30)&0x0f)|(((bak[i+1]-0x30)&0x0f)<<4);
                 buf++;
         }
         return OK;
}


uint8_t Read_NTenergy(uint8_t *buf)
{
        uint8_t i;
        uint8_t bak[8]={'0','0','0','0','0','0','0','0'};
        get_NTenergy(bak);
        for(i=7;i>0;i--)
        {
                bak=bak[i-1];
        }
         bak[0]=0x30;
         for(i=0;i<7;i=i+2)
         {
                 *buf=((bak-0x30)&0x0f)|(((bak[i+1]-0x30)&0x0f)<<4);
                 buf++;
         }
        return OK;
}


int serial_write(int port, const uint8_t buf[], int len);
int dlt645_finalise_tx_message(int port, uint8_t msg[], int len, const uint8_t address[6]);

void dlt645_log_di(const uint8_t di[4]);
void dlt645_log_date(const uint8_t date[4], int n);
void dlt645_log_n(const uint8_t n[4], int m);
void dlt645_log_p(const uint8_t p[4]);
void dlt645_log_c(const uint8_t c[4]);
void dlt645_log_address(const uint8_t address[6]);

void dlt645_send_msg_11(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4]);
void dlt645_send_msg_11a(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int n);
void dlt645_send_msg_11b(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int n, rtc_t *date);
void dlt645_send_msg_91(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m);
void dlt645_send_msg_b1(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m);
void dlt645_send_msg_d1(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_12(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], int seq);
void dlt645_send_msg_92(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m);
void dlt645_send_msg_b2(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t n[], int m);
void dlt645_send_msg_d2(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_14(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t p[4], const uint8_t c[4], const uint8_t n[], int m);
void dlt645_send_msg_94(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_d4(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_13(int port, uint8_t msg[]);
void dlt645_send_msg_93(int port, uint8_t msg[], const uint8_t address[6], const uint8_t addressx[]);
void dlt645_send_msg_15(int port, uint8_t msg[], const uint8_t address[6], const uint8_t addressx[]);
void dlt645_send_msg_95(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_08(int port, uint8_t msg[], const uint8_t address[6], rtc_t *date);
void dlt645_send_msg_16(int port, uint8_t msg[], const uint8_t address[6], rtc_t *date);
void dlt645_send_msg_16_999999(int port, uint8_t msg[], rtc_t *date);
void dlt645_send_msg_96(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_d6(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_17(int port, uint8_t msg[], const uint8_t address[6], int z);
void dlt645_send_msg_97(int port, uint8_t msg[], const uint8_t address[6], int z);
void dlt645_send_msg_d7(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_18(int port, uint8_t msg[], const uint8_t address[6], const uint8_t di[4], const uint8_t p[4], const uint8_t pn[4]);
void dlt645_send_msg_98(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4]);
void dlt645_send_msg_d8(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_19(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4]);
void dlt645_send_msg_99(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_d9(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_1a(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4]);
void dlt645_send_msg_9a(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_da(int port, uint8_t msg[], const uint8_t address[6], int err);
void dlt645_send_msg_1bx(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4]);
void dlt645_send_msg_1b(int port, uint8_t msg[], const uint8_t address[6], const uint8_t p[4], const uint8_t c[4], const uint8_t di[4]);
void dlt645_send_msg_9b(int port, uint8_t msg[], const uint8_t address[6]);
void dlt645_send_msg_db(int port, uint8_t msg[], const uint8_t address[6], int err);
char * ultoa (unsigned long val, char *buf, int radix);



void num16_to_array2(uint16_t num,uint8_t *arr);
void num24_to_array3(uint32_t num,uint8_t *arr);
void num32_to_array4(uint32_t num,uint8_t *arr);


uint32_t dec_to_bcd(uint32_t val);

uint32_t Str_to_Uint32(const unsigned char *p,unsigned char len) ;
void Uint32_to_Str(uint32_t indata,char* outdata);


void hex_to_bcd(unsigned long dat,unsigned char *buf,unsigned char bytelength);
unsigned char bcd_to_u8(unsigned char *buf,unsigned char length);
unsigned short bcd_to_u16(unsigned char *buf,unsigned char length);
unsigned long bcd_to_u32(unsigned char *buf,unsigned char length);

void get_energydata(uint8_t *buf,uint32_t data_to_be_read);




extern uint32_t PTenergy;                      /*total current positive energy*/
extern uint32_t NTenergy;                      /*total current negative energy */
extern uint32_t PTenergy1;                     /*total current positive energy at fee-rate 1*/
extern uint32_t NTenergy1;                     /*total current negative energy at fee-rate 1*/
extern uint32_t PTenergy2;                     /*total current positive energy at fee-rate 2*/
extern uint32_t NTenergy2;                     /*total current negative energy at fee-rate 2*/


void get_PTenergy(uint8_t *buf) ;
void get_NTenergy(uint8_t *buf);
void get_PTenergy1(uint8_t *buf);
void get_NTenergy1(uint8_t *buf);
void get_PTenergy2(uint8_t *buf);
void get_NTenergy2 (uint8_t *buf);

#define OK                   1
#define NOT_OK               0

uint8_t Read_PTenergy(uint8_t *buf);
uint8_t Read_NTenergy(uint8_t *buf);



  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        SerialDecode();

    /* USER CODE BEGIN 3 */
  }

主函数完成解码即可
// 数据解码
void SerialDecode(void)
{
   SerialTimeOut();
   if(!MSG_SERIAL.RecOver) {return;} // 接收没有完成
   if(MSG_SERIAL.RecBuf[7]!=ADR) {return;} // 如果帧起始符错误
   if(!RcvChk()) {return;} // 如果校验错误
   SerialDecoding(&MSG_SERIAL.RecBuf[8]); //   
   ClrRcvBuf();          // 清缓存区  
}

这里发帖有图片限制,只能发在附件里了
1,打开DLT645-2007电表上位机




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

6

帖子

0

粉丝