龙鳞铁碎牙 发表于 2025-5-20 11:15

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

本帖最后由 龙鳞铁碎牙 于 2025-5-21 16:55 编辑

#有奖活动# #技术资源# #申请开发板# #每日话题# #申请原创#         大家平时在家用电时,每家每户都会接入一个电表,这个东西记录了每个家庭使用的电量读数,在农村每月或者每季度就有专门的人来村里催收电费,然而在城市里面,每家都有电表卡,当出现欠费后,就需要人员去充值缴费后,才能正常用电.
      这个电表说白了就是一个计量电能读数的一个装置,内部原理非常的简单,就是一个电表协议的收发,国内的电表协议非常的专一,一直以来都是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=SOI;MSG_SERIAL.RecCount=1; // 启动接收
   }
   else if((MSG_SERIAL.RecBuf==SOI)&&(MSG_SERIAL.RecCount<REC_MAX)) // 如果已经接收到起始位
   {MSG_SERIAL.RecBuf=RecData;} // 将数据添加到缓存区
   else {MSG_SERIAL.RecCount=0;}      
   if((RecData==EOI)&&(MSG_SERIAL.RecCount==(MSG_SERIAL.RecBuf+12)))
   {
   MSG_SERIAL.RecOver=1;
   MSG_SERIAL.RecTimer=0;          // 清计时器
   } //接收完成         
}

#defineREC_MAX   150    // 定义接收缓存区的大小
#defineSEND_MAX150    // 定义发送缓存区的大小

#defineSOI       0x68       // 帧起始符
#defineADR       0x68       // 帧起始符
#defineEOI       0x16       // 结束符

#defineSERIAL_TIME_ISR   5// 定时器间隔 ms
#defineTIME_OUT   500       // 接收超时时间 ms
#defineTIME_SLEEP 10000   // 休眠超时时间

typedef struct
{
uint8_tRecBuf;    // 接收缓存区
uint8_tRecCount;         // 接收的字节数
uint8_tSendBuf;   // 发送缓存区
uint8_tSendCount;          // 要发送的字节数
uint8_tRecOver;            // 接收完成标志
uint16_t RecTimer;         // 接收计时器
uint16_t SleepTime;          // 休眠计时
uint8_tSleepFlag;          // 通讯休眠标志
} 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+10]==ChkSum(&MSG_SERIAL.RecBuf,MSG_SERIAL.RecBuf+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!=ADR) {return;} // 如果帧起始符错误
   if(!RcvChk()) {return;} // 如果校验错误
   SerialDecoding(&MSG_SERIAL.RecBuf); //   
   ClrRcvBuf();          // 清缓存区
}

