目录
一、工程依赖的硬件及背景
二、设计目的
三、 建立工程
1.选择时钟源和Debug模式
2.配置系统时钟和ADC时钟
3.配置串口
4.配置ADC
5.设置TIM3
6.设置TIM4
7.配置中断
8.GPIO
四、代码修改
1.重新定义ADC回调函数
2.在主程序中编写数据发送代码
3.使能ADC和开启定时器
4.查看结果
在细说MCU的ADC模块单通道连续采样的实现方法-CSDN博客 https://blog.csdn.net/wenchm/article/details/140008718http://xn--https-rfa//blog.csdn.net/wenchm/article/details/140008718中,通过使能AD配置参数中的连续转换模式(Continuous Conversion Mode),并结合ADC中断,实现了连续采样。该例中,ADC的采样频率约为1.58 kHz,是通过设置ADC的时钟频率和采样时间得到的。实际中,有时希望ADC以给定的采样频率转换数据,譬如1 kHz。在这种情况下靠配置ADC时钟频率和采样时间的方法就非常不方便。
本例子使用定时器来控制ADC连续采样。
一、工程依赖的硬件及背景
文章依赖的硬件及工程配置参考本文作者的其他文章:细说MCU的ADC模块单通道连续采样的实现方法-CSDN博客 https://blog.csdn.net/wenchm/article/details/140008718http://xn--https-rfa//blog.csdn.net/wenchm/article/details/140008718
二、设计目的
信号源为TIM4的TIM_CHANNEL_1,管脚PA11,给ADC1_IN1输入信号;也可以用管脚PA5的LD2作为信号源给ADC1_IN1输入信号;
ADC1_IN1采集到信号后,按缓冲大小的规定,循环给串口发送数据;
ADC采集样品的频率由TIM3设置的规则控制;
三、 建立工程
1.选择时钟源和Debug模式
使用片外时钟晶体作为HSE的时钟源。将Debug设置为Serial Wire。
2.配置系统时钟和ADC时钟
将系统时钟(SYSCLK)频率配置为170 MHz,并设置ADC1的时钟为34 MHz。
3.配置串口
配置USART2模式(Mode)为异步(Asychronous),其他参数设置均保持默认(波特率为115200),不开启中断。将USART2的两引脚PA2和PA3均设置为上拉(Pull-up)。
4.配置ADC
配置ADC1的通道1(IN1),选择IN1 Single-ended;在下面的配置(Configuration)区,对几个参数进行调整:
- ADC的时钟预分频参数(Clock Prescaler)选择Asynchronous clock mode divided by 1,也就是不分频(前面的例子是分频256倍,目的是想得到所需要的采样频率)。本例将用定时器实现对采样频率的控制,所以ADC的时钟可以不用进行分频处理。
- 将ADC设置(ADC_Settings)参数栏中连续转换模式(Continuous Conversion Mode)设置为Disabled,即不使能,因为本例中ADC采样频率要通过定时器来控制。
- 转换结束选择(End Of Conversion Selection)参数仍保持单次转换结束(End of single conversion);由于目前只使用了一个ADC通道,还可以选择序列转换结束(End of sequence conversion),对结果没有影响。
- 在ADC规则转换模式(ADC_Regular_Conversion Mode)栏中,外部触发转换源(External Trigger Conversion Source)选择Timer 3 Trigger Out event,使用TIM3的触发输出作为ADC的触发源。
- 位于Rank下的采样时间选择2.5个周期。前面提到过,这个参数决定着ADC的转换时间。如果选择2.5个周期,则在12位分辨率时ADC的转换时间为2.5+12+0.5=15个周期。
- 使能ADC1的中断。
5.设置TIM3
TIM3的模式(Mode)区,选择时钟源(Clock Source)为内部时钟(InterClock);计数器的预分频因子设置为169,则定时器的时钟频率为系统频率的1/170,如果系统频率为170 MHz,则定时器的时钟频率为1 MHz;计数器的周期设置为999,则计数器的溢出频率为1MHz/1000 =1 kHz。在Trigger Output参数栏中将发事件设置为更新事件(Update Event)。
6.设置TIM4
TIM4的模式(Mode)区,选择时钟源(Clock Source)为内部时钟(InterClock);通道1选择PWM Generation CH1;GPIO管脚默认PA11;计数器的预分频因子设置为999,计数器的周期设置为8499,auto reload=Enable;Pulse=2125;
7.配置中断
将ADC1中断的优先级设为1。此外,由于将会用到HAL_Delay函数,所以要将tick timer中断的占式优先级设为0。
TIM4的全局中断的优先级设置为2;
8.GPIO
设置 PA5(LD2) 为GPIO OUTPUT,OUTput level默认LOW,PP,Pullup,High;别名LED;
四、代码修改
1.重新定义ADC回调函数
在主程序中重写回调函数HAL_ADC_ConvCpltCallback()和串口发数据的putchar函数,并且将它们放到main.c的注释对中:
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
ADC1ConvertedData[ADC1Data_index] = HAL_ADC_GetValue(&hadc1);
if(ADCSampleFlag == 0)
ADC1Data_index ++;
if(ADC1Data_index == ADC_CONVERTED_DATA_BUFFER_SIZE)
{
ADCSampleFlag = 1;
ADC1Data_index = 0;
}
}
//信号源
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
//串口打印
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 4 */
2.在主程序中编写数据发送代码
将数据发送代码放置到main函数的while(1)循环中。
while(1)
/* USER CODE BEGIN 3 */
if(ADCSampleFlag == 1)
{
for(uint16_t i=1;i<ADC_CONVERTED_DATA_BUFFER_SIZE;i++)
{
printf("ADC1ConvertedData[%d] = %d\r\n",i,ADC1Convertedata[i]);
}
ADCSampleFlag = 0;
}
HAL_Delay(1000);
/*USER CODE END 3 */
上述函数中用到的变量需要定义。仍然是将它们定义为全局变量,放到主程序中的注释中:
/*USER CODE BEGIN PV*/
uint16_t ADC1ConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];
uint16_t ADC1Data_index =0;
uint8_t ADCSampleFlag =0;
/*USER CODE END PV*/
其中,数组长度ADC_CONVERTED_DATA_BUFFER_SIZE可以定义到main.h中:
/* USER CODE BEGIN Private defines */
#define ADC_CONVERTED_DATA_BUFFER_SIZE(uint16_t) 65
/* USER CODE END Private defines */
同时,在main.c中,包含头文件stdio.h:
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
3.使能ADC和开启定时器
在主程序初始化代码中使能ADC中断,并开启定时器TIM3、TIM4。将HAL_ADC_Sta IT()、HAL_ADCEx_Calibration_Start()、HAL_TIM_Base_Start()、HAL_TIM_Base_Start_IT()和HAL_TIM_PWM_Start()放到while(1)之前, MX_ADC1_Init()之后的注释对中:
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim3);
HAL_TIM_Base_Start_IT(&htim4);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
/* USER CODE END 2 */
4.查看结果
把PA5(LD2)信号或者PA11(TIM4_CH1)信号施加信号到ADC1_IN1输入端PA0上,打开串口助手即可收到送上来的数据。
为了实测ADC的采样频率,同样可以配置PC3作为输出引脚,在回调函数HAL_ADC _ ConvCpltCallback()中加入控制PC3输出状态的语句,并通过示波器测量PC3引脚的输出 形,此时测得的频率为采样频率。
实测的PA5(LD2)信号:
实测的串口接收的数据: