热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

phpdlt645,RTThreadMirror

DLT645采集软件包使用说明本软件包用于DLT645协议的采集与数据处理。在硬件层的移植(主要针对于串口收发数据)完成之后,用户仅需调用一个API即可完成针对于特定

DL/T 645 采集软件包使用说明

本软件包用于 DL/T 645 协议的采集与数据处理。在硬件层的移植(主要针对于串口收发数据)完成之后, 用户仅需调用一个API即可完成针对于特定协议(DL/T 1997 或 DL/T 2007)的标识符数据读取、处理与存储。 使用户无需关注请求数据的封包与接收数据的解包等复杂的协议内部操作,真正做到 一键采集 。

当然,由于本人精力有限,无法第一时间考虑并编写所有可能的情况与功能,所以在软件包的初期其功能只是根据我所用到的功能进行编写,无法涵盖所有的需求。并且可能会有一些小问题。但本文档今后会加入详细的功能开发指南,供开发成员们能够很方便地根据自己的需求进行功能的添加与修改。随着时间的推移,本软件包会逐步趋向于完善,也希望使用本软件包的开发人员们能够加入到软件包的完善中来,为该软件包的成长提供一份宝贵的力量!

目前支持的功能:

DL/T 645 1997 版数据采集与部分标识符数据解析

DL/T 645 2007 版数据采集与部分标识符数据解析

标识符的解析提供了便捷的接口,用户可以调用该接口实现自己所需标识符的解析功能

目前还不支持数据写入功能

一、软件包使用说明

在使用软件包之前, 需要把 src 目录下的所有源文件加入工程,将 inc 添加到头文件目录,并且参照 port 路径下的 dlt645_port.c 源文件实现基于用户使用的硬件平台的底层硬件操作的移植。scons现在默认不会将port文件加入到工程中,使用时需在工程的其他目录下手动加入。(详细的移植方法会在下文进行描述)

当完成硬件接口移植后,可以参照以下步骤进行对软件包的使用:

调用用户实现的硬件接口初始化用于DLT645采集的硬件,并注册645环境结构体。

调用 dlt645_set_addr() 函数设置需要采集的从机设备地址。(函数详细说明请阅读 API详解 )

调用 dlt645_read_data() 函数进行具体标识符数据的读取并存储到用户指定的地址下。(函数详细说明请阅读 API详解 )

二、软件包移植指南

软件包提供了完备的基于DL/T 645协议的数据包封包与解包操作,而用户则需要根据自己的平台给软件包提供底层数据的发送与接收接口,让软件包能够接收到数据并且成功发送出去。下面就来详细介绍一下软件包的移植操作。如文字描述有概念模糊或者不理解的地方可以参考本节下方的移植案例。

移植步骤

初始化用于dlt645协议通信的硬件。(如串口)

定义一个dlt645结构体作为dlt645通信的环境结构体。

实现数据发送与接收函数。(发送和接收单位为一个数据包)

将数据发送与接收函数注册到dlt645环境结构体中。

环境结构体:

环境结构体是本软件包运行时的内核对象,内核在工作中会调用其中的数据及接口,因此,用户提供的接口也需要注册到该结构体中。其结构如下:

typedef struct dlt645

{

uint8_t addr[6]; //从机地址

uint8_t debug; //调试标志

int (*write)(struct dlt645 *ctx, uint8_t *buf, uint16_t len); //底层写函数

int (*read) (struct dlt645 *ctx, uint8_t *msg, uint16_t len); //底层读函数

void *port_data; //移植层拓展接口

} dlt645_t;

成员

说明

addr

从机六位地址数组

debug

内核调试开关标志

write

硬件层写数据接口(用户提供)

read

硬件层读数据接口(用户提供)

port_data

用户拓展接口

数据发送接口:

接口格式:

int (*write)(struct dlt645 *ctx, uint8_t *buf, uint16_t len);

详细介绍:

在用户想要 读/写 从机设备时软件包内核需要调用该接口发送相应的指令帧,用户需要针对于自己的硬件平台来实现该函数。该函数会传入三个参数:

ctx: 为dlt645环境结构体;

buf: 为待发送的数据首地址;

len: 为要发送的长度。

数据接收接口:

接口格式:

int (*read) (struct dlt645 *ctx, uint8_t *msg, uint16_t len);

详细介绍:

当内核成功发送一个命令后,会立刻调用该接口进行从机设备回应数据的读取,调用时会传入三个参数:

ctx: 为dlt645环境结构体;

msg: 为接收到数据的存储地址;

len: 为允许接收数据的最大长度。

其中 len 参数标志着本次接收的最大长度,用户要注意对接收数据长度进行判断,若实际接收长度大于传入的允许接收数据最大长度,用户应该 视本次数据接收无效,返回0。

拓展接口

在 dlt645 结构体中提供了一个 port_data 成员字段,其类型为 void * ,用户可以利用此字段创建针对于自身应用的结构体,从而拓展更多的接口和数据字段,实现更为复杂的硬件操作。

移植案例

/*************************************************

Copyright (c) 2019

All rights reserved.

File name: dlt645_port.c

Description: DLT645 移植&使用例程文件

History:

1. Version:

Date: 2019-09-19

Author: wangjunjie

Modify:

*************************************************/

#include "dlt645.h"

#include "rtthread.h"

#include "drv_gpio.h"

//DLT645采集使用的串口名

#define DLT645_SERIAL_NAME "uart4"

//DL/T 645硬件拓展结构体

typedef struct

{

rt_sem_t dlt645_sem; //用于串口接收的信号量

uint32_t byte_timeout; //字节间的超时时间

} dlt645_port_t;

static dlt645_port_t dlt645_port = {

.dlt645_sem = RT_NULL,

.byte_timeout = 10, //接收字节间超时时间

};

//dlt645 采集设备句柄

static rt_device_t dlt645_device = RT_NULL;

//dlt645 采集接收信号量

static struct rt_semaphore dlt645_receive_sem;

//串口配置参数

struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;

//dlt645 环境结构体

dlt645_t dlt645;

//串口接收数据回调函数

rt_err_t uart_handler(rt_device_t dev, rt_size_t size)

{

//接收到一个数据释放信号量

rt_sem_release(&dlt645_receive_sem);

return RT_EOK;

}

/**

* Name: dlt645_hw_read

* Brief: dlt645 硬件层接收数据

* Input:

* @ctx: 645运行环境

* @msg: 接收数据存放地址

* @len: 数据最大接收长度

* Output: 读取数据的长度

*/

static int dlt645_hw_read(dlt645_t *ctx, uint8_t *msg ,uint16_t len)

{

//实际接收长度

int read_len = 0;

//清缓存变量

uint8_t buf = 0;

//清空缓存

while(rt_device_read(dlt645_device,0,&buf,1));

//等待串口接收到数据

if(rt_sem_take(&dlt645_receive_sem, 1000) == -RT_ETIMEOUT)

{

return 0;

}

//每次读取一个字节的数据

while (rt_device_read(dlt645_device, 0, msg + read_len, 1) == 1)

{

if(read_len > len)

{

return 0;

}

else

{

read_len ++;

}

//读取超时标志一帧数据读取完成

if (rt_sem_take(&dlt645_receive_sem, ((dlt645_port_t *)(ctx->port_data))->byte_timeout) == -RT_ETIMEOUT)

{

break;

}

}

return read_len;

}

/**

* Name: dlt645_hw_write

* Brief: dlt645 硬件层发送数据

* Input:

* @ctx: 645运行环境

* @buf: 待发送数据

* @len: 发送长度

* Output: 实际发送的字节数,错误返回-1

*/

static int dlt645_hw_write(dlt645_t *ctx, uint8_t *buf, uint16_t len)

{

//串口发送数据

return rt_device_write(dlt645_device,0,buf,len);

}