// 串口发送数据
void SerialOutput(void)
{
   static uint8_t mSendCount=0;
   if(MSG_SERIAL.SendCount)
   {
          MSG_SERIAL.SendCount--;
      //UART_DR=MSG_SERIAL.SendBuf; // 发送数据
   }
   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+12);
          for(uint8_t i = 0; i < MSG_SERIAL.RecBuf+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 = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
   uint8_t nx = {0x33, 0x35, 0x44, 0x44};

   port = 0;
   type = *pData;
   tx = &MSG_SERIAL.SendBuf;
   msg_len = MSG_SERIAL.RecBuf;
   msg = &MSG_SERIAL.RecBuf;

   //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);
                  dlt645_log_date(&msg, 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)
{
    int i;

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

static __inline__ void dlt645_insert_di(uint8_t msg[], const uint8_t di)
{
    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 = date->second;
    msg = date->minute;
    msg = date->hour;
    msg = date->day;
    msg = date->month;
    if (n > 4)
      msg = date->year;
}



static voidxtoa ( 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)
{
    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 = 0x68;
    dlt645_insert_address(&msg, address);
    msg = 0x68;
    /* The type should already be in byte 12 */
    msg = len;
    msg = 0;
    msg = 0x16;
    for (i = DLT645_PREAMBLE_BYTES;i < DLT645_PREAMBLE_BYTES + DLT645_MESSAGE_HEADER_BYTES + len;i++)
      msg += 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, const uint8_t di)
{
    /* 68 A0 ... A5 68 11 04 DI0 ... DI3 CS 16 */
    msg = 0x11;
    dlt645_insert_di(&msg, di);
    dlt645_finalise_tx_message(port, msg, 4, address);
}

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

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

void dlt645_send_msg_91(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 91 L DI0 ... DI3 N1 ... NM CS 16 */
    msg = 0x91;
    dlt645_insert_di(&msg, di);
    memcpy(&msg, 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, const uint8_t di, const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 B1 L DI0 ... DI3 N1 ... NM CS 16 */
    msg = 0xB1;
    dlt645_insert_di(&msg, di);
    memcpy(&msg, 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, int err)
{
    /* 68 A0 ... A5 68 D1 01 ERR CS 16 */
    msg = 0xD1;
    msg = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

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

void dlt645_send_msg_92(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 92 L DI0 ... DI3 N1 ... NM SEQ CS 16 */
    msg = 0x92;
    dlt645_insert_di(&msg, di);
    memcpy(&msg, 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, const uint8_t di, const uint8_t n[], int m)
{
    /* 68 A0 ... A5 68 B2 L DI0 ... DI3 N1 ... NM SEQ CS 16 */
    msg = 0xB2;
    dlt645_insert_di(&msg, di);
    memcpy(&msg, 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, int err)
{
    /* 68 A0 ... A5 68 D2 01 ERR CS 16 */
    msg = 0xD2;
    msg = err;
    dlt645_finalise_tx_message(port, msg, 1, address);
}

void dlt645_send_msg_14(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t p, const uint8_t c, 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 = 0x14;
    dlt645_insert_di(&msg, di);
    memcpy(&msg, p, 4);
    memcpy(&msg, c, 4);
    memcpy(&msg, 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)
{
    /* 68 A0 ... A5 68 94 00 CS 16 */
    msg = 0x94;
    dlt645_finalise_tx_message(port, msg, 0, address);
}

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

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

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

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

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

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

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

void dlt645_send_msg_16(int port, uint8_t msg[], const uint8_t address, rtc_t *date)
{
    /* 68 A0 ... A5 68 16 04 mm hh DD MM CS 16 */
    msg = 0x16;
    dlt645_insert_date(&msg, 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 = {0x99, 0x99, 0x99, 0x99, 0x99, 0x99};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



void dlt645_log_di(const uint8_t di)
{
    printf("DI = %02X %02X %02X %02X\r\n", di, di, di, di);
}

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

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

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


void dlt645_log_p(const uint8_t p)
{
    printf("P = %02X %02X %02X %02X", p, p, p, p);
}

void dlt645_log_c(const uint8_t c)
{
    printf("C = %02X %02X %02X %02X", c, c, c, c);
}

void dlt645_log_address(const uint8_t address)
{
    printf("Address = %02X %02X %02X %02X %02X %02X", address, address, address, address, address, address);
}


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

    while (left < right)
    {
      // 交换元素
      int temp = arr;
      arr = arr;
      arr = 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=0x00;
                arr=((num/10)<<4|(num%10));
      }
      else if(i==2)
      {
                num_h=num/100;
                num_l=num%100;
                arr=((num_h/10)<<4|(num_h%10));
                arr=((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=0x00;
                arr=((num/10)<<4|(num%10));
      }
      else if(i==2)
      {
                num_h=num/100;
                num_l=num%100;
                arr=((num_h/10)<<4|(num_h%10));
                arr=((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=((num_2/10)<<4|(num_2%10));
                arr=((num_h/10)<<4|(num_h%10));
                arr=((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=0x00;
            arr=0x00;
                arr=0x00;
                arr=((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=0x00;
            arr=0x00;
                arr=((num_h/10)<<4|(num_h%10));
                arr=((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=0x00;
            arr=((num_3/10)<<4|(num_3%10));
                arr=((num_h/10)<<4|(num_h%10));
                arr=((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=((num_5/10)<<4|(num_5%10));
            arr=((num_3/10)<<4|(num_3%10));
                arr=((num_l/10)<<4|(num_l%10));
                arr=((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-48)*pos;
                pos *= 10;
      }
      return res;
}

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








void hex_to_bcd(unsigned long dat,unsigned char *buf,unsigned char bytelength)
{
      unsigned char data={'0','0','0','0','0','0','0','0','0','0'};
      unsigned char databak;
      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;
      }
      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&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;
      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;      
                        }
                }
      else
                {
                        for(i=0;i<7;i++)
                        {
                              *(buf+i)=bak;      
                        }
                }
}


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={'0','0','0','0','0','0','0','0'};
      get_PTenergy(bak);
      for(i=7;i>0;i--)
      {
                bak=bak;
      }
         bak=0x30;
         for(i=0;i<7;i=i+2)
         {
               *buf=((bak-0x30)&0x0f)|(((bak-0x30)&0x0f)<<4);
               buf++;
         }
         return OK;
}


uint8_t Read_NTenergy(uint8_t *buf)
{
      uint8_t i;
      uint8_t bak={'0','0','0','0','0','0','0','0'};
      get_NTenergy(bak);
      for(i=7;i>0;i--)
      {
                bak=bak;
      }
         bak=0x30;
         for(i=0;i<7;i=i+2)
         {
               *buf=((bak-0x30)&0x0f)|(((bak-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);

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

void dlt645_send_msg_11(int port, uint8_t msg[], const uint8_t address, const uint8_t di);
void dlt645_send_msg_11a(int port, uint8_t msg[], const uint8_t address, const uint8_t di, int n);
void dlt645_send_msg_11b(int port, uint8_t msg[], const uint8_t address, const uint8_t di, int n, rtc_t *date);
void dlt645_send_msg_91(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m);
void dlt645_send_msg_b1(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m);
void dlt645_send_msg_d1(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_12(int port, uint8_t msg[], const uint8_t address, const uint8_t di, int seq);
void dlt645_send_msg_92(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m);
void dlt645_send_msg_b2(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t n[], int m);
void dlt645_send_msg_d2(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_14(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t p, const uint8_t c, const uint8_t n[], int m);
void dlt645_send_msg_94(int port, uint8_t msg[], const uint8_t address);
void dlt645_send_msg_d4(int port, uint8_t msg[], const uint8_t address, 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, const uint8_t addressx[]);
void dlt645_send_msg_15(int port, uint8_t msg[], const uint8_t address, const uint8_t addressx[]);
void dlt645_send_msg_95(int port, uint8_t msg[], const uint8_t address);
void dlt645_send_msg_08(int port, uint8_t msg[], const uint8_t address, rtc_t *date);
void dlt645_send_msg_16(int port, uint8_t msg[], const uint8_t address, 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);
void dlt645_send_msg_d6(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_17(int port, uint8_t msg[], const uint8_t address, int z);
void dlt645_send_msg_97(int port, uint8_t msg[], const uint8_t address, int z);
void dlt645_send_msg_d7(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_18(int port, uint8_t msg[], const uint8_t address, const uint8_t di, const uint8_t p, const uint8_t pn);
void dlt645_send_msg_98(int port, uint8_t msg[], const uint8_t address, const uint8_t p);
void dlt645_send_msg_d8(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_19(int port, uint8_t msg[], const uint8_t address, const uint8_t p, const uint8_t c);
void dlt645_send_msg_99(int port, uint8_t msg[], const uint8_t address);
void dlt645_send_msg_d9(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_1a(int port, uint8_t msg[], const uint8_t address, const uint8_t p, const uint8_t c);
void dlt645_send_msg_9a(int port, uint8_t msg[], const uint8_t address);
void dlt645_send_msg_da(int port, uint8_t msg[], const uint8_t address, int err);
void dlt645_send_msg_1bx(int port, uint8_t msg[], const uint8_t address, const uint8_t p, const uint8_t c);
void dlt645_send_msg_1b(int port, uint8_t msg[], const uint8_t address, const uint8_t p, const uint8_t c, const uint8_t di);
void dlt645_send_msg_9b(int port, uint8_t msg[], const uint8_t address);
void dlt645_send_msg_db(int port, uint8_t msg[], const uint8_t address, 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!=ADR) {return;} // 如果帧起始符错误
   if(!RcvChk()) {return;} // 如果校验错误
   SerialDecoding(&MSG_SERIAL.RecBuf); //   
   ClrRcvBuf();          // 清缓存区
}

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


可以看到,刚开始是没有数据的,空白,必须要我们手动发送报文
1.发送正向有功电能

发送:(16:52:32 376)FE FE FE FE 68 99 99 99 99 99 99 68 11 04 33 33 33 33 47 16
接收:(16:52:32 668)FE FE FE FE 68 12 34 56 78 9A BC 68 91 08 00 00 00 00 70 56 34 12 77 16

串口助手上提取的接收报文

和发送:(16:52:32 376)FE FE FE FE 68 99 99 99 99 99 99 68 11 04 33 33 33 33 47 16 的一致,解析正确,因为4个0XFE前导码必须舍去,这只是起到唤醒电表作用,没有其它的实际意义!
接着继续发完

到此,DLT645-2007三相电表协议解析完成!!!!

598330983 发表于 2025-5-26 17:27

如果只从单相取电,电表是计量单相电的还是三相电的?

daichaodai 发表于 2025-5-26 19:33

这个是协议是标准协议,应该有标准文档吧

suncat0504 发表于 2025-5-26 20:23

挺详细的,谢谢分享!

龙鳞铁碎牙 发表于 2025-5-27 08:42

daichaodai 发表于 2025-5-26 19:33
这个是协议是标准协议,应该有标准文档吧

是的,文档在附件里

龙鳞铁碎牙 发表于 2025-5-27 08:46

598330983 发表于 2025-5-26 17:27
如果只从单相取电,电表是计量单相电的还是三相电的?

协议是不分单相和三相的,都是DLT645-2007,单相和三相是涉及到电能计量和计算算法,这个自己去实现
页: [1]
查看完整版本: 【STM32C092RC 测评】解码DLT645-2007多功能三相电表