【BUG】記STM32F030多通道ADC DMA讀取亂序問題

STM32F0多通道ADC的校準順序與DMA亂序問題的本質

聲明:本段轉載:https://www.cnblogs.com/chihirosan/p/5458673.html

  • 問題描述
    通過 uint16_t ConvData[8]保存DMA搬運的ADC轉換數值,但是這個數組數值的順序總是和ADC不是順序對應的。比如用7個通道的ADC,

    • 當設置ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward,是對應順序是:0->0,1->7,2->6…7->1 ;
    • 當設置ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward,是對應順序是:0->7,1->0,2->1…7->6 。
  • 問題原因
    F0的ADC在使用之前需要校準。這個7位的校準值也是放在ADC_DR中的,它也會觸發DMA請求。
    可以參照F0的ADC-DMA例程,先做ADC校準、然后再設置DMA,再使能ADC的DMA。

  • 實例代碼

void ADC1_DMA_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = 0x00ff;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA, &GPIO_InitStructure);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);ADC_DeInit(ADC1); //ADC恢復默認設置ADC_StructInit(&ADC_InitStructure); //初始化ADC結構ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //12位精度ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //規定模式裝換工作在連續模式ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //數據對其為右對齊ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward; // ADC_ScanDirection_Backward; //ADC的掃描方向ADC_Init(ADC1, &ADC_InitStructure);ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_3, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_4, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_5, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_6, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_ChannelConfig(ADC1, ADC_Channel_7, ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ADC_GetCalibrationFactor(ADC1); /* ADC Calibration */ADC_Cmd(ADC1, ENABLE); /* Enable ADCperipheral[PerIdx] */while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); /* Wait the ADCEN falg *///設置DMA要在校準ADC之后DMA_DeInit(DMA1_Channel1); /* DMA1 Channel1 Config */DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 0x40012440; //ADC1->DR; //外設地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) RegularConvData_Tab; //內存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外設作為數據傳輸的來源DMA_InitStructure.DMA_BufferSize = 8; //DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址寄存器不變DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址寄存器不變DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //數據寬度為16位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //數據寬度為16位DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA_Mode_Circular;DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA_Priority設定DMA通道x的軟件優先級DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x沒有設置為內存到內存傳輸DMA_Init(DMA1_Channel1, &DMA_InitStructure);DMA_Cmd(DMA1_Channel1, ENABLE);/* DMA1 Channel1 enable */DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular); /* Enable ADC_DMA */ADC_DMACmd(ADC1, ENABLE);ADC_StartOfConversion(ADC1); /* ADC1 regular Software Start Conv */}
原問題現象與深層原因
  1. DMA在ADC中的應用

    • ADC多通道掃描時,DMA用于自動搬運轉換結果。但STM32F0系列的ADC包含校準值存儲機制
    • 校準階段:調用ADC_GetCalibrationFactor()時,會將一個7位的校準值寫入ADC_DR寄存器(與轉換結果共用同一地址),并觸發DMA請求。
  2. DMA亂序的成因

    • 過早啟用DMA(如在校準前)會導致DMA將校準值當做首個有效數據搬運,后續通道數據依次錯位。
    • 數值錯位實例
      • 若ADC通道0的值在ADC_DR中的實際存儲順序應為第1個,但因校準值的介入,DMA搬運時該值會出現在數組的第二個位置。
  3. 解決方案的工程意義

    • 校準后配置DMA:確保DMA僅搬運有效轉換結果。關鍵代碼如下:
      ADC_GetCalibrationFactor(ADC1);   // 先校準
      DMA_Init(DMA1_Channel1, ...);     // 后配置DMA
      ADC_DMACmd(ADC1, ENABLE);         // 最后使能ADC的DMA請求
      
  4. ADC掃描方向的補充解釋
    ADC_ScanDirection參數定義通道掃描的物理順序:

    • Upward模式:從通道編號低到高掃描(如0→1→2)。
    • Backward模式:從編號高到低掃描(如2→1→0)。
      此參數需要與DMA數組的預期存儲順序一致,否則需軟件層調整數組索引。
