STM32F3系列 ADC採樣單端採樣模式(基於LL庫)

来源:https://www.cnblogs.com/muheandrabbit/archive/2023/10/29/17783979.html
-Advertisement-
Play Games

STM32F3系列 ADC 單端採樣(基於LL庫) 晶元型號:STM32f303RBT6 開發軟體:MDK5 & CubeMX & VS Code 目錄 目錄STM32F3系列 ADC 單端採樣(基於LL庫)目錄引言1 基礎知識1.1ADC轉換基本流程1.2 時鐘樹1.3 關鍵參數1.3.1 位數1 ...


STM32F3系列 ADC 單端採樣(基於LL庫)

  • 晶元型號:STM32f303RBT6
  • 開發軟體:MDK5 & CubeMX & VS Code

目錄

目錄

引言

STM32F303系列單片機一般具有多個12位逐次逼近型(Successive approximatio)模數轉換器(ADC,analog-to-digital converter)。STM32的ADC功能很多:單端採樣、差分採樣、主從模式、雙ADC模式、註入模式等。本文作為學習筆記,記錄最簡單的單端(single-end)模式.

1 基礎知識

1.1ADC轉換基本流程

image
上圖是STM32ADC的框圖,黑色箭頭我自己加的開關。其轉換流程大概可以簡略為:

  1. 接收到觸發信號,摁下開關
  2. 外部電壓經過外部電阻(\(R_{AIN}\)),雜散電容(\(C_{parastitic}\))、ADC內部電阻(\(R_{ADC}\)),給採樣電容\(C_{ADC}\)充電。
  3. 充電完成,鬆開開關,轉換核心開始將電容上的電壓值轉為數字信號。
  4. 轉換完成,轉換結果存入ADC的數據寄存器中。

1.2 時鐘樹

STM32F3系列的單片機的ADC時鐘有兩路,一路為同步時鐘(黑色),一路為非同步時鐘(藍色)。非同步時鐘除了比同步時鐘具有更多的分頻選擇,其他沒有大的區別,其時鐘最高頻率也是相同的。

但是建議採用同步時鐘,使用非同步時鐘時或許可能轉換會出現問題,我也不知道什麼原因。
image

1.3 關鍵參數

1.3.1 位數

ADC一般可以分為10bit、12bit、16bit等,這個bit就是指的位數。位數的含義就是能把參考電平分為2的多少次方份。

比如:10bit的ADC可以把參考電平分為1024份; 12bit的ADC可以把參考電平分為4096份。若是參考電壓為3.3V,則10bitADC可以分辨的最小電壓為\(3.3/(2^{10}) = 3.22mV\),12bitADC可以分辨的最小電壓為\(3.3/(2^{12}) = 0.806mV\)

由此可見,ADC位數越大,其解析度越高,採集到的電壓相對越準確。

1.3.2 觸發信號

觸發信號對於ADC轉換流程中的第一步,即告訴ADC什麼時候開始轉換。觸發信號有很多種,常用的有:軟體觸發、定時器信號觸發和外部觸發等。

1.3.3 採樣時間

採樣時間對應ADC轉換流程中的第二步,即開關摁下多久,外部信號對\(C_{ADC}\)充電多長時間。一般來說採樣時間以ADC時鐘周期\(T_{ADC}\)的倍數,如:\(1.5T_{ADC}\)\(2.5T_{ADC}\)\(19.5T_{ADC}\)等。一般來說採樣時間越長,信號採樣越準確,一般是根據外電阻的大小來選擇採樣時間,具體採樣時間選擇可以參照下表:
image
例如:外電阻為5k,外電阻介入2.7k~8.2k之間,則可以選擇的採樣時間為\(61.5T_{ADC}\)

1.3.4 轉換時間

轉換時間指的是ADC將制定電壓轉為為數字信號所用的時間,這個時間一般不可以控制,與ADC的時鐘周期有關,時鐘周期越長則轉換時間越小。

2 CubeMx 配置步驟

2.1 確定輸入通道

image
選取ADC1-IN1通道作為檢測通道,選擇單端模式Single-ended。

2.2 配置ADC