/**

* Name: dlt645_port_init

* Brief: 645采集硬件层初始化

* Input: None

* Output: None

*/

int dlt645_port_init(void)

{

//串口初始化

dlt645_device = rt_device_find(DLT645_SERIAL_NAME);

if (dlt645_device == RT_NULL)

{

rt_kprintf("cannot find device %s\r\n", DLT645_SERIAL_NAME);

return -RT_ERROR;

}

if (rt_device_open(dlt645_device, RT_DEVICE_FLAG_INT_RX) != RT_EOK)

{

rt_kprintf("cannot open device %s\r\n", DLT645_SERIAL_NAME);

return -RT_ERROR;

}

else

{

config.baud_rate = BAUD_RATE_9600;

config.data_bits = DATA_BITS_8;

config.stop_bits = STOP_BITS_1;

config.parity = PARITY_NONE;

/* 打开设备后才可修改串口配置参数 */

rt_device_control(dlt645_device, RT_DEVICE_CTRL_CONFIG, &config);

rt_kprintf("device %s open success\r\n", DLT645_SERIAL_NAME);

}

//信号量初始化

if (rt_sem_init(&dlt645_receive_sem, "receive_sem", 0, RT_IPC_FLAG_FIFO) == RT_EOK)

{

dlt645_port.dlt645_sem = &dlt645_receive_sem;

}

else

{

return -RT_ERROR;

}

//设置串口接收回调函数

rt_device_set_rx_indicate(dlt645_device, uart_handler);

//485控制引脚初始化

rt_pin_mode(GET_PIN(A,15),PIN_MODE_OUTPUT);

return RT_EOK;

}

//645结构体注册

static dlt645_t dlt645 = {

{0},

0,

dlt645_hw_write,

dlt645_hw_read,

(void *)&dlt645_port};

三、API详解

1、设置从机地址

简介: 用户在通过645协议读取某设备的数据时,首先要通过该接口设置想要读取的从机的地址。

API格式:

void dlt645_set_addr(dlt645_t *ctx, uint8_t *addr);

参数:

参数名

介绍

ctx

645结构句柄

addr

6位地址数组

使用示例

//dlt645 环境结构体

extern dlt645_t dlt645;

//从机地址为111

uint8_t slave_addr[6] = {0x00,0x00,0x00,0x00,0x01,0x11};

dlt645_set_addr(&dlt645,slave_addr);

2、读取数据

简介: 用户通过调用该接口读取从机指定标识符的数据

API格式:

int dlt645_read_data(dlt645_t *ctx, uint32_t code, uint8_t *read_data, dlt645_protocal protocal);

参数:

参数名

描述

ctx

645结构句柄

code

标识符

read_data

读取数据的存储地址(注意地址长度为4字节)

protocal

指定协议类型(可选 DLT645_2007 或 DLT645_1997 )

返回值

描述

整数

读取数据长度

-1

读取失败

read_data 参数为读取数据的存储地址,目前的版本中将所有的数据都转换为浮点数保存,(尚不支持超过4字节大小的数据,若有需要可以修改内核)因此 read_data 大小必须为4字节。后续版本会进行修改,从而支持任意大小。

protocal 参数指定了读取的协议类型,可选值为:DLT645_1997 和 DLT645_2007 ,分别对应1997版与2007版。

使用示例

//dlt645 环境结构体

extern dlt645_t dlt645;

//dlt645 采集测试标识符 (A相电压)

#define DLT645_2007_READ_TEST_CODE 0x02010100

//用于存放读取数据的数组

uint8_t read_buf[4];

//读取数据

if (dlt645_read_data(&dlt645,DLT645_2007_READ_TEST_CODE,read_buf,DLT645_2007) > 0)

{

printf("读取成功,A相电压值为: %.2f\r\n",*(float *)read_buf);

}

else

{

rt_kprintf("读取失败\r\n");

}

四、使用案例

