当前位置: 首页 > news >正文

yyf做的搞笑视频网站装修设计公司简介

yyf做的搞笑视频网站,装修设计公司简介,国际网站怎么进,python 做的网站有哪些前言 在工业控制领域#xff0c;Android 设备通过 RS485 接口与 PLC#xff08;可编程逻辑控制器#xff09;通信是一种常见的技术方案。最近在实现一个项目需要和plc使用485进行通讯#xff0c;记录下实现的方式。 我这边使用的从平的Android平板#xff0c;从平里面已经…前言 在工业控制领域Android 设备通过 RS485 接口与 PLC可编程逻辑控制器通信是一种常见的技术方案。最近在实现一个项目需要和plc使用485进行通讯记录下实现的方式。 我这边使用的从平的Android平板从平里面已经对这个串口进行了优化和提供了开发工具包这样哦我们就不需要自己实现这方面的东西了【Uart 】就是提供的工具类。 正文 先贴代码 public class Rs485Util {private static final String TAG Rs485Util;private static final String UART_PATH /dev/ttyWK1;private static final int BAUD_RATE 19200;private static final String QUERY_COMMAND 01030000001AC401;private static final int QUERY_INTERVAL 199; // 定时查询间隔(毫秒)private static final int SEND_RETRY_COUNT 3; // 命令重试次数private static final int SEND_DELAY 51; // 重试间隔(毫秒)private static final int COMMAND_INTERVAL 101; // 不同命令间间隔(毫秒)private static volatile Rs485Util instance;private Uart uart485;private final ScheduledExecutorService queryExecutor; // 定时查询线程池private final ScheduledExecutorService commandExecutor; // 命令处理线程池private final BlockingQueueString commandQueue;private final AtomicBoolean isRunning new AtomicBoolean(false);private final AtomicBoolean isQuerying new AtomicBoolean(false);private final AtomicBoolean isQueryPaused new AtomicBoolean(false); // 查询暂停标记private String lastCommand null; // 上一条命令记录// 重要指令private static final String START_COMMAND_1 010600060001A80B;private static final String START_COMMAND_0 01060006000069CB;private static final String STOP_COMMAND_1 010600070001F9CB;private static final String STOP_COMMAND_0 010600070000380B;private Rs485Util() {// 初始化命令线程池单线程确保命令顺序执行commandExecutor Executors.newSingleThreadScheduledExecutor(r - {Thread thread new Thread(r, RS485-Command-Thread);thread.setDaemon(true);return thread;});// 初始化查询线程池单线程定时发送查询指令queryExecutor Executors.newSingleThreadScheduledExecutor(r - {Thread thread new Thread(r, RS485-Query-Thread);thread.setDaemon(true);return thread;});// 命令队列存储待发送的命令指令commandQueue new LinkedBlockingQueue();}// 单例模式获取实例public static Rs485Util getInstance() {if (instance null) {synchronized (Rs485Util.class) {if (instance null) {instance new Rs485Util();}}}return instance;}/*** 打开485串口并初始化通信*/public synchronized void open485Uart() {if (isRunning.get()) {Log.e(TAG, 串口已处于打开状态);return;}commandExecutor.execute(() - {try {// 初始化串口uart485 new Uart(UART_PATH, BAUD_RATE, true);uart485.setReceiveListener(bytes - {String receiveData DigitalTransUtil.byte2hex(bytes);PLCUtil.analyzePLCData(receiveData);});uart485.start();Log.e(TAG, 串口启动成功);isRunning.set(true);// 启动定时查询任务startQueryTask();// 启动命令队列处理processCommandQueue();} catch (Exception e) {e.printStackTrace();Log.e(TAG, 启动485串口失败 e.getMessage());closeResources(); // 异常时释放资源}});}/*** 启动定时查询任务带暂停判断*/private void startQueryTask() {if (isQuerying.get()) return;// 定时发送查询指令每次发送前检查是否被暂停queryExecutor.scheduleAtFixedRate(() - {// 仅在运行中且未被暂停时发送查询指令if (uart485 ! null isRunning.get() !isQueryPaused.get()) {try {byte[] sendByte DigitalTransUtil.hex2byte(QUERY_COMMAND);uart485.send(sendByte);Log.d(TAG, 发送查询指令: QUERY_COMMAND);} catch (Exception e) {Log.e(TAG, 查询命令发送失败: e.getMessage());}}}, 0, QUERY_INTERVAL, TimeUnit.MILLISECONDS);isQuerying.set(true);}/*** 处理命令队列发送命令时暂停查询*/private void processCommandQueue() {commandExecutor.execute(() - {while (isRunning.get()) {try {// 从队列获取命令阻塞等待新命令String command commandQueue.take();// 1. 暂停定时查询确保命令发送时无查询干扰 // pauseQuery();// 2. 不同命令间等待间隔if (lastCommand ! null !lastCommand.equals(command)) {Thread.sleep(COMMAND_INTERVAL);}// 3. 发送命令带重试sendCommandInternal(command);// 4. 更新最后一条命令记录lastCommand command;// 5. 恢复定时查询命令发送完成 // resumeQuery();} catch (InterruptedException e) {Log.e(TAG, 命令处理线程被中断, e);Thread.currentThread().interrupt();break;} catch (Exception e) {Log.e(TAG, 命令处理异常: e.getMessage());// 异常时也需恢复查询resumeQuery();}}});}/*** 内部发送命令带重试机制*/private void sendCommandInternal(String strCommand) throws InterruptedException {if (uart485 null || !isRunning.get()) {Log.e(TAG, 串口未初始化或已关闭无法发送命令);return;}for (int i 0; i SEND_RETRY_COUNT; i) {try {byte[] sendByte DigitalTransUtil.hex2byte(strCommand);uart485.send(sendByte);Log.e(TAG, 命令发送成功(第 (i 1) 次): strCommand);// 非最后一次重试时等待间隔if (i SEND_RETRY_COUNT - 1) {Thread.sleep(SEND_DELAY);}} catch (Exception e) {Log.e(TAG, 命令发送失败(第 (i 1) 次): e.getMessage());// 最后一次重试失败时仍继续后续流程避免阻塞if (i SEND_RETRY_COUNT - 1) {Log.e(TAG, 命令达到最大重试次数: strCommand);}}}}/*** 暂停定时查询*/private synchronized void pauseQuery() {if (!isQueryPaused.get()) {isQueryPaused.set(true);Log.e(TAG, 暂停定时查询);}}/*** 恢复定时查询*/private synchronized void resumeQuery() {if (isQueryPaused.get()) {isQueryPaused.set(false);Log.e(TAG, 恢复定时查询);}}/*** 发送命令接口线程安全*/public void sendString(String strCommand) {if (!isRunning.get()) {Log.e(TAG, 串口未打开无法发送命令);return;}try {boolean isSpecial START_COMMAND_1.equals(strCommand) || STOP_COMMAND_1.equals(strCommand);if (isSpecial) {commandQueue.clear();}commandQueue.put(strCommand);Log.e(TAG, 命令已加入队列: strCommand);} catch (InterruptedException e) {Log.e(TAG, 添加命令到队列被中断, e);Thread.currentThread().interrupt();}}/*** 停止485串口通信*/public synchronized void stop485Uart() {if (!isRunning.get()) {Log.e(TAG, 串口已处于关闭状态);return;}Log.e(TAG, 正在停止485串口通信...);isRunning.set(false);isQuerying.set(false);isQueryPaused.set(false); // 重置暂停状态closeResources();}/*** 关闭所有资源*/private void closeResources() {// 关闭查询线程池if (queryExecutor ! null) {queryExecutor.shutdownNow();try {if (!queryExecutor.awaitTermination(500, TimeUnit.MILLISECONDS)) {Log.e(TAG, 查询任务未能及时关闭);}} catch (InterruptedException e) {queryExecutor.shutdownNow();Thread.currentThread().interrupt();}}// 关闭命令线程池if (commandExecutor ! null) {commandExecutor.shutdownNow();try {if (!commandExecutor.awaitTermination(500, TimeUnit.MILLISECONDS)) {Log.e(TAG, 命令任务未能及时关闭);}} catch (InterruptedException e) {commandExecutor.shutdownNow();Thread.currentThread().interrupt();}}// 清空命令队列commandQueue.clear();// 关闭串口if (uart485 ! null) {try {uart485.stop();} catch (Exception e) {Log.e(TAG, 关闭串口异常: e.getMessage());}uart485 null;}Log.e(TAG, 485串口资源已完全释放);}/*** 检查串口是否已打开*/public boolean isUartOpen() {return isRunning.get();} }代码解析 使用两个单线程调度线程池实现任务分离 queryExecutor负责定时发送查询指令采用scheduleAtFixedRate实现固定间隔执行 commandExecutor处理命令队列确保命令按顺序执行 线程池配置为守护线程thread.setDaemon(true)避免应用退出时线程残留。这种分离设计保证了查询任务和命令任务的独立性防止相互干扰。 通过BlockingQueue实现命令的缓冲与有序处理 所有命令先进入队列等待由专门的线程按顺序取出并发送 特殊命令启动 / 停止具有清空队列的优先权 boolean isSpecial START_COMMAND_1.equals(strCommand) || STOP_COMMAND_1.equals(strCommand); if (isSpecial) { commandQueue.clear(); }这种设计解决了多线程发送命令的冲突问题保证了命令执行的顺序性同时确保关键操作如启动 / 停止能够立即执行。 关键方法解析 1. 串口初始化open485Uart() 该方法是启动通信的入口主要完成 检查当前状态避免重复打开 初始化 UART 设备配置端口路径/dev/ttyWK1和波特率19200 设置接收数据的监听器实现数据的异步处理 uart485.setReceiveListener(bytes - {//数据的解析处理String receiveData DigitalTransUtil.byte2hex(bytes);PLCUtil.analyzePLCData(receiveData); });2. 定时查询startQueryTask() 实现对 PLC 的定时查询功能 采用固定间隔199ms发送查询指令QUERY_COMMAND 发送前检查运行状态和暂停标记确保仅在合适状态下发送 通过scheduleAtFixedRate实现周期性执行 3. 命令处理processCommandQueue() 命令处理的核心流程 从队列阻塞获取命令commandQueue.take() 不同命令间保持固定间隔101ms避免命令发送过于密集 调用sendCommandInternal()实际发送命令包含重试逻辑 更新最后一条命令记录用于间隔判断 4. 资源释放closeResources() 该方法负责在通信结束或异常时释放所有资源 关闭线程池shutdownNow() awaitTermination 清空命令队列避免残留命令干扰 关闭串口设备释放硬件资源 重置所有状态标记确保下次启动正常 在和PLC对接的时候哥们建议我在进行定时循环或者类似的操作的时候最好不要把时间卡在5、10 等 5 的倍数核心逻辑还是与 PLC 扫描周期的 “同步冲突” 有关 避免同步重叠 PLC 的扫描周期通常是动态变化的如因程序复杂度波动在 8~12ms。若通讯间隔固定为 10ms5 的倍数可能与 PLC 的扫描周期 “同步”—— 例如 PLC 在第 10ms、20ms 时正处于数据刷新阶段此时外部设备如 SCADA、HMI发送通讯请求可能导致 数据读取不完整PLC 尚未完成输出刷新读取到的是 “旧数据”。 通讯响应延迟PLC 优先处理内部程序暂时搁置通讯请求导致外部设备超时。 实际建议 通讯间隔应避开 PLC 的典型扫描周期范围或采用非固定间隔如随机增加 1~2ms 偏移量。例如 若 PLC 扫描周期约为 10ms通讯间隔可设为 12ms 或 8ms减少同步概率。 对于需要高频通讯的场景如毫秒级控制建议采用 PLC 支持的高速通讯协议如 Profinet IO、EtherCAT而非依赖定时轮询。 还有PLC的撞包概念 “撞包” 是工业通讯中的通俗说法指数据帧冲突即多个设备在同一时间向 PLC 的通讯总线发送数据导致信号干扰、数据丢失。 常见场景 采用半双工通讯协议如 RS485 总线的 Modbus RTU时总线上的多个从设备如传感器、变频器若同时向 PLC主设备发送响应会导致数据帧重叠。 总线负载过高当多个设备的通讯频率过高如间隔过短总线上数据帧密集容易发生碰撞。 解决方式 采用全双工协议如 Profinet、EtherNet/IP通过交换机实现点对点通讯避免总线冲突。 严格主从机制如 Modbus RTU 中由 PLC主设备轮流查询从设备从设备仅在被询问时响应禁止主动发送数据。 降低总线负载控制总线上的设备数量或延长通讯间隔确保数据帧发送时间不重叠。
http://www.zqtcl.cn/news/847720/