image
重要參數介紹:

  • Mode:independence即獨立模式;
  • Clock Prescale:選取同步時鐘最為ADC的時鐘,分頻繫數為1,即ADC時鐘為72M
  • Resolution(解析度):選取12bit
  • Data Alignment(數據對其):一般選右對齊
  • End of Conversion selection(轉換完成信號):這個參數指定了何時ADC觸發DMA和中斷,有兩個參數End of single conversion(EOC) 與 End of sequence of conversion(EOS),即單次轉換完成和順序轉換完成,由於我們只有一個通道選擇這兩個一樣的,本次選擇EOC。
  • OverRun behavior(覆寫行為):若使能這個功能,則在ADC上次數據還沒有讀取的時候,新的輸出產生時,會直接覆寫上次數據。
  • Lower Power Auto Wait(低功耗自動等待):用於低功耗的功能。
  • Enable Regular Conversations(使能常規轉換組):字面意思,使能常規組轉換。
  • Number of Conversion(轉換數量):需要轉換的信號有幾個。
  • External Trigger Conversion Source(外部觸發源):觸發信號是什麼?軟體、或定時器等。
  • External Trigger Conversion Edge(外部觸發邊沿):指定觸發類型,上升沿觸發、或下降沿觸發等
  • Rank 1:
    • Channal(通道號):對應Channel1
    • Sampling Time(採樣時間):對應上文的採樣時間;
    • Offset Number(通道偏移):指定那個通道需要數據偏移。
    • Offset(數值偏移):即在採集到的數據減去一個數字偏置。
  • ADC_Injected Conversions(ADC註入模式):暫時不需要。
  • Analog Watchdog1~3():看門狗功能,暫時不需要。

2.3 輸出設置

image

使用LL庫,剩下的按照常規配置就行。

2.4 MD5 設置

image

勾選Reset and Run,否則下載程式後單片機不會自動運行,複位後才會運行。

3 程式解讀

3.1 ADC初始化

void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
  LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_ADC12);    // 使能ADC時鐘

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);    // 使能GPIOA時鐘
  /**ADC1 GPIO Configuration
  PA0   ------> ADC1_IN1
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;   // 12bit解析度
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;// 數據右對齊
  ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;// 不使用低功耗模式
  LL_ADC_Init(ADC1, &ADC_InitStruct);
  ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;// 軟體觸發
  ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;// 不使用掃描模式
  ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;// 不使用斷續模式
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;// 單次觸發單次轉換
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_LIMITED;// 不使用DMA
  ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN; // 數據覆寫使能
  LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
  ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV1;// 使能內部時鐘1分頻作為ADC時鐘
  ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;// ADC採取獨立模式
  LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);

  /* Enable ADC internal voltage regulator *//*使能ADC內部的穩壓器*/
  LL_ADC_EnableInternalRegulator(ADC1);
  /* Delay for ADC internal voltage regulator stabilization. */
  /* Compute number of CPU cycles to wait for, from delay in us. */
  /* Note: Variable divided by 2 to compensate partially */
  /* CPU processing cycles (depends on compilation optimization). */
  /* Note: If system core clock frequency is below 200kHz, wait time */
  /* is only a few CPU processing cycles. */
  uint32_t wait_loop_index;
  wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
  while(wait_loop_index != 0)
  {
    wait_loop_index--;
  }

  /** Configure Regular Channel
  */
  LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_1);    // 設置通道1轉換次序為1
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_181CYCLES_5);// 採樣時間為181.5個ADC周期
  LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED);// 採樣模式為單端採樣
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

3.2 校準和啟動ADC

上述配置完後,使用LL庫還需要一些額外的代碼,ADC才可以正常工作。

void Mx_ADC_Start(void)
{
  uint8_t TimeDelta = LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES;

  LL_ADC_StartCalibration(ADC1,LL_ADC_SINGLE_ENDED);        // 開始校準
  while(LL_ADC_IsCalibrationOnGoing(ADC1))                  // 等待校準完成
  	;
  LL_ADC_SetCalibrationFactor(ADC1,LL_ADC_SINGLE_ENDED  LL_ADC_GetCalibrationFactor(ADC1,LL_ADC_SINGLE_ENDED));// 將校準向量寫  ADC1中

  while(TimeDelta > 0)  // 校準後延時
  {
  	TimeDelta--;
  }
  LL_ADC_Enable(ADC1); // 使能ADC
}

3.3 主函數配置

主函數就比較簡單,使用軟體觸發ADC轉換,待ADC轉換完成後,使用視窗將轉換數據經串口上傳到上位機。串口程式用的為匿名上位機。

while (1)
{
  LL_ADC_REG_StartConversion(ADC1);           // 用軟體觸發ADC轉換
  while(LL_ADC_REG_IsConversionOngoing(ADC1)) // 等待ADC轉換完成
  	;
  sent_data(LL_ADC_REG_ReadConversionData12(ADC1),0,0,0);// 使用匿名上機  ADC數據發送到電腦
  while(count)  // 適當延遲
  {
  	count--;
  }
}

3.4 匿名上位機程式

uint8_t BUFF[30];

