stm32实现电表电量采集

stm32实现电表电量采集

wangxl@20180815

一、概述

  1. 本章中,不特殊说明都以stm32F030为例,软件平台为iar6.4
  2. 通过开发板的485与电表通讯,波特率采用1200,根据DLT645-1997通讯规约通信规约,采集电表的电量。

二、本章学习目标

  1. 学会了解DLT645-1997通讯规约通信规约
  2. 理解stm32 485配置
  3. 学会485通讯及串口收发数据处理
  • DLT645-1997通讯规约
  1. 帧格式:

  

  

帧起始符

68H

地址域

A0

A1

A2

A3

A4

A5

帧起始符

68

控制码

C

数据长度域

L

数据域

DATA

校验码

CS

结束符

16H

帧起始符68H :标识一帧信息的开始,其值为 68H;

地址域  A0 ∽ A5 :地址域由 6 个字节构成,每字节 2 位 BCD 码。

当地址为999999999999H 时,为广播地址;

控制码:读数据主站请求帧 控制码 C=01H;从站正常应答 控制码 C=81H 无后续数据帧;

数据长度域 L :L 为数据域的字节数;

数据域  DATA :数据域包括数据标识和数据、密码等,其结构随控制码的功能而改变。传输时发送方按字节进行加 33H 处理,接收方按字节进行减 33H 处理。

校验码  CS :从帧起始符开始到校验码之前的所有各字节的模 256 的和, 即各字节二进制算术和,不计超过 256 的溢出值。

当前正向有功总电能的数据标识为:9010H,数据格式为 XXXXXX.XX(kWh)

  1. 报文格式简介

(1)发送求请当前正向有功总电能的数据:

报文: FE FE FE 68 99 99 99 99 99 99 68 01 02 43 c3 6f 16

数据分析:

FE:为唤醒符,报文之前可以加若干个FE;

68:帧起始符;

99 99 99 99 99 99:地址域,为广播表号;

68:帧起始符;

01:控制码,为读数据(主站请求帧);

02:指数据区域字节数,表示之后2个字节为数据区域,也就是43 c3;

43 c3:数据区域,传输时发送方按字节进行加 33H 处理,接收方按字节进行减 33H 处理,接收处理后为10 90,刚好等于当前正向有功总电能的数据标识为0x9010;

6f :校验码,校验方式为和校验,取最低位字节,

(16进制68+99+99+99+99+99+99+68+01+02+43+c3=56F,取6F)

16:结束符

 

  1. 接收当前正向有功总电能的数据

报文:FE FE FE FE 68 15 32 00 67 00 00 68 81 06 43 C3 84 77 33 33 6C 16

FE:为唤醒符;

15 32 00 67 00 00:地址域,表号;

81:从站正常应答

06:数据区域字节数为6字节;

43 C3 84 77 33 33:减33H后为10 90 51 44 00 00 ,数据标识为10 90,相当于u16数据类型的0x9010,根据协议解析为读正向有功总电能,数据为51 44 00 00,当于u32数据类型的0x00004451,即解析出电量数据为44.51kWh;参见下表电能量数据标识编码表;

详见:DL/T645-2007  通讯规约通信规约

四、RS485配置及数据处理

1.配置外设时钟

需要配置串口所在引脚IO的时钟及串口的时钟,本例用串口1做485,开启GPIOA的时钟,及USART1时钟。 参考代码:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


2.配置 CS引脚

 RS485需要设置CS脚来控制收发模式;

#define  RS485_CS_PIN          GPIO_Pin_4 // 485  CS--PA4

#define CS_485_TX  GPIO_ResetBits(GPIOA, RS485_CS_PIN) #define  CS_485_RX  GPIO_SetBits(GPIOA, RS485_CS_PIN)  

GPIO_InitTypeDef    GPIO_InitStructure;

      GPIO_InitStructure.GPIO_Pin =  RS485_CS_PIN ;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

      GPIO_Init(GPIOA, &GPIO_InitStructure);

初始USART1配置

需要跟电表485通讯方式一致;电表为半双口通讯方式,波特率:1200bps。

通讯字节格式:每字节含8位二进制码,传输时加上一个起始位(0)、一个偶校验位和一个停止位(1)共11;配置如下:

USART_InitTypeDef USART_InitStructure;

 USART_InitStructure.USART_BaudRate = 1200;

      USART_InitStructure.USART_WordLength = USART_WordLength_9b;

      USART_InitStructure.USART_StopBits = USART_StopBits_1;

      USART_InitStructure.USART_Parity =USART_Parity_Even;

      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1, &USART_InitStructure);