相关文章:

  • 专门做汽车配件的网站东莞招聘网有哪些比较好
  • 网站前台怎么套用织梦后台小网站怎么建设
  • 网站框架代码深圳手机网站设计
  • 更改网站主题九江建网站的公司
  • 如何分析一个网站网站页面建设
  • 做网站好网页制作3个网页的网站图片
  • 合肥网站建设网站推广新的网站建设一般多少钱
  • 北京网站改版哪家好网站关键词怎样做优化
  • 网站开发行业分析wordpress 粘贴表格
  • 网站开发的招标参数网络科技公司网站源码下载
  • 属于网络营销站点推广的是seo好wordpress主题
  • j2ee只做网站阿里企业邮箱免费
  • 做企业网站需要买什么资料室内设计学徒
  • 网站新增关键词设计公司logo公司文化
  • 怎么写一个网站程序农产品网站如何做地推
  • 北京网站优化服务商有了域名怎么建网站
  • 转运网站开发国外永久免费crm系统
  • 免费网站建设网站wordpress扁平化中文主题
  • 外贸企业网站策划个人简历模板免费可编辑
  • 自助建站免费建站免费建站工具有哪些
  • 海外网站导航前端静态网站开发
  • 德庆网站建设价格网站的月度流量统计报告怎么做
  • 网站哪里买外链品牌网站设计步骤
  • 网站推广 优帮云淄博网站制作公司
  • 二手书哪个网站做的好wordpress 直排主题
  • 网站开发风险分析做情诗网站
  • 怎样可以快速增加网站的反链网络广告平台有哪些
  • 学校网站源码小游戏网站审核怎么做
  • 西乡网站建设政务网站开发协议
  • 美食网站开发环境北京app网站建设