void sent_data(uint16_t A,uint16_t B,uint16_t C,uint16_t D)
{
  int i;
  uint8_t sumcheck = 0;
  uint8_t addcheck = 0;
  uint8_t _cnt=0;
  BUFF[_cnt++]=0xAA;//幀頭
  BUFF[_cnt++]=0xFF;//目標地址
  BUFF[_cnt++]=0XF1;//功能碼
  BUFF[_cnt++]=0x08;//數據長度
  BUFF[_cnt++]=(A&0x00ff);//數據內容,小段模式,低位在前
  BUFF[_cnt++]=(A&0xff00)>>8;//需要將位元組進行拆分,調用上面的巨集定義即可。
  BUFF[_cnt++]=(B&0x00ff);
  BUFF[_cnt++]=(B&0xff00)>>8;	
  BUFF[_cnt++]=(C&0x00ff);//數據內容,小段模式,低位在前
  BUFF[_cnt++]=(C&0xff00)>>8;//需要將位元組進行拆分,調用上面的巨集定義即可。
  BUFF[_cnt++]=(D&0x00ff);
  BUFF[_cnt++]=(D&0xff00)>>8;
  //SC和AC的校驗直接抄最上面上面簡介的即可
  for(i=0;i<BUFF[3]+4;i++) 
  {
  	sumcheck+=BUFF[i];
  	addcheck+=sumcheck;
  }
  BUFF[_cnt++]=sumcheck;	
  BUFF[_cnt++]=addcheck;	

  for(i=0;i<_cnt;i++) 
  {
  	while ((USART1->ISR & 0X40) == 0)
    ; /* 等待上一個字元發送完成 */
  	USART1->TDR=BUFF[i];
  }//串口逐個發送數據
}

4 實驗波形

使用函數信號發生器,產生頻率為1kHz,幅值為3V的正弦波,經兩個2k電阻分壓後傳入ADC採集通道,電路圖如圖:
image
實驗波形在匿名上位機上顯示如圖:
image
可以看到:

  • 波形為正弦波
  • 最高值 1863 對應 1.501V
    證明ADC採集正確。

5 總結

至此完成了STM32最簡單的ADC單端採樣,STM32的ADC還有很多其他功能,待之後有時間再記錄。本文記錄難免有錯誤,如有錯誤,歡迎指出。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • OpenSSL 是一種開源的加密庫,提供了一組用於加密和解密數據、驗證數字證書以及實現各種安全協議的函數和工具。它可以用於創建和管理公鑰和私鑰、數字證書和其他安全憑據,還支持`SSL/TLS`、`SSH`、`S/MIME`、`PKCS`等常見的加密協議和標準。OpenSSL 的功能非常強大,可以用於... ...
  • # Unity進階開發-FSM有限狀態機 前言 我們在進行開發時,到了一定程度上,會遇到數十種狀態,繼續使用Unity的Animator控制器會出現大量的bool,float類型的變數,而這些錯綜複雜的變數與Animatator控制器如同迷宮版連線相結合會變得極其的複雜且無法良好維護擴展,出現一個B ...
  • 這是一篇入職3周.NET 實習開發的感悟 吐槽 開篇先吐槽一下吧! 首先吐槽的就是加班費的問題,公司加班費挺多,但是我是試用期(3個月)沒有加班費,但是公司帶我的組長特喜歡加班,老是問我加不加班,懂點人情的都會一起加班,雖然公司規定17.30下班,但是基本都是18.00才開始走人,然後加班一般都是8 ...
  • 在進行2D游戲開發時,跳躍是不可缺少的一個重要功能。但是我們在Unity開發時Unity本身的物理引擎並不能提供很好的的手感,下落的時候輕飄飄的,這操作起來顯然非常不舒服。所以,我們需要自己對跳躍進行優化,以此來獲得更好的手感。我們不難發現,在絕大多數2D游戲的跳躍中,下落的速度比上升的速度要快上很 ...
  • 一、背景: 微軟的.net core開發工具,目前來看,winform界面軟體還沒有打算要支持linux系統下運行的意思,要想讓c#桌面軟體在linux系統上運行,開發起來還比較麻煩。微軟只讓c#的控制台軟體支持在linux運行。 二、解決方案: 我想到的一個方案是自定義封裝軟體的System.Wi ...
  • bind介紹 在區域網環境中,一般我們要搭建DNS服務,使用的是BIND(Berkeley Internet Name Domain)軟體來實現,BIND提供了一個名為named(也叫named daemon)的服務程式,用於處理DNS查詢。 BIND 由 Internet Systems Cons ...
  • 1、當使用makefile自動推導的功能時編譯器報錯ccJS7JEh.s: Assembler messages: ccJS7JEh.s:5: Error: invalid instruction suffix for `push' ccJS7JEh.s:7: Error: invalid inst ...
  • 簡單來說就是一個文件傳遞的機制,首先創建/安裝一個硬碟,然後把前硬碟中的一部分文件先轉移到Linux系統上,再通過Linux系統轉移到創建的新硬碟,之後用虛擬機,把新硬碟裝在其中,就可以在新硬碟上做到一些功能了 前知識準備: Linux啟動流程: 1、首先Linux要通過自檢,檢查硬體設備有沒有故障 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...