注:

在STM32中WordLength需要包含数据位数和奇偶校验的位数;

如果需要8位数据,无奇偶校验,则WordLength=8;

如果需要8位数据,有奇偶校验,则WordLength=9;(电表需要偶校验所以WordLength配为9)

 

3、发送数据

485是半双工(发时不能收,收时不能发)工作模式,在485通信中,收发是通过CS脚来控制切换R/D高低电平来实现的,通过了解基本的RS485电路,R/D为低电平时,发送禁止,接收有效,R/D为高电平时,则发送有效,接收截止;所以发送数据时,需要先配置成可发送的状态,数据发送完后,再切换成接收状态;

 

u16 Uart_E_Meter_Write_data(u8 *odata,u16 odatalen)

{

         

    CS_485_TX ; //设置为发送模式

    

      for(u8 i=0;i<4;i++)

    {

 

         USART_SendData(CMU_E_METER_USART_PORT, 0xfe);

         while(USART_GetFlagStatus(CMU_E_METER_USART_PORT, USART_FLAG_TXE) == RESET );

 

    }

    

       while(odatalen--)

    {

                 USART_SendData(CMU_E_METER_USART_PORT, *odata++);

         while(USART_GetFlagStatus(CMU_E_METER_USART_PORT, USART_FLAG_TXE) == RESET );

 

    }

      delay_ms(20); //跟据芯片做调整

      CS_485_RX ;//发送完设置为接收模式

      

    return 0;

}

 

4、数据编码函数

*功能描述: 数据编码成dtl645格式 返回包长度

*返回值  :  dtl645包长度

*参数    :  *meter_id电表ID,*src控制码+长度+DATA , srcLenth src长度,*dst 返回数据包

u16 Eleout_Encode(u8 *meter_id, u8 *src, u8 srcLenth, u8 *dst)

{

    u8 i = 0, prt = 0;

    u8 CHK = 0;

    u16 packlen = srcLenth + 10;

    

    dst[prt++] = 0x68;                    /*STX*/

    memcpy((u8 *)&dst[prt], (u8 *)meter_id, 6);

    prt += 6;

    dst[prt++] = 0x68;           /*STX*/

    dst[prt++] = src[i++];                      /*控制码*/

    dst[prt++] = src[i++];                      /*数据域长度*/

    

    for( ; i < srcLenth; i++)               /*DATA*/

    {    

        dst[prt++] = src[i] + 0x33;           /*加33H处理*/

    }

 

    for(i = 0; i < packlen - 2; i++)

    {

        CHK += dst[i];                           /*CHK*/

    }

    

    dst[prt++] = CHK;            /*CHK*/

    

    dst[prt++] = 0x16;              /*ETX*/

 

    return packlen;

}

5、参考本例程下载

https://download.csdn.net/download/flyme2010/10607580

  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32的AD电量采集是通过ADC模块实现的。根据STM32的数据手册上的ADC章节,参考电压Vref是已经接到Vadd引脚上面的,通常情况下,AD采集到的电量值是实际电池电压的1/2分压。以12位AD为例,测得电压值可以通过测得值除以4096再乘以参考电压来计算。而实际电压值则是测得电压值乘以2,这里的2是采样电路的分压比。\[1\] STM32的ADC是12位逐次逼近型的模拟数字转换器,具有18个通道,可以测量16个外部和2个内部信号源。ADC的转换可以单次、连续、扫描或间断模式执行,结果可以左对齐或右对齐方式存储在16位数据寄存器中。最大的转换速率为1MHz,转换时间为1us。需要注意的是,不要让ADC的时钟超过14M,否则会导致结果准确度下降。\[2\] 在进行AD电量采集之前,需要给ADC上电。通过设置ADC_CR2寄存器的ADON位可以给ADC上电。当第一次设置ADON位时,它将ADC从断电状态下唤醒。在上电延迟一段时间后,再次设置ADON位时开始进行转换。通过清除ADON位可以停止转换,并将ADC置于断电模式,此时ADC几乎不耗电。\[3\] #### 引用[.reference_title] - *1* [STM32HAL库ADC采集电池剩余电量](https://blog.csdn.net/qq_35547767/article/details/83783179)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [STM32F103_ADC电压采集](https://blog.csdn.net/weixin_44636409/article/details/118678500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值