[3]rt-thread-nano agile_modbus主机例程

gitee代码:

https://gitee.com/xuwenqiang_1989/rt-thread-nano

简介

移植agile_modbus,演示主机程序。

串口:UART4

过程:每隔3秒,读取从机1的10个位数据和10个寄存器数据,将位数据取反,寄存器数据+1后,再发送返回从机。

1.下载agile_modbus包

agile_modbus作者博客:http://github.loogg.cn/agile_packages/agile_modbus/#_1-3%E3%80%81%E8%AE%B8%E5%8F%AF%E8%AF%81

agile_modbus github下载地址:https://github.com/loogg/agile_modbus

下载后,把agile_modbus放入工程

2.工程配置

将agile_modbus/src内的C文件添加进工程

将agile_modbus/inc内的头文件包含进目录

新建模块modbus_poll.c和modbus_poll.h用于演示主机程序,并用同方法添加进工程

3.在Cubemx中配置UART4

开启UART4,配置波特率,数据等参数

配置UART4所用引脚

配置UART4   DMA接收

开启UART4中断,取消生成IRQ函数(我们自己编写)。

开启DMA接收中断,取消生成IRQ函数。

生成代码

4.modbus_poll.h

modbus_poll.h程序入下图

#ifndef __MODBUS_POLL_H_
#define __MODBUS_POLL_H_

#include "main.h"
#include "board.h"

#include "agile_modbus.h"

int modbus_poll_init(void);

#endif /*__MODBUS_H_*/

5.modbus_poll.c

包含头文件

#include "modbus_poll.h"

声明和定义接收和发送缓冲区

#define UART_PORT huart4                               // 串口
#define UART_REC_MAX_SIZE AGILE_MODBUS_MAX_ADU_LENGTH  // 接收缓冲大小
#define UART_SEND_MAX_SIZE AGILE_MODBUS_MAX_ADU_LENGTH // 发送缓冲大小
static uint8_t rx_buff[UART_REC_MAX_SIZE];             // 接收缓冲区
static uint32_t rx_size;                               // 接收数据长度
static uint8_t tx_buff[UART_SEND_MAX_SIZE];            // 发送缓冲区

定义agile_modbus需要的变量

static uint16_t hold_reg[10];               // 数据寄存器
static uint8_t coil_reg[10];                // 位寄存器
static agile_modbus_rtu_t ctx_rtu;          // rtu结构体
static agile_modbus_t *ctx = &ctx_rtu._ctx; // modbus 结构体

定义接收用信号量,线程句柄。

声明数据发送函数,数据接收函数,线程入口函数。

static rt_sem_t usart_rec_sem = RT_NULL; // 接收信号量

static int modbus_usart_read(rt_int32_t time);                                // 数据发送
static void modbus_usart_send(uint8_t *buff, uint32_t size, rt_int32_t time); // 数据接收

static rt_thread_t modbus_thread = RT_NULL;       // 线程句柄
static void modbus_thread_entry(void *parameter); // 线程入口

modbus_poll.c完整代码:

/* agile_modbus rtu poll sample*/
/* agile modbus rtu 主机程序*/
/* 2023-12-30*/
/* by Qaaa*/

#include "modbus_poll.h"

#define UART_PORT huart4                               // 串口
#define UART_REC_MAX_SIZE AGILE_MODBUS_MAX_ADU_LENGTH  // 接收缓冲大小
#define UART_SEND_MAX_SIZE AGILE_MODBUS_MAX_ADU_LENGTH // 发送缓冲大小
static uint8_t rx_buff[UART_REC_MAX_SIZE];             // 接收缓冲区
static uint32_t rx_size;                               // 接收数据长度
static uint8_t tx_buff[UART_SEND_MAX_SIZE];            // 发送缓冲区

static uint16_t hold_reg[10];               // 数据寄存器
static uint8_t coil_reg[10];                // 位寄存器
static agile_modbus_rtu_t ctx_rtu;          // rtu结构体
static agile_modbus_t *ctx = &ctx_rtu._ctx; // modbus 结构体

static rt_sem_t usart_rec_sem = RT_NULL; // 接收信号量

static int modbus_usart_read(rt_int32_t time);                                // 数据发送
static void modbus_usart_send(uint8_t *buff, uint32_t size, rt_int32_t time); // 数据接收

static rt_thread_t modbus_thread = RT_NULL;       // 线程句柄
static void modbus_thread_entry(void *parameter); // 线程入口

