文章目录
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, 否则会出现频谱混叠的现象,具体具体可看人家的博客: 奈奎斯特采样定理 (转载,侵权即删)