/*************************************************

Copyright (c) 2019

All rights reserved.

File name: sample.c

Description: DLT645 软件包使用样例

History:

1. Version:

Date: 2019-09-23

Author: wangjunjie

Modify:

*************************************************/

#include "dlt645.h"

#include "dlt645_port.h"

//dlt645 采集测试标识符 (A相电压)

#define DLT645_2007_READ_TEST_CODE 0x02010100

#define DLT645_1997_READ_TEST_CODE 0xB611

uint8_t test_addr[6] = {0x00,0x00,0x00,0x00,0x00,0x01};

/**

* Name: dlt645_read_test

* Brief: dlt645协议采集测试程序

* Input: None

* Output: None

*/

static void dlt645_read_test(void)

{

uint8_t read_buf[4];

rt_memset(read_buf, 0, 4);

//设置从机地址

dlt645_set_addr(&dlt645,test_addr);

//if(dlt645_read_data(&dlt645,DLT645_1997_READ_TEST_CODE,read_buf,DLT645_1997) > 0) //1997采集测试

if(dlt645_read_data(&dlt645,DLT645_2007_READ_TEST_CODE,read_buf,DLT645_2007) > 0) //2007采集测试

{

printf("读取成功,A相电压值为: %.2f\r\n",*(float *)read_buf);

}

else

{

rt_kprintf("读取失败\r\n");

}

}

/**

* Name: main

* Brief: 主函数

* Input: None

* Output: None

*/

int main(void)

{

//dlt645 硬件层初始化

dlt645_port_init();

while(1)

{

//采集测试

dlt645_read_test();

rt_thread_mdelay(1000);

}

}



推荐阅读
  • 本文详细介绍了在Luat OS中如何实现C与Lua的混合编程,包括在C环境中运行Lua脚本、封装可被Lua调用的C语言库,以及C与Lua之间的数据交互方法。 ... [详细]
  • 想把一组chara[4096]的数组拷贝到shortb[6][256]中,尝试过用循环移位的方式,还用中间变量shortc[2048]的方式。得出的结论:1.移位方式效率最低2. ... [详细]
  • 1、编写一个Java程序在屏幕上输出“你好!”。programmenameHelloworld.javapublicclassHelloworld{publicst ... [详细]
  • 本文详细介绍如何安装和配置DedeCMS的移动端站点,包括新版本安装、老版本升级、模板适配以及必要的代码修改,以确保移动站点的正常运行。 ... [详细]
  • 使用Matlab创建动态GIF动画
    动态GIF图可以有效增强数据表达的直观性和吸引力。本文将详细介绍如何利用Matlab软件生成动态GIF图,涵盖基本代码实现与高级应用技巧。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • 本文探讨了异步编程的发展历程,从最初的AJAX异步回调到现代的Promise、Generator+Co以及Async/Await等技术。文章详细分析了Promise的工作原理及其源码实现,帮助开发者更好地理解和使用这一重要工具。 ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • binlog2sql,你该知道的数据恢复工具
    binlog2sql,你该知道的数据恢复工具 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • 深入解析 C++ 中的 String 和 Vector
    本文详细介绍了 C++ 编程语言中 String 和 Vector 的使用方法及特性,旨在帮助开发者更好地理解和应用这两个重要的容器。 ... [详细]
  • 本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ... [详细]
  • 本文详细介绍如何在 Apache 中设置虚拟主机,包括基本配置和高级设置,帮助用户更好地理解和使用虚拟主机功能。 ... [详细]
  • Hanks博士是一位著名的生物技术专家,他的儿子Hankson对数学有着浓厚的兴趣。最近,Hankson遇到了一个有趣的数学问题,涉及求解特定条件下的正整数x,而不使用传统的辗转相除法。 ... [详细]
  • 本文深入探讨了动态赋值的概念及其在编程实践中的应用,特别是通过Java代码示例来展示如何利用循环结构动态地为数组分配值。 ... [详细]
author-avatar
网吧b国漫救星
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有