野火STM32Modbus主機讀取寄存器/線圈失敗(一)-解決接收中斷不觸發的問題

接收中斷不觸發

前情提要

在自己的開發板上移植了野火的modbus主機程序。
野火主機程序移植
野火主機代碼理解與使用

問題背景

我使用STM32顯示板作為Modbus主機連接電腦,并在電腦上運行Modbus Slave軟件。測試中發現,讀取保持寄存器和輸入寄存器均失敗,但寫入操作正常。例如,當我的板子作為主機發送讀取從機1的40、41地址(其中預先寫入了4000和6500)的請求時,Modbus Slave可以正確接收到請求幀:

Rx: 001205-01 03 00 28 00 02 44 03
Tx: 001206-01 03 04 0F A0 19 64 B1 97

這說明主機發出的命令沒有問題。然而,在我的代碼中,用于存儲保持寄存器的數組 usMRegHoldBuf[][] 始終為0,未能更新。進一步排查發現,程序并未進入回調函數 eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)

后續測試表明,Modbus主機的接收中斷從未被觸發,因此初步判斷問題出在Modbus主機的接收中斷部分,可能存在配置或實現上的錯誤。


現象

在portserial_m.c中添加調試代碼,變量tx_int_count遞增,但是rx_int_count始終為0,說明沒觸發接收中斷。

/* * Create an interrupt handler for the transmit buffer empty interrupt* (or an equivalent) for your target processor. This function should then* call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that* a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character.*/
void prvvUARTTxReadyISR(void)
{/* 發送狀態機 */extern volatile uint32_t tx_int_count;tx_int_count++;pxMBMasterFrameCBTransmitterEmpty();
}/* * Create an interrupt handler for the receive interrupt for your target* processor. This function should then call pxMBFrameCBByteReceived( ). The* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the* character.*/
void prvvUARTRxISR(void)
{/* 接收狀態機 */extern volatile uint32_t rx_int_count;rx_int_count++;pxMBMasterFrameCBByteReceived();
}

解決

將portserial_m.c中的void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)進行修改。

void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
{/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/if(xRxEnable){/* 串口2接收中斷使能 */__HAL_USART_ENABLE_IT(&huart2,USART_IT_RXNE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)	/* 485低電平接收 */HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_LOW);#endif}else{/* 串口2接收中斷關閉 */__HAL_USART_DISABLE_IT(&huart2,USART_IT_RXNE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)/* 485高電平發送 */HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_HIGH);#endif}if(xTxEnable){/* 串口2發送中斷使能 */__HAL_USART_ENABLE_IT(&huart2,USART_IT_TXE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)/* 485高電平發送*/HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_HIGH);#endif}else{/* 串口2發送中斷關閉 */__HAL_USART_DISABLE_IT(&huart2,USART_IT_TXE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)	/* 485低電平接收*/HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_LOW);#endif}
}

改成

