关于modbus与HMI车载侧屏通信的错误机制处理

news2024/10/21 12:20:27

目录

1.关于6个人机交互功能按钮逻辑图设计

2.错误处理机制


1.关于6个人机交互功能按钮逻辑图设计

        初次的设计想法是按钮亮表示大家能按,但要是想在按一次,发送有效数据,就得先按亮,在按灭。这里以上料区为例,其它区域同理。

2.错误处理机制

        代码部分逻辑如下,得到过大师的指点,这部分的逻辑写的杠杆滴~

//线程1的入口函数,处理数据的线程函数,负责将解析json的数组写入寄存器
#define MAX_CONNECT_ATTEMPTS 6
void* processDataWrapper(void* arg) {
    #if HMI_INFO   //HMI_INFO控制是否打印日志信息到当前目录
        // 设置日志文件名
        hlog_set_file("hmi_info.log");
        // 设置日志格式
        hlog_set_format("[hmi_info] %y-%m-%d %H:%M:%S.%z %L %s");
        // 启用日志颜色(如果支持)
        logger_enable_color(hlog, 1);
    #endif
    hmi_info_log_init();
    modbus_t* ctx = NULL;
    static int connect_attempt = 0;
    static int conn_succ_flag = 0;

    while (1) {
        if (ctx == NULL) {
            // 新建libmodbus context
            ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N', 8, 1);
            if (ctx == NULL) {
                fprintf(stderr, "Unable to allocate libmodbus context\n");
                #if HMI_INFO
                fprintf(stderr, "Unable to allocate libmodbus context\n");
                #endif
                //goto cleanup;
            }
            // 设置从机地址
            int slave_id_set = modbus_set_slave(ctx, SERVER_ID);
            // 设置从机地址
            if (slave_id_set == -1) {
                fprintf(stderr, "Unable to set slave ID: %s\n", modbus_strerror(errno));
                #if HMI_INFO
                fprintf(stderr, "Unable to allocate libmodbus context\n");
                #endif
                modbus_close(ctx);
                modbus_free(ctx);
                ctx = NULL;
            }
            if(ctx != NULL)
            {
            // 设置485模式
            modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
            }
           
        }

        // 连接设备
        if (ctx != NULL) {
           if ((conn_succ_flag==0)&&(modbus_connect(ctx) == -1))
           {
                conn_succ_flag =0;
                fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
                #if HMI_INFO
                fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
                #endif
                connect_attempt++;

                if (connect_attempt >= MAX_CONNECT_ATTEMPTS) {
                    fprintf(stderr, "Exceeded maximum connect attempts. Exiting.\n");
                    #if HMI_INFO
                    fprintf(stderr, "Exceeded maximum connect attempts. Exiting.\n");
                    #endif
                    goto cleanup;
                }
                // Retry after a delay
                usleep(500000);
                continue;
            } 
            else
            {
                connect_attempt = 0; // Reset connect attempt count on successful connection
                conn_succ_flag = 1;
            }
        }

        // 写多个寄存器
        convertMachineInfoToArray(machineInfo, infoArray);
        //pthread_mutex_lock(&mutex);
        writeModbusRegisters(ctx, 0, infoArray, 29);
        //pthread_mutex_unlock(&mutex);

         //先使能按钮 enablebutton_present readCoilValues_before[1 1 0 0 0 0]
        pthread_mutex_lock(&mutex);
        convert_Enable_ButtonInfo_ToArray(buttoninfo, enablebutton_present);  // 将接收的使能按钮json值转换为数组
        handleEnableButton(ctx, enablebutton_present, readCoilValues_before);
        memcpy(readCoilValues_before, enablebutton_present, sizeof(enablebutton_present));
        pthread_mutex_unlock(&mutex);

        //读取6个开关量的状态
        int rc = modbus_read_bits(ctx, coiladdr, 6, readCoilValues_after);//复制一份才能做对比
        if (rc == -1) {
            //fprintf(stderr, "Failed to read coil values: %s\n", modbus_strerror(errno));
            // 解锁
            usleep(500000); // 等待一段时间再重试
            continue;
            #if HMI_INFO
            hlogi("Failed to read coil values: %s", modbus_strerror(errno));
            #endif
            if(hmi_log)
            {
                hlogi("Failed to read coil values: %s", modbus_strerror(errno));
            }
        }
        memcpy(enablebutton_person_save, readCoilValues_after, sizeof(readCoilValues_after));

        usleep(1000); 
    }
    goto cleanup;
cleanup:
    // 清理资源
    if (ctx) {
        modbus_close(ctx);
        modbus_free(ctx);
    }
    return NULL;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2220018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Midjourney中文版:创意无界,绘梦成真

在数字艺术的浩瀚宇宙中,Midjourney中文版如同一颗璀璨的新星,以其独特的魅力和无限可能,引领着每一位创作者探索创意的无限边界。作为专为国内用户打造的AI绘画工具,Midjourney中文版不仅继承了原版的核心优势,更在本…

基于cloudreve(Docker应用)搭建网盘服务,用于目录的分享和在线预览。

文章目录 I 基于cloudreve(Docker应用)搭建网盘服务安装主要功能设置角色最大容量II 知识扩展:网盘类的文件预览需求背景: iOS可以直接预览PDF等常见格式文件,但是Android浏览器需要先下载文件,才能查看文件内容,因此需要搭建支持目录的分享和在线预览的MinIO文件服务提供…

【Redis】Zset类型常用命令

文章目录 一. Zset有序集合简介.二. 添加元素相关命令.2.1 向有序集合中添加元素(zadd) 三. 查询元素相关操作.3.1 查询有序集合中的元素个数( zcard zcount)3.2 查询指定区间内的元素(zrange zrevrange zrangebyscore)3.3 查询有序集合中指定成员的排名(zrank zrevrank )3.4 查…

AI大模型学习路线路径,巨详细!

大模型技术已经成为推动人工智能发展的关键力量。无论你是初学者还是有经验的开发者,想要掌握大模型应用,都需要遵循一定的学习路线。 从核心技术解析到模型微调与私有化部署,逐步深入大模型应用的世界。 这份学习路线图详细的介绍了那年每…

规划控制复现:Apollo LQR横向控制(算法原理推导与流程)

本文在前文已经搭建好的规划控制验证平台中进行LQR算法的复现: 1.车辆动力学建模 汽车轨迹跟踪误差模型示意图如下: 为车辆横向速度,为车辆纵向速度;和 分别为质心到前、 后轴的距离 ; 为车辆的横 摆角 ; 和 分别为车辆前 、 后轮的侧偏角。并设车辆…

【C++】哈希表的模拟实现

目录 一、闭散列(开放定址定法) 1、哈希表的结构: 2、哈希表的插入: 3、哈希表的查找: 4、哈希表的删除: 二、开散列(哈希桶) 1、哈希表的结构: 2、构造与析构&a…

若依前后分离版集成积木报表进行token传递

若依分离板集成积木报表就不说了需要的请移步:若依前后分离版集成积木报表-CSDN博客 考虑到前端摸鱼不干活,所以一般都是前后端都干,我这里前后端都搞上,你们直接抄,抄完接着去摸鱼,代码不美观,轻喷 一、…

【JavaEE】【多线程】synchronized和死锁

目录 一、synchronized详解1.1 互斥1.2 可重入 二、死锁2.1 死锁成因2.2 避免死锁 一、synchronized详解 1.1 互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到 同一个对象 synchronized 就会阻塞等待. 语法&#xff1…

AI时代程序员何去何从?提升自我还是被淘汰出局!

AI 在编程界的使用变得越来越普遍了。随着 ChatGPT 的横空出世,各种大语言模型如雨后春笋不断出现。国外如谷歌 Bard、Anthropic 的 Claude,国内如百度文心一言、阿里通义千问、讯飞星火认知大模型、昆仑万维天工大模型等。 想想看,以前得花好…

支持国密算法的数字证书-国密SSL证书详解

在互联网中,数字证书作为标志通讯各方身份信息的数字认证而存在,常见的数字证书大都采用国际算法,比如RSA算法、ECC算法、SHA2算法等。随着我国加强网络安全技术自主可控的大趋势,也出现了支持国密算法的数字证书-国密SSL证书。那…

【网络安全】缓存欺骗问题之查看个人资料接口

未经许可,不得转载。 文章目录 正文正文 目标网站 target.com,查看个人资料页面时,API 端点为/get_user,完整的 URL 是 https://target.com/web-api/v1/get_user?timestamp=123456(其中 timestamp 是一个易受攻击的参数)。 我注意到响应中有一个 cf-cache-status= MISS…

k8s部署Kafka集群超详细讲解

准备部署环境 Kubernetes集群信息 NAMEVERSIONk8s-masterv1.29.2k8s-node01v1.29.2k8s-node02v1.29.2 Kafka:3.7.1版本,apche版本 Zookeeper:3.6.3版本 准备StorageClass # kubectl get sc NAME PROVISIONER RECLA…

Docker安装ActiveMQ镜像以及通过Java生产消费activemq示例

拉取镜像 docker pull docker.io/webcenter/activemq 启动容器 docker run -d --name myactivemq -p 61616:61616 -p 8162:8161 docker.io/webcenter/activemq:latest 这样就代表启动成功了 浏览器访问 http://localhost:8162/ admin admin 开启验证 修改配置文件/opt/ac…

关于k8s集群高可用性的探究

1. k8s的高可用的核心是什么? 说到核心、本质 意味着要从物理层来考虑技术 k8s是一个容器编排管理工具,k8s受欢迎的时机 是docker容器受欢迎时,因为太多的docker容器,管理起来是一个大工程 那么刚好k8s是google自己用了十来年…

STM32L031F6P6基于CubeMX的串口通信调试笔记

用CubeMX创建项目 本实例用的PA14、PA13两个引脚,LPUART1。 对串口参数进行设置: 开启串口中断: 时钟源设置成内部高频时钟: 对项目进行设置: 生成代码: 在串口初始化函数中加入 __HAL_UART_ENA…

Asp.net Core MVC 动态路由

动态路由 asp.net core 3.0 就支持了 // 映射关系public class TranslationDatabase{private static Dictionary<string, Dictionary<string, string>> Translations new Dictionary<string, Dictionary<string, string>>{{"en", new Dictio…

《Vue3 踩坑》expose 和 defineExpose 暴露属性或方法注意事项

选项式写法 使用 选项式API - 状态选项 - expose 一定要注意&#xff1a; 接下来&#xff0c;进一步看示例说明&#xff1a; 设置 expose 仅显示列出的属性/方法才能被父组件调用&#xff1b;代码第 2 行&#xff0c;父组件可访问属性 a 和 方法 myFunc01&#xff0c;不可访…

Windows server 2022 数据中心版本的安装

安装前的准备工作&#xff1a; 1.准备好VMware虚拟机&#xff08;略&#xff09; 2.准备好镜像 图1-1 准备安装镜像 3.准备好安装的位置&#xff08;F盘2022vm文件夹&#xff09; 图1-2 选择并设定安装位置 4.开始安装 图1-3 开心VMware安装向导 图1-4 插入光盘镜像 图1-5…

视频转文字工具搜集

视频转文字工具是一种能够将视频中的音频内容转化为文字的软件或在线服务。这类工具通常支持多种视频格式和语言&#xff0c;适用于不同的场景和需求。以下是一些推荐的视频转文字工具及其特点&#xff1a; 媒关系&#xff1a;这是一款免费的视频转文字工具&#xff0c;支持多种…

ABAQUS应用11——支座弹簧

文章目录 0、背景1、ABAQUS中几类弹簧的简介2、SPRING1的性质初探 0、背景 1、ABAQUS中几类弹簧的简介 先说参考来源&#xff0c;ABAQUS2016的帮助文档里第4卷&#xff0c;32.1.1节&#xff0c;有三种弹簧&#xff08;SPRING1 、SPRING2 以及SPRINGA&#xff09;。 三种弹簧里…