学习记录一下
简单实现了adc采集波形数据,并通过vofa打印出波形
定时器配置
ADC配置
根据板子原理图,配置差分模式
设置dma
然后配置一下串口和时钟,生成工程,注意DMA搬运数据是需要时间的,因此需要有AdcConvEnd这样一个标志位,搬运完成之后再进下一次采集传输
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SAMP_NUM 1024
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint16_t ADC_1_buff[SAMP_NUM];
//uint16_t ADC_2_buff[SAMP_NUM];
__IO uint8_t AdcConvEnd = 0; // ADC DMA搬运完成标志
/* USER CODE END PV */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_1_buff,SAMP_NUM); // 开启ADC DMA采样
HAL_TIM_Base_Start(&htim1); // 使能定时器
while(!AdcConvEnd); // DMA搬运完成标志
// 打印波形数据
for(int i=0;i<SAMP_NUM;i++)
{
printf("%d\n",ADC_1_buff[i]);
}
}
/* USER CODE END 3 */
在stm32h7xx_it.c文件中找到
void DMA1_Stream1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
/* USER CODE END DMA1_Stream1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
AdcConvEnd = 1; // DMA传输完成
/* USER CODE END DMA1_Stream1_IRQn 1 */
}
串口重定向
// 串口重定向
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;
}
实际测试
上述只是实现的方式之一,实际应用也有很多其他的选择
// ADC校准
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET_LINEARITY, ADC_DIFFERENTIAL_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY, ADC_DIFFERENTIAL_ENDED);
// 启动ADC转换
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adcBuff_1,FFT_LENGTH); // enable ADC_1 DMA采样
HAL_ADC_Start_DMA(&hadc2,(uint32_t *)adcBuff_2,FFT_LENGTH); // enable ADC_2 DMA采样
HAL_TIM_Base_Start(&htim3); // 使能定时器3
比如将处理逻辑放在ADC中断回调函数中
// ADC中断回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
HAL_ADC_Stop_DMA(&hadc1); // 关闭 ADC_1 DMA采样
HAL_ADC_Stop_DMA(&hadc2); // 关闭 ADC_2 DMA采样
HAL_TIM_Base_Stop(&htim3); // 失能定时器3
// ----------------------------------------------------------------------------------数据处理开始----------------------------------------------------------------------------------//
for(int i=0;i<FFT_LENGTH;i++)
{
// adcBuff_1_f[i] =(float) (adcBuff_1[i] - 7075)/605 - 2;
// adcBuff_2_f[i] =(float) (adcBuff_2[i] - 7075)/605 - 2; // ADC数据转化为浮点数
adcBuff_1_f[i] =(float) (1.0 *adcBuff_1[i] - 8520);
adcBuff_2_f[i] =(float) (1.0 *adcBuff_2[i] - 8520 ); // ADC数据转化为浮点数
}
// 加窗处理
Add_Win_Fun(adcBuff_1_f, adcBuff_1_f_WIN, hanning_win_norm, FFT_LENGTH); // 对ADC_1数据加窗
Add_Win_Fun(adcBuff_2_f, adcBuff_2_f_WIN, hanning_win_norm, FFT_LENGTH); // 对ADC_2数据加窗
FFT_Cal(adcBuff_1_f_WIN,fft_inputbuf_1,fft_outputbuf_1,FFT_LENGTH);
FFT_Cal(adcBuff_2_f_WIN,fft_inputbuf_2,fft_outputbuf_2,FFT_LENGTH);
// for(int i =0;i<5;i++)
// {
// phase_diff[i] = phase_diff_1[i] - phase_diff_2[i]; // 相位差计算
// printf("%f\n",phase_diff[i]);
// }
// for(int i=0;i<FFT_LENGTH/2;i++) // 取一半长度的有用信息打印
// {
// //printf("%f\n",adcBuff_1_f[i]);
// //printf("%d\n",adcBuff_1[i]);
// printf("%f\n",fft_outputbuf_1[i]); // 打印FFT结果
// }
Phase = AP_FFT(adcBuff_1_f ,adcBuff_2_f ,FFT_LENGTH );
printf("%f\n",Phase);
// for(int i=0;i<FFT_LENGTH/2;i++) // 取一半长度的有用信息打印
// {
// printf("%f\n",adcBuff_2_f[i]);
// printf("%d\n",adcBuff_2[i]);
// // printf("%f\n",fft_outputbuf_1[i]); // 打印FFT结果
// }
//--------------------------------------------------------------------- 数据处理完成后,再开始启动下一次同步采样-------------------------------------------------------------------//
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adcBuff_1,FFT_LENGTH); // enable ADC_1 DMA采样
HAL_ADC_Start_DMA(&hadc2,(uint32_t *)adcBuff_2,FFT_LENGTH); // enable ADC_2 DMA采样
HAL_TIM_Base_Start(&htim3); // 重新使能定时器3
/* NOTE : This function should not be modified. When the callback is needed,
function HAL_ADC_ConvCpltCallback must be implemented in the user file.
*/
}