void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
{/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/if(xRxEnable){#if defined(MODBUS_MASTER_USE_CONTROL_PIN)	/* 485低電平接收 */HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_LOW);/* 添加小延時確保485切換完成 */for(volatile int i = 0; i < 100; i++);#endif/* 串口2接收中斷使能 */__HAL_USART_ENABLE_IT(&huart2,USART_IT_RXNE); }else{/* 串口2接收中斷關閉 */__HAL_USART_DISABLE_IT(&huart2,USART_IT_RXNE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)/* 485高電平發送 */HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_HIGH);#endif}if(xTxEnable){#if defined(MODBUS_MASTER_USE_CONTROL_PIN)/* 485高電平發送*/HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_HIGH);/* 添加小延時確保485切換完成 */for(volatile int i = 0; i < 100; i++);#endif/* 串口2發送中斷使能 */__HAL_USART_ENABLE_IT(&huart2,USART_IT_TXE); }else{/* 串口2發送中斷關閉 */__HAL_USART_DISABLE_IT(&huart2,USART_IT_TXE); #if defined(MODBUS_MASTER_USE_CONTROL_PIN)	/* 485低電平接收*/HAL_GPIO_WritePin(MODBUS_MASTER_GPIO_PORT,MODBUS_MASTER_GPIO_PIN,MODBUS_MASTER_GPIO_PIN_LOW);#endif}
}

就可以觸發了,rx_int_count遞增。

原因分析

您遇到的問題非常典型,涉及到RS-485半雙工通信中一個關鍵且容易忽視的細節:方向控制引腳(DE/RE)切換與UART中斷使能的時序問題

問題根本原因分析

(暫不清楚,以下為ai的解釋)
中斷使能(__HAL_USART_ENABLE_IT)的操作在GPIO方向切換(HAL_GPIO_WritePin)之前。這會引發一個競態條件(Race Condition):

  1. 使能接收中斷的時刻:當調用 __HAL_USART_ENABLE_IT(&huart2, USART_IT_RXNE) 后,USART2的接收中斷立即被打開。此時,USART硬件已經開始監聽總線上的數據。
  2. 切換485方向的時刻:緊接著,代碼才去設置GPIO引腳為接收模式(低電平)。從CPU執行完第一條指令到GPIO電平實際穩定、收發器切換到接收狀態,存在一個極短但不可忽略的延遲。

在這個短暫的延遲窗口內,總線狀態是不確定的:

  • 如果總線上恰好有數據(例如,上一幀數據的殘留、噪聲、或者其他設備的發送),USART的接收寄存器(RXNE)會立即被置位。
  • 由于接收中斷已經使能,CPU會立刻響應并進入接收中斷服務程序(ISR)。
  • 然而,此時485收發器可能還未完全切換到接收模式,導致它無法正確地將總線差分信號傳遞給USART,或者傳遞的是錯誤的電平。
  • 最終結果是,ISR讀取到的可能是無效數據幀錯誤(FE)、或噪音。更常見的是,這個過早觸發的中斷會清空RXNE標志,但并沒有讀到有效數據。而當Modbus協議棧真正開始等待響應時,由于標志位已被清除,無法再次觸發中斷,導致接收超時。

修改后的代碼為什么能工作?

修改后的代碼調整了時序

  1. 先切換485方向:首先通過GPIO將收發器穩穩地設置為目標模式(接收或發送)。
  2. 添加短暫延時:使用 for 循環提供一個短暫的阻塞延時。這個延時確保了GPIO電平有足夠的時間穩定下來,并且485收發器內部的電路已經完成了切換(通常需要幾百納秒到幾微秒)。雖然用循環實現延時不是最優雅的方式(更好的做法是使用硬件定時器或精確延時函數),但它簡單有效,解決了硬件切換的時序問題。
  3. 最后使能中斷:在確保硬件已經完全準備好之后,再打開USART中斷。這樣,當中斷使能時,總線狀態和收發器狀態都是穩定和正確的,只有在使能之后到來的新數據才會觸發中斷,從而避免了“舊”數據或噪音的誤觸發。

簡單比喻:

  • 修改前:就像先打開麥克風的開關(中斷使能),然后再告訴別人“現在你可以對我說話了”(485切接收)。在你告訴他之前,任何環境噪音(總線數據)都會被麥克風錄進去。
  • 修改后:先告訴別人“現在你可以對我說話了”(485切接收),確保自己準備好了,然后再打開麥克風開關(中斷使能)。這樣錄到的才是對方真正要對你說的話。

總結與建議

總結: 接收中斷不觸發的根本原因不是中斷沒打開,而是中斷被過早地觸發并在錯誤的時刻被處理掉了。修改后的代碼通過調整GPIO操作和中斷使能的順序,并加入延時確保硬件穩定,解決了這個問題。

改進建議:

  1. 替換循環延時for循環延時受編譯器優化和CPU頻率影響,不精確。建議使用HAL_Delay(1)(延時1ms,對于485切換綽綽有余)或者查詢硬件定時器來實現更可靠的微秒級延時。
  2. 檢查中斷優先級:確保USART中斷的優先級設置合理,不會被其他高優先級中斷長時間阻塞。
  3. 檢查中斷服務程序(ISR):確保在USART2的IRQHandler中正確處理了USART_IT_RXNE事件,并且清除了相應的標志位。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920956.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

5種常見的網絡安全漏洞及防護建議

五種常見的網絡安全漏洞及防護建議在數字化時代&#xff0c;網絡安全已成為個人和企業面臨的重要挑戰。網絡攻擊手段不斷升級&#xff0c;黑客利用各種漏洞入侵系統、竊取數據或破壞服務。了解常見的網絡安全漏洞并采取相應的防護措施&#xff0c;是保障信息安全的關鍵。本文將…

mysql5.6+分頁時使用 limit+order by 會出現數據重復問題

mysql5.6分頁時使用 limitorder by 會出現數據重復問題 問題描述 在MySQL中我們通常會采用limit來進行翻頁查詢&#xff0c;比如limit(0,10)表示列出第一頁的10條數據&#xff0c;limit(10,10)表示列出第二頁。但是&#xff0c;當limit遇到order by的時候&#xff0c;可能會出現…

【XR技術概念科普】VST(視頻透視)vs OST(光學透視):解碼MR頭顯的兩種核心技術路徑

混合現實(MR)頭顯作為連接虛擬與現實世界的橋梁&#xff0c;其核心技術路徑主要分為視頻透視(VST)和光學透視(OST)兩種。本文將深入探討這兩種技術的原理、優缺點、代表性產品、應用場景及未來發展趨勢&#xff0c;為讀者全面解析MR頭顯的技術選擇。一、VST技術詳解1.1 VST技術…

VR智慧樓宇技術:打造智能辦公空間的卓越方案?

在華銳視點打造的極具創新性的VR智慧樓宇的智能辦公空間里&#xff0c;員工的工作模式迎來了前所未有的、徹頭徹尾的顛覆性變革。憑借華銳視點自主研發的先進VR設備&#xff0c;哪怕員工遠在千里之外的不同城市&#xff0c;甚至身處不同國家&#xff0c;也能如同真切地置身于同…

C++ 面試考點 類成員函數的調用時機

構造函數和析構函數的調用時機 1. 對于全局定義的對象&#xff0c;每當程序開始運行&#xff0c;在主函數 main 接受程序控制權之前&#xff0c;就調 用構造函數創建全局對象&#xff0c;整個程序結束時&#xff0c;自動調用全局對象的析構函數。 2. 對于局部定義的對象&#…

59.螺旋矩陣II

59.螺旋矩陣II 螺旋矩陣沒有什么算法&#xff0c;就是一道單純模擬轉圈的一道題目&#xff0c;因為轉圈的過程需要處理的邊界條件很多&#xff0c;所以有難度 那只能從第二個節點開始處理&#xff1b;從第二個節點開始處理&#xff0c;把最后一個節點也處理了&#xff08;第二…

MS SQL(Microsoft SQL Server)面試常考的知識點

MS SQL是Microsoft SQL Server的簡稱&#xff0c;是由微軟公司開發的一款關系型數據庫管理系統&#xff08;RDBMS,Relational DataBase Management System&#xff09;。它支持在Windows和Linux上運行&#xff0c;廣泛應用于企業級數據庫市場&#xff0c;適用于大型企業網站和應…

百勝軟件獲邀出席第七屆中國智慧零售大會,智能中臺助力品牌零售數智變革

8月28日&#xff0c;由深圳市智慧零售協會主辦的第七屆中國智慧零售大會在深圳福田希爾頓酒店成功召開。本屆大會以“聚勢AI共啟智慧零售新生態”為主題&#xff0c;匯聚了來自北京大學、騰訊云、百果園、舍得酒業、美宜佳等眾多知名企業與機構的專家代表&#xff0c;共同探討A…

QEMU使用Qemu-Guest-Agent傳輸文件、執行指令等

簡介 之前介紹過qemu傳輸文件,使用的掛載 / samba方式 :Qemu和宿主機不使用外網進行文件傳輸。 這是一種方式,這里還有另一種方式:使用Qemu-Guest-Agent,后面簡稱qga。 官網介紹:https://www.qemu.org/docs/master/interop/qemu-ga.html 安裝 這里有一篇參考文章,會…

HTML 核心標簽全解析:從文本排版到媒體嵌入

在網頁開發中&#xff0c;HTML&#xff08;超文本標記語言&#xff09;是構建頁面結構的基石。掌握各類核心標簽的用法&#xff0c;是實現頁面內容有序呈現、提升用戶體驗的關鍵。本文將系統講解 HTML 中最常用的幾類標簽 —— 段落標簽、文本格式標簽、列表標簽、表格&#xf…

[后端快速搭建]基于 Django+DeepSeek API 快速搭建智能問答后端

在 AI 應用開發中&#xff0c;將大模型 API 與 Web 框架結合是常見需求。本文將詳細記錄如何使用 Django 搭建后端服務&#xff0c;并集成 DeepSeek API 實現智能問答功能&#xff0c;包含環境配置、路由設計、API 調用及異常處理的完整流程&#xff0c;適合需要快速搭建 AI 問…

R 語言 + 卒中 Meta 分析

R 語言 卒中 Meta 分析&#xff1a;4 類核心場景完整代碼&#xff08;含藥物對比 / 劑量風險&#xff09; 卒中&#xff08;缺血性 / 出血性&#xff09;的臨床決策高度依賴循證證據&#xff0c;而 Meta 分析是整合多中心研究結果的核心工具。本文以卒中臨床研究為核心&#x…

Goframe 框架下HTTP反向代理并支持MCP所需的SSE協議的實現

一、需求背景 Go 語言開發 MCP 服務&#xff0c;并在 Goframe 框架下實現 Http 反向代理&#xff0c;代理該 MCP 服務。 二、效果演示 三、Goframe框架簡介 GoFrame 是一款模塊化、低耦合設計、高性能的Go 語言開發框架。包含了常用的基礎組件和開發工具&#xff0c;既可以作…

Git將多筆patch合并成一筆

一、方法1、在你的代碼中把這多筆patch都打上2、git reset到origin那一筆(默認模式&#xff0c;不帶soft或者hard)3、再add和commit&#xff0c;push二、種模式對比模式命令示例影響范圍適用場景--softgit reset --soft HEAD~1僅移動 HEAD&#xff0c;保留修改在暫存區修改提交…

【SpringBoot】Dubbo、Zookeeper

文章目錄前提知識概要分布式系統單體架構垂直應用架構分布式架構流式架構RPCDubbo概念Dubbo環境搭建Zookeeper測試 ZookeeperWindow環境下使用Dubbo-admin版本匹配不對服務注冊實戰內容總結導入相關依賴選擇 Zookeeper 版本配置并啟用 Zookeeper創建服務接口和實現(DubboServic…

【不說廢話】pytorch張量相對于numpy數組的優勢

核心關系 我們首先需要了解&#xff1a;PyTorch 張量在設計上深受 NumPy 數組的影響&#xff0c;它們共享許多相似的 API 和概念。實際上&#xff0c;PyTorch 張量可以看作是支持 GPU 加速和自動求導功能的 NumPy 數組。PyTorch 張量的主要優勢 1. GPU 加速支持&#xff08;最重…

拼團小程序源碼分享拼團余額提現小程序定制教程開發源碼二開

功能詳細說明&#xff08;一&#xff09;首頁功能進入首頁&#xff0c;可看到以下核心功能&#xff1a;1、優惠券&#xff0c;錢包&#xff0c;簽到&#xff0c;拼團&#xff0c;分銷等各種功能入口2、推薦的商品和活動3、下方功能欄的各種功能&#xff08;二&#xff09;客服功…

pikachu之XSS

XSS&#xff08;跨站腳本&#xff09;概述Cross-Site Scripting 簡稱為“CSS”&#xff0c;為避免與前端疊成樣式表的縮寫"CSS"沖突&#xff0c;故又稱XSS。一般XSS可以分為如下幾種常見類型&#xff1a;1.反射性XSS;2.存儲型XSS;3.DOM型XSS;XSS漏洞一直被評估為web漏…

【Element Plus `el-select` 下拉菜單響應式定位問題深度解析】

Element Plus el-select 下拉菜單響應式定位問題深度解析 本文檔旨在深入剖析一個在響應式布局中常見的 UI 問題&#xff1a;如何確保一個靠近屏幕邊緣的 el-select 組件的下拉菜單&#xff0c;在任何屏幕尺寸下都能以預期的、優雅的方式顯示。 1. 需求背景 在一個大屏數據展示…

Qt 項目文件(.pro)中添加 UI 文件相關命令

在 Qt 的 .pro 項目文件中&#xff0c;處理 UI 文件&#xff08;.ui 文件&#xff09;通常需要以下配置&#xff1a; 基本 UI 文件配置 自動包含 UI 文件&#xff1a; qmake FORMS yourfile.ui \anotherfile.ui Qt 構建系統會自動使用 uic&#xff08;用戶界面編譯器&#xff…