/* modbus 初始化*/
int modbus_poll_init(void)
{
    usart_rec_sem = rt_sem_create("usart_sem",
                                  0,
                                  RT_IPC_FLAG_FIFO);              // 创建接收信号量
    __HAL_UART_CLEAR_IDLEFLAG(&UART_PORT);                        // 清除接收空闲中断标志
    __HAL_UART_ENABLE_IT(&UART_PORT, UART_IT_IDLE);               // 使能接收空闲中断
    HAL_UART_Receive_DMA(&UART_PORT, rx_buff, UART_REC_MAX_SIZE); // 开启DMA接收

    // agile_modbus init
    modbus_thread = rt_thread_create("modbus_thread",
                                     modbus_thread_entry,
                                     RT_NULL,
                                     1024,
                                     4,
                                     20); // 创建任务线程
    if (modbus_thread != RT_NULL)
        rt_thread_startup(modbus_thread); // 启动线程
    else
        return -1;

    return 0;
}

/* 任务线程入口函数*/
static void modbus_thread_entry(void *parameter)
{
    agile_modbus_rtu_init(&ctx_rtu, tx_buff, sizeof(tx_buff), rx_buff, sizeof(rx_buff)); // rtu初始化
    agile_modbus_set_slave(ctx, 1);                                                      // 设置地址
    while (1)
    {
        rt_thread_mdelay(3000); // 每次主机读取间隔

        /*hold reg 数据寄存器读取*/
        int send_len = agile_modbus_serialize_read_registers(ctx, 0, 10); // 格式化读取数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                  // 发送读取数据
        int read_len = modbus_usart_read(1000);                           // 等待slave返回数据
        if (read_len == 0)                                                // 读取超时
        {
            rt_kprintf("read hold reg timout\n");
            continue; // 继续下次循环
        }

        int rc = agile_modbus_deserialize_read_registers(ctx, read_len, hold_reg); // 将收到的salve数据格式化进数据缓冲
        if (rc < 0)                                                                // 格式化失败
        {
            rt_kprintf("read hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }

        rt_kprintf("hold reg:\n"); // 打印收到的数据
        for (int i = 0; i < 10; i++)
        {
            rt_kprintf("hold_reg[%d]:0x%04x\n", i, hold_reg[i]);
        }

        /* 写入寄存器数据*/
        for (int i = 0; i < 10; i++)
        {
            hold_reg[i]++;
        }
        send_len = agile_modbus_serialize_write_registers(ctx, 0, 10, hold_reg); // 格式化写入数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                         // 串口发送
        read_len = modbus_usart_read(1000);                                      // 等待从机返回数据
        if (read_len == 0)                                                       // 读取超时
        {
            rt_kprintf("write hold reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_write_registers(ctx, 10); // 检查从机应答数据
        if (rc < 0)
        {
            rt_kprintf("write hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }
        rt_kprintf("write hold reg success\n");
        rt_kprintf("\r\n\r\n\r\n");

        /*coil reg 位读取*/
        send_len = agile_modbus_serialize_read_bits(ctx, 0, 10);
        modbus_usart_send(ctx->send_buf, send_len, 100);
        read_len = modbus_usart_read(1000);
        if (read_len == 0)
        {
            rt_kprintf("read coil reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_read_bits(ctx, read_len, coil_reg);
        if (rc < 0)
        {
            rt_kprintf("read coil reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue;
        }

        rt_kprintf("coil reg:\n");
        for (int i = 0; i < 10; i++)
        {
            rt_kprintf("coil_reg[%d]:%d\n", i, coil_reg[i]);
        }

        /* 写入位数据*/
        for (int i = 0; i < 10; i++)
        {
            coil_reg[i] ^= 1;
        }
        send_len = agile_modbus_serialize_write_bits(ctx, 0, 10, coil_reg); // 格式化写入数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                    // 串口发送
        read_len = modbus_usart_read(1000);                                 // 等待从机返回数据
        if (read_len == 0)                                                  // 读取超时
        {
            rt_kprintf("write coil reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_write_bits(ctx, 10); // 检查从机应答数据
        if (rc < 0)
        {
            rt_kprintf("write coil reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }
        rt_kprintf("write coil reg success\n");
        rt_kprintf("\r\n\r\n\r\n");
    }
}

/* 串口读取*/
/* int: 数据帧长度 */
/* time: 等待数据时间*/
static int modbus_usart_read(rt_int32_t time)
{
    rt_err_t uwRet = RT_EOK;
    uwRet = rt_sem_take(usart_rec_sem, time); // 获取接收空闲中断信号量
    if (uwRet == RT_EOK)                      // 收到数据帧,返回数据帧长度,数据在rx_buff内
    {
        return rx_size;
    }

    return 0;
}

/* 串口发送*/
/* *buff:待发送数据缓冲指针*/
/* size:待发送数据长度*/
/* time: 发送超时时间*/
static void modbus_usart_send(uint8_t *buff, uint32_t size, rt_int32_t time)
{
    if ((buff == NULL) || (size == 0U))
    {
        return;
    }
    HAL_UART_Transmit(&UART_PORT, buff, size, time);
}

/* 串口中断函数*/
void UART4_IRQHandler(void)
{
    uint32_t tmp;

    if (__HAL_UART_GET_FLAG(&UART_PORT, UART_FLAG_IDLE) != RESET) // 检测接收空闲中断是否挂起
    {
        __HAL_UART_CLEAR_IDLEFLAG(&UART_PORT); // 清除空闲中断标志
        tmp = UART_PORT.Instance->ISR;         // 根据手册清除空闲中断标志操作
        tmp = UART_PORT.Instance->RDR;
        tmp++;
        HAL_UART_DMAStop(&UART_PORT);                                          // 停止DMA接收
        rx_size = UART_REC_MAX_SIZE - __HAL_DMA_GET_COUNTER(UART_PORT.hdmarx); // 计算接收到的数据长度
        rt_sem_release(usart_rec_sem);                                         // 释放接收信号量
        HAL_UART_Receive_DMA(&UART_PORT, rx_buff, UART_REC_MAX_SIZE);          // 重新开启DMA接收
    }
}

5.1 modbus初始化函数

1.创建DMA接收用信号量 usart_sem

2.使能接收空闲中断 UART_IT_IDLE

3.开启DMA接收

4.创建modbus_poll线程

5.启动modbus_poll线程

/* modbus 初始化*/
int modbus_poll_init(void)
{
    usart_rec_sem = rt_sem_create("usart_sem",
                                  0,
                                  RT_IPC_FLAG_FIFO);              // 创建接收信号量
    __HAL_UART_CLEAR_IDLEFLAG(&UART_PORT);                        // 清除接收空闲中断标志
    __HAL_UART_ENABLE_IT(&UART_PORT, UART_IT_IDLE);               // 使能接收空闲中断
    HAL_UART_Receive_DMA(&UART_PORT, rx_buff, UART_REC_MAX_SIZE); // 开启DMA接收

    // agile_modbus init
    modbus_thread = rt_thread_create("modbus_thread",
                                     modbus_thread_entry,
                                     RT_NULL,
                                     1024,
                                     4,
                                     20); // 创建任务线程
    if (modbus_thread != RT_NULL)
        rt_thread_startup(modbus_thread); // 启动线程
    else
        return -1;

    return 0;
}

5.2 串口接收中断处理

1.串口进入空闲中断,说明数据桢接收完毕。

2.清除空闲中断。

3.停止串口DMA,停止接收新数据。

4.计算接收到的数据帧长度,写入rx_size。

5.释放信号量uart_rec_sem。

6.重新启动DMA接收。

/* 串口中断函数*/
void UART4_IRQHandler(void)
{
    uint32_t tmp;

    if (__HAL_UART_GET_FLAG(&UART_PORT, UART_FLAG_IDLE) != RESET) // 检测接收空闲中断是否挂起
    {
        __HAL_UART_CLEAR_IDLEFLAG(&UART_PORT); // 清除空闲中断标志
        tmp = UART_PORT.Instance->ISR;         // 根据手册清除空闲中断标志操作
        tmp = UART_PORT.Instance->RDR;
        tmp++;
        HAL_UART_DMAStop(&UART_PORT);                                          // 停止DMA接收
        rx_size = UART_REC_MAX_SIZE - __HAL_DMA_GET_COUNTER(UART_PORT.hdmarx); // 计算接收到的数据长度
        rt_sem_release(usart_rec_sem);                                         // 释放接收信号量
        HAL_UART_Receive_DMA(&UART_PORT, rx_buff, UART_REC_MAX_SIZE);          // 重新开启DMA接收
    }
}

5.3 串口数据读取

1.获取接收信号量usart_rec_sem。(数据帧接收完毕,在中断中释放)。

2.成功获取,返回接收数据帧长度。(数据在缓冲rx_buff中)。

/* 串口读取*/
/* int: 数据帧长度 */
/* time: 等待数据时间*/
static int modbus_usart_read(rt_int32_t time)
{
    rt_err_t uwRet = RT_EOK;
    uwRet = rt_sem_take(usart_rec_sem, time); // 获取接收空闲中断信号量
    if (uwRet == RT_EOK)                      // 收到数据帧,返回数据帧长度,数据在rx_buff内
    {
        return rx_size;
    }

    return 0;
}

5.4 串口数据发送

用HAL库发送数据。

/* 串口发送*/
/* *buff:待发送数据缓冲指针*/
/* size:待发送数据长度*/
/* time: 发送超时时间*/
static void modbus_usart_send(uint8_t *buff, uint32_t size, rt_int32_t time)
{
    if ((buff == NULL) || (size == 0U))
    {
        return;
    }
    HAL_UART_Transmit(&UART_PORT, buff, size, time);
}

5.4 modbus线程处理 

1.agile_modbus RTU模式初始化,配置接收和发送缓冲。

2.设置modbus地址为1。

    agile_modbus_rtu_init(&ctx_rtu, tx_buff, sizeof(tx_buff), rx_buff, sizeof(rx_buff)); // rtu初始化
    agile_modbus_set_slave(ctx, 1);                                                      // 设置地址

 1.格式化读取从机寄存器需要发送的数据帧格式。

2.发送读取从机寄存器的数据帧。

3.等待从机答复。

        /*hold reg 数据寄存器读取*/
        int send_len = agile_modbus_serialize_read_registers(ctx, 0, 10); // 格式化读取数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                  // 发送读取数据
        int read_len = modbus_usart_read(1000);                           // 等待slave返回数据
        if (read_len == 0)                                                // 读取超时
        {
            rt_kprintf("read hold reg timout\n");
            continue; // 继续下次循环
        }

1.将收到从机的答复数据帧,反格式化写入到保存数据中。

2.打印收到的数据。

        int rc = agile_modbus_deserialize_read_registers(ctx, read_len, hold_reg); // 将收到的salve数据格式化进数据缓冲
        if (rc < 0)                                                                // 格式化失败
        {
            rt_kprintf("read hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }

        rt_kprintf("hold reg:\n"); // 打印收到的数据
        for (int i = 0; i < 10; i++)
        {
            rt_kprintf("hold_reg[%d]:0x%04x\n", i, hold_reg[i]);
        }

 1.将收到的从机寄存器数据+1。

2.格式化写入从机寄存器数据帧格式。

3.发送写入从机寄存器数据帧。

4.等待从机应答。

5.检查从机应答。

6.写入从机寄存器成功,打印写入寄存器成功信息。

        /* 写入寄存器数据*/
        for (int i = 0; i < 10; i++)
        {
            hold_reg[i]++;
        }
        send_len = agile_modbus_serialize_write_registers(ctx, 0, 10, hold_reg); // 格式化写入数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                         // 串口发送
        read_len = modbus_usart_read(1000);                                      // 等待从机返回数据
        if (read_len == 0)                                                       // 读取超时
        {
            rt_kprintf("write hold reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_write_registers(ctx, 10); // 检查从机应答数据
        if (rc < 0)
        {
            rt_kprintf("write hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }
        rt_kprintf("write hold reg success\n");
        rt_kprintf("\r\n\r\n\r\n");

 位数据的读取和写入,同寄存器操作。

附上完整线程代码:

/* 任务线程入口函数*/
static void modbus_thread_entry(void *parameter)
{
    agile_modbus_rtu_init(&ctx_rtu, tx_buff, sizeof(tx_buff), rx_buff, sizeof(rx_buff)); // rtu初始化
    agile_modbus_set_slave(ctx, 1);                                                      // 设置地址
    while (1)
    {
        rt_thread_mdelay(3000); // 每次主机读取间隔

        /*hold reg 数据寄存器读取*/
        int send_len = agile_modbus_serialize_read_registers(ctx, 0, 10); // 格式化读取数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                  // 发送读取数据
        int read_len = modbus_usart_read(1000);                           // 等待slave返回数据
        if (read_len == 0)                                                // 读取超时
        {
            rt_kprintf("read hold reg timout\n");
            continue; // 继续下次循环
        }

        int rc = agile_modbus_deserialize_read_registers(ctx, read_len, hold_reg); // 将收到的salve数据格式化进数据缓冲
        if (rc < 0)                                                                // 格式化失败
        {
            rt_kprintf("read hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }

        rt_kprintf("hold reg:\n"); // 打印收到的数据
        for (int i = 0; i < 10; i++)
        {
            rt_kprintf("hold_reg[%d]:0x%04x\n", i, hold_reg[i]);
        }

        /* 写入寄存器数据*/
        for (int i = 0; i < 10; i++)
        {
            hold_reg[i]++;
        }
        send_len = agile_modbus_serialize_write_registers(ctx, 0, 10, hold_reg); // 格式化写入数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                         // 串口发送
        read_len = modbus_usart_read(1000);                                      // 等待从机返回数据
        if (read_len == 0)                                                       // 读取超时
        {
            rt_kprintf("write hold reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_write_registers(ctx, 10); // 检查从机应答数据
        if (rc < 0)
        {
            rt_kprintf("write hold reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }
        rt_kprintf("write hold reg success\n");
        rt_kprintf("\r\n\r\n\r\n");

        /*coil reg 位读取*/
        send_len = agile_modbus_serialize_read_bits(ctx, 0, 10);
        modbus_usart_send(ctx->send_buf, send_len, 100);
        read_len = modbus_usart_read(1000);
        if (read_len == 0)
        {
            rt_kprintf("read coil reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_read_bits(ctx, read_len, coil_reg);
        if (rc < 0)
        {
            rt_kprintf("read coil reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue;
        }

        rt_kprintf("coil reg:\n");
        for (int i = 0; i < 10; i++)
        {
            rt_kprintf("coil_reg[%d]:%d\n", i, coil_reg[i]);
        }

        /* 写入位数据*/
        for (int i = 0; i < 10; i++)
        {
            coil_reg[i] ^= 1;
        }
        send_len = agile_modbus_serialize_write_bits(ctx, 0, 10, coil_reg); // 格式化写入数据的发送内容
        modbus_usart_send(ctx->send_buf, send_len, 100);                    // 串口发送
        read_len = modbus_usart_read(1000);                                 // 等待从机返回数据
        if (read_len == 0)                                                  // 读取超时
        {
            rt_kprintf("write coil reg timout\n");
            continue;
        }

        rc = agile_modbus_deserialize_write_bits(ctx, 10); // 检查从机应答数据
        if (rc < 0)
        {
            rt_kprintf("write coil reg failed\n");
            if (rc != -1)
                rt_kprintf("error code:%d", -128 - rc);
            continue; // 继续下次循环
        }
        rt_kprintf("write coil reg success\n");
        rt_kprintf("\r\n\r\n\r\n");
    }
}

6.演示

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RT-Thread诞生于2006年,是一款以开源、中立、社区化发展起来的物联网操作系统。 RT-Thread主要采用 C 语言编写,浅显易懂,且具有方便移植的特性(可快速移植到多种主流 MCU 及模组芯片上)。RT-Thread把面向对象的设计方法应用到实时系统设计中,使得代码风格优雅、架构清晰、系统模块化并且可裁剪性非常好。 RT-Thread有完整版和Nano版,对于资源受限的微控制器(MCU)系统,可通过简单易用的工具,裁剪出仅需要 3KB Flash、1.2KB RAM 内存资源的 NANO 内核版本;而相对资源丰富的物联网设备,可使用RT-Thread完整版,通过在线的软件包管理工具,配合系统配置工具实现直观快速的模块化裁剪,并且可以无缝地导入丰富的软件功能包,实现类似 Android 的图形界面及触摸滑动效果、智能语音交互效果等复杂功能。 RT-Thread架构 RT-Thread是一个集实时操作系统(RTOS)内核、中间件组件的物联网操作系统,架构如下: 内核层:RT-Thread内核,是 RT-Thread的核心部分,包括了内核系统中对象的实现,例如多线程及其调度、信号量、邮箱、消息队列、内存管理、定时器等;libcpu/BSP(芯片移植相关文件 / 板级支持包)与硬件密切相关,由外设驱动和 CPU 移植构成。 组件与服务层:组件是基于 RT-Thread内核之上的上层软件,例如虚拟文件系统、FinSH命令行界面、网络框架、设备框架等。采用模块化设计,做到组件内部高内聚,组件之间低耦合。 RT-Thread软件包:运行于 RT-Thread物联网操作系统平台上,面向不同应用领域的通用软件组件,由描述信息、源代码或库文件组成。RT-Thread提供了开放的软件包平台,这里存放了官方提供或开发者提供的软件包,该平台为开发者提供了众多可重用软件包的选择,这也是 RT-Thread生态的重要组成部分。软件包生态对于一个操作系统的选择至关重要,因为这些软件包具有很强的可重用性,模块化程度很高,极大的方便应用开发者在最短时间内,打造出自己想要的系统。RT-Thread已经支持的软件包数量已经达到 180+。 RT-Thread的特点: 资源占用极低,超低功耗设计,最小内核(Nano版本)仅需1.2KB RAM,3KB Flash。 组件丰富,繁荣发展的软件包生态 。 简单易用 ,优雅的代码风格,易于阅读、掌握。 高度可伸缩,优质的可伸缩的软件架构,松耦合,模块化,易于裁剪和扩展。 强大,支持高性能应用。 跨平台、芯片支持广泛。
RT-Thread作品秀】通用型数据采集设备作者:鱼柯 概述(说明应用产生的背景、实现功能)在一些低频采集设备中,典型的运行策略是,采集数据,上传数据,关闭外设进入睡眠状态;但是,在运行过程中,需要根据实际需求,更改采集频率,连接不同的设备,如果每次通过修改代码解决,通用性就很难保证,这个项目将一些uart型的传感器进行归类,通过文件设置数据交互过程中的命令,解析方式等,可以适配大多数的uart型传感器;同时,对一些网络摄像头也以同样的方式进行处理; 实现数据采集调度配置,数据采集,数据上传,图片采集,图片上传, 配置文件解析,固件远程更新;由于contab配置文件中的event使用的是MSH_CMD_EXPRT宏导出的命令。所以,它也支持系统需要定时执行的相对时间间隔需要变化的任务,比如:12:00. 13:10, 15:35, 18:23分别执行一次任务; 开发环境(所采用的软、硬件方案)硬件:art-pi, INDUSTRY-IO, 微气象仪, 网络摄像头 RT-Thread版本:rt-thread 4.0.3 开发工具及版本:ubuntu 18.04,gcc-arm-none-eabi-6_2-2016q4,scons v3.0.1,python 3.6.9,pkgs RT-Thread使用情况概述(简要总结下应用中RT-Thread使用情况:内核部分、组件部分、软件包部分、内核、其他)内核部分Inter-thread communication Event Semaphore mutex memory management device object 组件部分Finsh DFS (device virtual file system) serial device, mtd nor flash device, gpio device, ntp rtc device, sd/mmc device, spi device, serial flash universal driver (device driver) posix layer and c stand library SAL (socket abstraction layer) ping, ifconfig, netstat, netdev (network interface) LwIP 2.0.2 Ymodem ulog 软件包部分agile_console-v1.0.0 fal-v0.5.0 ota_downloader-v1.0.0 agile_telnet-v2.0.0 littlefs-v2.2.1 SignalLed-latest cJSON-v1.0.2 netutils-v1.2.0 vi-latest EasyFlash-v4.1.0 webclient-v2.1.1 硬件框架(概述应用所采用的硬件方案框图,并对核心部分做介绍)软件框架说明(介绍应用所采用的软件方案框图、流程图等,并加以解说)软件模块说明(介绍应用软件关键部分的逻辑、采用的实现方式等)类似 linux定时任务contab解析相关json配置文件,构建设备运行数据树: "contab": [{"event":"misc_check","time":"0 18"},{"event":"img_cap_start","time":"20 7,9,14"},{"event":"app_image_upload","time":"20 7,9,14"},{"event":"sensor_acq_start","time":"5,10,15,20,25,30,35,40,45,50,55 *"},{"event":"app_data_upload","time":"5,10,15,20,25,30,35,40,45,50,55 *"}] 事件执行分钟: 表示xx:5, xx:25, xx:30, xx:36, xx:45, xx:54 事件执行小时:*通配符,表示1-24小时 上面参数表示:每个小时的5,25,30,45,54分,执行img_upload_invl事件; 上传数据每次采集数据后,将数据存在本地一个缓存文件中,按照采集时间从前到后写入;同时会生成一个读取位置的缓存文件指示,下一次从哪个文件的那一行读取数据进行上传,上传成功后,更新读取位置的缓存;如20201217,227, 表示从文件20201217.txt的227个字符后读取一行数据进行上传,避免文件过大引起设备死机; 上传图片每次拍照时,将拍照成功的照片名及端口追加记录到一个缓存文件中,每次从缓存文件中,读取需要上传的图片构造form-data上传图片;如4,/sd/1608167012_4.jpg;如果上传成功,则删

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值