HAL庫教程12:ADC與DMA採集多路AD值

AD的基礎知識

  AD很複雜,其實也不復雜,因爲我們用的不多。
  AD:模擬量轉換數字量(模擬信號轉換數字信號)。
  ADC:模擬量轉數字量的轉換器。
  爲什麼需要AD呢?
  自然界宏觀的物理量都是連續的。而機器識別的信號0與1是離散的。爲了讓機器能夠採集、分析、儲存這些連續的量,所以要把需要被模擬的量轉換爲數字量。
  主要的參數:採樣精度與轉換速度。
  採樣精度,也叫作分辨率。如果0-100攝氏度用8位AD來儲存的話,精度計算?
  0000 0000 —— 0攝氏度
  1111 1111 —— 100攝氏度
  100/256 = 0.39攝氏度,0.39就是最小份的分辨率,也就是採樣精度.沒有辦法表現出0.2度
  100/65536 = 0.0015,16位的AD,精度就很高了。
  轉換速度
  從啓動到出結果用的時間,一般來說越快越好。與精度不可兼得。被單位時間採樣數量影響。採樣多,速度不會很快。
  STM32F4使用的AD是逐次逼近型ADC,它產生一系列比較電壓VR,但它是逐個產生比較電壓,逐次與輸入電壓分別比較,以逐漸逼近的方式進行模數轉換的。它比並聯比較型ADC的轉換速度慢,比雙分積型ADC要快得多,屬於中速ADC器件。

多通道AD採集需要使用DMA

  在STM32的手冊中,我們發現,不論是單次採集還是多次採集,轉換完成的數據都會放在同一個地方。
在這裏插入圖片描述
  由於DR寄存器不是一個數組,而是一個字節,所以只能保存最新的轉換結果。例如,通道1和通道2都使用,通道1的轉換結果放在DR寄存器。通道2轉換完畢以後,就會覆蓋通道1的結果。
  程序裏,當然可以通過一些處理,讓通道1的結果在被覆蓋之前就保存好。不過,運用STM32的DMA功能,可以更好地解決結果被覆蓋的問題。
在這裏插入圖片描述

DMA的介紹

在這裏插入圖片描述
在這裏插入圖片描述
  重點:用於高速搬運數據,還無需CPU干預。 因此在多通道採集模擬量是,我們可以建立一個數組,用於儲存AD轉換的數據。一旦ADC_DR寄存器裏有了新的數據,就把新數據放在數組裏。一會兒ADC_DR有了一個新的數據,就放在數組下一位。數組裝滿以後?根據需求來。我們設置的是循環模式,也就是再來一遍,覆蓋之前的數據。

使用CubeMX配置DMA+多通道ADC

  我使用的板子,有兩路NTC熱敏電阻分別接在PC0與PC1上,我們把這兩個引腳用作ADC1的通道10與11。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

啓用DMA

  新建AD.c與AD.h文件,設置全局的接收數組與計數器。

//AD.c
uint32_t AD_Buf[ADC_CHANNEL_CNT];
uint32_t DMA_CNT = 0;

//AD.h
#define ADC_CHANNEL_CNT     2

extern uint32_t AD_Buf[ADC_CHANNEL_CNT];
extern uint32_t DMA_CNT;

  在主函數中可以藉助HAL庫提供的HAL_ADC_Start_DMA()函數,開啓ADC的DMA功能,指定接收數組爲AD_Buf,並指定接收的字符數爲ADC_CHANNEL_CNT。

  DMA通常用於處理大量數據,但是目前,每秒發送兩個數據,數據量很小,沒有體現出DMA的特點。雖然只打印了兩個數據,但是DMA到底採集了多少數據?已知DMA在AD轉換完成以後“搬運”數據,所以我們可以在ADC轉化完成的中斷函數裏做計數。

//AD.c
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  if(hadc==(&hadc1))
  {
    DMA_CNT++;
  }    
}
//main.c main()
  while (1)
  {
    HAL_Delay(1000);
    for(int i=0;i<ADC_CHANNEL_CNT;i++)
    printf("CH%d value = %d \n",i,AD_Buf[i]&0xFFF);
    printf("DMA採集數據的次數是 %d",DMA_CNT);
    DMA_CNT=0;
  }

  我看到的現象是,DMA_CNT大約是15W,每次兩個數據,也就是DMA1秒鐘搬運了30W個字節。可以想象,如果不是AD轉換速度限制,DMA還可以更快一點.
  至於採集過來的AD值到底怎麼用,那就是另一個問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章