擴展思考:其他引發DMA錯位的可能
  1. 未清除DMA緩存:DMA傳送前后未重置緩存區,殘留數據可能導致混淆。
  2. 中斷搶占沖突:若ADC中斷優先級低于其他中斷,可能因響應延遲導致數據覆蓋。

總結

  1. 編碼規范的重要性:結構體聲明的位置不僅是語法問題,更影響代碼可移植性。
  2. 硬件機制的深度理解:結合芯片手冊分析異常(如STM32F0校準值特性),能快速定位隱蔽問題。

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

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

相關文章

Java - Mysql數據類型對應

Mysql數據類型java數據類型備注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮點型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定長度字符串VARCHARjava.lang…

今天刷SQL

多說幾句,JAVA真不行了? 剛剛看到那個tiobe最新的指數,JAVA只剩下8.84%?感覺上次看的時候還有百分之十呢。 185-department-top-three-salaries https://leetcode.com/problems/department-top-three-salaries/description/ 公…

【SQL學習筆記1】增刪改查+多表連接全解析(內附SQL免費在線練習工具)

可以使用Sqliteviz這個網站免費編寫sql語句,它能夠讓用戶直接在瀏覽器內練習SQL的語法,不需要安裝任何軟件。 鏈接如下: sqliteviz 注意: 在轉寫SQL語法時,關鍵字之間有一個特定的順序,這個順序會影響到…

【計算機網絡】SDN

SDN這種新型網絡體系結構的核心思想:把網絡的控制層面與數據層面分離,而讓控制層面利用軟件來控制數據層面中的許多設備。 OpenFlow協議可以被看成是SDN體系結構中控制層面與數據層面之間的通信接口。 在SDN中取代傳統路由器中轉發表的是“流表”&…

量化面試綠皮書:9. 通往Offer的門

文中內容僅限技術學習與代碼實踐參考,市場存在不確定性,技術分析需謹慎驗證,不構成任何投資建議。 9. 通往Offer的門 你面對著兩扇門。 一個通往你的工作機會,另一個是退出。 兩扇門前都有一名警衛。一個守衛總是說謊&#xff0c…

【雜談】-遞歸進化:人工智能的自我改進與監管挑戰

遞歸進化:人工智能的自我改進與監管挑戰 文章目錄 遞歸進化:人工智能的自我改進與監管挑戰1、自我改進型人工智能的崛起2、人工智能如何挑戰人類監管?3、確保人工智能受控的策略4、人類在人工智能發展中的角色5、平衡自主性與控制力6、總結與…

Ascend NPU上適配Step1X-Edit模型

1 概述 1.1 簡述 Step1X-Edit:一個在各種真實用戶指令下表現出現的統一圖像編輯模型。 Step1X-Edit,其性能可與 GPT-4o 和 Gemini2 Flash 等閉源模型相媲美。更具體地說,我們采用了多模態LLM 來處理參考圖像和用戶的編輯指令。我們提取了潛…

WEB3全棧開發——面試專業技能點P8DevOps / 區塊鏈部署

一、Hardhat / Foundry 進行合約部署 概念介紹 Hardhat 和 Foundry 都是以太坊智能合約開發的工具套件,支持合約的編譯、測試和部署。 它們允許開發者在本地或測試網絡快速開發智能合約,并部署到鏈上(測試網或主網)。 部署過程…

【題解-洛谷】B4292 [藍橋杯青少年組省賽 2022] 路線

題目:B4292 [藍橋杯青少年組省賽 2022] 路線 題目描述 有一個旅游景區,景區中有 N N N 個景點,景點以數字 1 1 1 到 N N N 編號,其中編號為 N N N 的景點為游客服務中心所在地。景區中有 M M M 條連接路線,每條…

