文章目錄
- STM32 HAL庫 CUBEMX配置 ADC采集
-
- 軟硬體型号
- 1.單通道不定時任意時刻采集信号
-
- CUBEMX配置
- 代碼添加
- 2.單通道ADC采集+DMA傳輸
-
- CUBEMX添加配置
- 代碼添加
- 3.定時器觸發轉換(1khz)+DMA傳輸
-
- CUBEMX配置
- 代碼添加
- 采集頻率滿足條件
STM32 HAL庫 CUBEMX配置 ADC采集
軟硬體型号
正點原子阿波羅STM32F428IG開發闆
STM32CUBEMX+KEIL5程式設計
STM32F4 1.24.2 庫版本
1.單通道不定時任意時刻采集信号
CUBEMX配置
1.打開RCC
2.配置時鐘樹
3.選擇ADC通道
4.使能持續轉換
5.開啟中斷
簡單說一下這個配置,
- Clock Prescaler 時鐘預分頻 為保證采集精度最好使分頻後時鐘在36Mhz以下
- Resolution 分辨率 有8位,10位,12位的,這裡選擇最高的就行
- Date Alignment 資料對齊方式 我們ADC轉換後的資料存在寄存器中,12位的,這12位是左對齊右對齊都行
- Scan Conversion Mode 掃描模式,當我們使用多通道采集的時候需要使能他去輪詢讀取每個通道值
- Continous Conversion Mode 持續轉換模式,一般我們都是連續轉換,這個我們需要使能他
- Discontinous Conversion Mode 與上邊序号5相反
-
DMA Continous Requests 不經過cpu去提取轉換的資料,直接交給DMA操作。具體的使用在下邊會講解
更詳細的講解可以看下邊這個部落格(轉載,侵權即删)
ST CubeMX翻譯
6.開啟USART
7.選擇KEIL5模式
8.生成獨立檔案
9.生成代碼
代碼添加
10.代碼中序列槽重定向
//usart.h 添加
#include "stdio.h"
//usart.c 添加
int fputc(int ch, FILE *f) //輪詢方式,逾時機制,輸出到序列槽函數重定義
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, sizeof(ch), 0xFFFF);
return ch;
}
/*HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)*/
int fgetc(FILE *f) //輪詢方式,逾時機制,接收到序列槽函數重定義
{
uint8_t ch;
HAL_UART_Receive(&huart1, (uint8_t *)&ch, sizeof(ch), 0xFFFF);
return ch;
}
11.ADC采集準備
// adc.h
uint16_t GET_ADC(ADC_HandleTypeDef hadc,uint32_t ch);
uint16_t GET_ADC_AVERAGE(ADC_HandleTypeDef hadc,uint32_t ch,uint8_t times);
//adc.c
//獲得ADC值
//ch: 通道值 0~16,取值範圍為:ADC_CHANNEL_0~ADC_CHANNEL_16
//傳回值:轉換結果
uint16_t GET_ADC(ADC_HandleTypeDef hadc,uint32_t ch)
{
ADC_ChannelConfTypeDef ADC_ChanConf;
ADC_ChanConf.Channel=ch; //通道
ADC_ChanConf.Rank=1; //第1個序列,序列1
ADC_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采樣時間
ADC_ChanConf.Offset=0;
HAL_ADC_ConfigChannel(&hadc,&ADC_ChanConf); //通道配置
HAL_ADC_Start(&hadc); //開啟ADC
HAL_ADC_PollForConversion(&hadc,10); //輪詢轉換
return (uint16_t)HAL_ADC_GetValue(&hadc); //傳回最近一次ADC1規則組的轉換結果
}
//擷取指定通道的轉換值,取times次,然後平均
//times:擷取次數
//傳回值:通道ch的times次轉換結果平均值
uint16_t GET_ADC_AVERAGE(ADC_HandleTypeDef hadc,uint32_t ch,uint8_t times)
{
uint32_t temp_val=0;
uint8_t t;
for(t=0;t<times;t++)
{
temp_val+=GET_ADC(hadc,ch);
HAL_Delay(5);
}
return temp_val/times;
}
12.主函數采集列印
//main.c 添加
uint16_t temp_adc_value;
float AD_Value;
while (1)
{
/* USER CODE END WHILE */
temp_adc_value=GET_ADC_AVERAGE(hadc1,ADC_CHANNEL_0,20);
AD_Value=temp_adc_value*3.3/4096;
printf("\r\n %f \r\n",AD_Value);
printf("\r\n The adc value is %f \r\n",AD_Value);
HAL_Delay(300);
/* USER CODE BEGIN 3 */
}
這是上邊實驗的源碼,需要的可以下載下傳 工程源碼
2.單通道ADC采集+DMA傳輸
CUBEMX添加配置
說明:在前邊配置好時鐘,ADC通道和序列槽的基礎上進行添加。
1.添加DMA通道
2.選擇對應的ADC通道
3.選擇循環模式
4.使能ADC的DMA采集
代碼添加
5.重新生成檔案在main函數添加代碼
//main函數中添加
uint16_t temp_ADC_Value; //暫時存儲DMA從DC通道轉移的數值
float ADC_Value; //換算後的電壓值
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&temp_ADC_Value, 100);
HAL_Delay(1);
while (1)
{
/* USER CODE END WHILE */
ADC_Value= (float)(temp_ADC_Value) / 4096 * 3.3;
printf("adcValue= %f V \r\n",ADC_Value);
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
3.定時器觸發轉換(1khz)+DMA傳輸
CUBEMX配置
1.關閉ADC持續轉換
2.選擇定時器觸發模式
我這裡選擇的是定時器的通道二作為觸發源,并設定成上升沿觸發
3.打開定時器時鐘并配置PWM模式
4.配置定時器頻率
這裡的定時器在AHP1 TIME CLOCK總線上,頻率為90Mhz,先将他90預分頻,降為1Mhz,重裝載值設定成1000,此時采集頻率為1khz,關于PWM的占空比,CCR這裡設定成500,占空比%50
代碼添加
5.main函數添加
//main函數
uint16_t temp_ADC_Value;
float ADC_Value;
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); //開啟定時器PWM模式
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&temp_ADC_Value, 100);
HAL_Delay(1);
while (1)
{
ADC_Value=(float)temp_ADC_Value*3.3/4096;
printf("%f",ADC_Value);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
采集頻率滿足條件
采集頻率需要滿足奈奎斯特定律,fs>fh/2, 否則會出現頻譜混疊的現象,具體具體可看人家的部落格: 奈奎斯特采樣定理 (轉載,侵權即删)