ADC+TIM+DMA采集交流
前言
本文主要講解定時器觸發(fā)ADC去采集交流信號,DMA把數據搬移到內存。
所需工具:
- 開發(fā)板:STM32F103C8T6
- STM32CubeMX
- IDE: Keil-MDK
相關文章:
- STM32HAL ADC+TIM+DMA采集交流信號 基于cubemx(二)
- STM32cubemx ADC+TIM+DMA超頻采樣
模式簡介
ADC+TIM+DMA采集交流信號是電賽中使用范圍最為廣泛的一個技術。這個模式下單個ADC可以實現0-1M的任意可調采樣率,采集20khz一下的信號輕輕松松。
F1的ADC支持許多觸發(fā)信號,這里選擇TIM3的TRGO事件作為觸發(fā)信號,其中TRGO選擇更新時間來引起。(這段新手看不懂沒關系,不耽誤使用)
工程建立
時鐘配置
ADC配置
相對于ADC采集直流,這里的觸發(fā)源不是軟件上的一行代碼來觸發(fā),而是選擇外部觸發(fā),這里選擇TIM3的TRGO信號。
對于新手來說這里可能有疑惑,換成硬件觸發(fā)有什么好處嗎?查看系列的上一篇文章,軟件觸發(fā)ADC采樣一次,需要寫幾行代碼,才能讓他們采集一次,如果我們想實現100hz的采樣率,可以設置一個100hz的定時器中斷,在中斷里用代碼(軟件)觸發(fā)ADC采樣,這樣確實可以達到100hz采樣的效果。可是如果100k采樣呢?CPU代碼執(zhí)行的速度是有限的,100hz可以勉強達到,100k就來不及了。但是我讓TIM這樣的硬件去觸發(fā)ADC采樣,ADC采集完成后,DMA硬件搬運數據,整個采集過程不需要CPU參與。
直觀上看就是你告訴ADC,TIM,DMA你們仨給我100k采樣率采集1000個點.說完這句話后,他們三就去采集了,CPU只需要等他們采集完成就可以。采集過程CPU不管的,也就是不需要寫任何代碼。
DMA配置為normal模式。如果配置成circular的話,ADC采集完成指定個數后,不會停下來,不方便管理。讀者可以修改成circular看看效果。
采樣率控制在100kz,那么TIM就需要產生100khz的TRGO的信號,我們這里選擇的更新時間產生TRGO信號,那么TIM3的計數器從0計算到ARR的頻率為100khz。于是我們這里設置PSC=0,ARR=720-1。換算下: 72 M 720 = 100 k \frac{72M}{720}=100k 72072M?=100k
配置串口
代碼生成
代碼編寫
串口重定向
#include <stdio.h>
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
這里是串口重定向的主體部分
#include <stdio.h>
在mian.c里面包含stdio.h頭文件,mian.c里面就可以printf了。別的.c文件同理。
勾選MicroLIB庫,否則沒法使用printf
ADC采集代碼
uint16_t adc_buff[200];//存放ADC采集的數據
/*
AdcConvEnd用來檢測ADC是否采集完畢
0:沒有采集完畢
1:采集完畢,在stm32f1xx_it里的DMA完成中斷進行修改
*/
__IO uint8_t AdcConvEnd = 0;
在main.c里面定義兩個變量,一個存放ADC采集到的數據,一個標志ADC是否采集完畢。
特別注意__IO修飾AdcConvEnd。他的含義是volatile。避免AdcConvEnd被MDK優(yōu)化掉。
HAL_TIM_Base_Start(&htim3); //開啟定時器3
HAL_ADCEx_Calibration_Start(&hadc1); //AD校準,F4不用校準沒用這行函數。
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buff, 200); //讓ADC1去采集200個數,存放到adc_buff數組里
while (!AdcConvEnd) //等待轉換完畢
;
for (uint16_t i = 0; i < 200; i++)
{
printf("%.3f\n", adc_buff[i] * 3.3 / 4095); //數據打印,查看結果
}
這里寫的采集程序,如每一步的含義都在注釋里寫明了。
希望讀者養(yǎng)成隨手寫注釋的好習慣。
extern uint8_t AdcConvEnd;//引入外部變量
AdcConvEnd = 1;
ADC采集,DMA搬運,當DMA搬運結束后,整個采集過程也就完成了。DMA搬運結束,程序會接收到DMA中斷,就會執(zhí)行DMA1_Channel1_IRQHandler函數,告訴CPU,采集完畢了。程序上則根據AdcConvEnd的變化,得知采集完畢。
硬件連接
引腳 | 連接對象 | 釋義 |
---|---|---|
PA9 | CH340的RX | 單片機的TX連接CH340的RX |
PA10 | CH340的TX | 單片機的RX連接CH340的TX |
PA0 | 信號發(fā)生器信號端 | 圖中紅線 |
GND | 信號發(fā)生器地 | 跟信號發(fā)生器共地 |
上面總共有STlinkV2,ch340,供電線,信號發(fā)生器接過來的夾子線
運行結果
ADC去采集信號發(fā)生器產生的1k正弦信號,數據打印到VOFA上,結果如圖。
為了驗證采樣率是否是100k,ADC去采集信號發(fā)生器產生的5k信號,打印到VOFA上,可以看到一個周期20個點。 5 k ? 20 = 100 k 5k*20=100k 5k?20=100k采樣率為100k驗證完畢。
VOFA的使用可以在電賽小站里查看到教程。
練習
-
嘗試在例程的基礎上更改采樣率200k、500k等,看看效果。
練練手,打野怪刷熟練度。
-
思考如何借助均值濾波來提高采樣精度,并付諸實踐。
這是最容易實現的降噪方法。你可以不會FIR、滑動濾波器等,這個還是要會的。元氣騎士拿破舊的手槍也是可以通關的嘛。
提示:如果你沒什么思路請看這里。比如我們去采集1k的正弦,想采集一個周期100個點,你可以設置采樣率為100k,那么采集100個點就結束了。也可以設置采樣率為200k,然后一個周期采集200個點,然后每兩個點取平均,這樣就可以達到2次均值濾波。
啥?還是不懂?就是數組的下標0和下標1取平均( X [ 0 ] + X [ 1 ] 2 = Y [ 0 ] \frac{X_{[0]}+X_{[1]}}{2}=Y_[0] 2X[0]?+X[1]??=Y[?0])作為第一個采樣點,下標2和下標3取平均( X [ 2 ] + X [ 3 ] 2 = Y [ 1 ] \frac{X_{[2]}+X_{[3]}}{2}=Y_{[1]} 2X[2]?+X[3]??=Y[1]?)作為第二個采樣點。
這個方法有個高級的稱呼:過采樣。H7自帶硬件過采樣STM32H7 ADC 過采樣對精度的影響效果
-
先以100k的采樣率采集一組信號,再通過程序更改定時的頻率來將采樣率改成200k,再采集一組數據。期間不能重新燒錄代碼
學會動態(tài)更改采樣率。
提示一下可以采用這種方式更改:
TIM1->ARR=...; TIM1->PSC=...;
-
如果你會測量頻率,嘗試控制采樣率始終是待測信號的100倍。
這技巧在FFT變化方面對提高精度有奇效。
后記
本文章收錄于:
唐承乾的電賽小站
本文為系列文章中的冰山一角,歡迎進入小站查看。
配套程序:文章來源:http://www.zghlxwxcb.cn/news/detail-435081.html
STM32的ADC+DMA+TIM采集交流信號.zip-嵌入式文檔類資源-CSDN文庫文章來源地址http://www.zghlxwxcb.cn/news/detail-435081.html
到了這里,關于STM32HAL ADC+TIM+DMA采集交流信號 基于cubemx的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!