MySQL體系架構解析(四):MySQL數據存儲的揭秘

MySQL中的數據目錄 確定MySQL的數據目錄 到底MySQL把數據都存到哪個路徑下呢?其實數據木對應著一個系統變量datadir,我們在使用客戶端與服務器建立連接之后查看這個系統變量的值就可以了。 -- 以下兩種方式都可以 show variables like datadir; selec…

Solidity從入門到精通-Remix的基本使用和Solidity的基本數據類型

Solidity從入門到精通-Remix的基本使用和Solidity的基本數據類型 講了那么多理論,相信大家對區塊鏈/web3也有了一定認知;這時候可能就問有人會問了如何把理論變成實際的代碼實現。 這就來了接下來會給大家分享Solidity入門教程 這時候就會有同學問了Sol…

ArcGIS Pro+ArcGIS給你的地圖加上北回歸線!

今天來看ArcGIS Pro和ArcGIS中如何給制作的中國地圖或者其他大范圍地圖加上北回歸線。 我們將在ArcGIS Pro和ArcGIS中一同介紹。 1 ArcGIS Pro中設置北回歸線 1、在ArcGIS Pro中初步設置好經緯格網等,設置經線、緯線都以10間隔顯示。 2、需要插入背會歸線&#xf…

在.NET Core控制器中獲取AJAX傳遞的Body參數

.Net Core是支持前后端不分離式的開發的,如果在原始系統中采用不分離式開發,后面需要在原系統中增加功能,并且新的服務采用其他語言開發,且系統原來功能保持原樣,這樣前端系統可以單獨調用新開發的接口。 但是&#x…

ubuntu24安裝opencv過程

1.訪問opencv官網,下載源代碼。 opencv 2.選擇相應版本的源碼下載 我這里用的是4.8.1版本的源碼進行安裝,opencv-4.8.1.tar.gz 安裝命令 tar xvf opencv-4.8.1.tar.gz #在當前文件夾創建build文件,并進入 mkdir build && cd build …

Kubernetes ClusterIP 端口深度解析:虛擬服務與流量轉發機制

事情的起因是創建了一個 NodePort 類型 Service,其端口映射關系為 8000:30948/TCP。既然30948是在每個node開的端口,那8000是開在哪的呢?出于好奇回顧了一下K8s的Cluster IP和Service 端口映射關系解析 在 Kubernetes 的 NodePort Service 中…

C++左值與右值及引用的總結

前言 在C中,理解左值(lvalue)和右值(rvalue)是掌握現代C核心特性的關鍵。左值通常指代具名的、持久存在的對象,可以取地址;而右值則是臨時的、即將銷毀的值,如字面量或表達式結果。…

學習記錄:DAY31

Java課設:數字水印處理與解析器開發 前言 想養成寫日記的習慣真不容易。最近比較懶散,復習不想復,項目又做完了,處于一種能干些什么,但是不太想干,但是不干些什么又渾身難受的處境。其實完全就不是勻不出…

Linux系統部署KES

1、安裝準備 1.版本說明V008R006C009B0014 V008:是version產品的大版本。 R006:是release產品特性版本。 C009:是通用版 B0014:是build開發過程中的構建版本2.硬件要求 #安全版和企業版 內存:1GB 以上 硬盤&#xf…

系統模塊與功能設計框架

系統模塊與功能設計框架,嚴格遵循專業架構設計原則,基于行業標準(如微服務架構、DDD領域驅動設計)構建。設計采用分層解耦模式,確保可擴展性和可維護性,適用于電商、企業服務、數字平臺等中大型系統。 系統…

MySQL中【正則表達式】用法

MySQL 中正則表達式通過 REGEXP 或 RLIKE 操作符實現(兩者等價),用于在 WHERE 子句中進行復雜的字符串模式匹配。以下是核心用法和示例: 一、基礎語法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …