STM32 HAL库学习(三)ADC采样以及printf的使用

ADC输出的电压值经转换后一般为一个浮点数,要将其打印到串口则需要对串口输出函数做一个调整。

首先是printf函数的重定向,将一下代码加入到usart.c中,完成后便可以用printf函数输出字符串到串口中,而要输出浮点数,则还需在“项目/建立设置/C Linker/Miscellaneous/Other options”中添加“-u _printf_float”

#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);
	return ch;
}
#endif
int _write(int file,char*ptr,int len)
{
	int Dataldx;
	for(Dataldx = 0;Dataldx < len;Dataldx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}

接下来是配置ADC采样,ADC采样可以配置为单通道、多通道,连续、非连续等采样模式,传输获取采样值的方式也有查询获取、中断获取以及DMA获取等方式,都有提供相应的HAL库函数。

STM32F070的ADC时钟来源主要有两种方式:

  • 直接来源于HSI 14MHZ,也是可配置的最大时钟频率,对应在CubeMX中的Clock Prescaler配置为Asynchronous clock mode
  • 来源于APB时钟的2分频或者4分频(但最大都不能超过14MHZ)

获取ADC采样值的方式

1、查询方式获取ADC采样值

  查询方式主要用到的函数是HAL_ADC_Start()、HAL_ADC_PollForConversion()以及HAL_ADC_GetValue(),其中,HAL_ADC_Start是软件开始ADC转换,PollForConversion则等待ADC转换完成,当转换完成后,既可在主函数中调用HAL_ADC_GetValue获取采样值,进行相应的转换和输出。

uint32_t value = 0;
float vol = 0;
while(1)
{
   /*USER CODE BEGIN WHILE*/
   HAL_ADC_Start(&hadc);
   HAL_ADC_PollForConversion(&hadc,HAL_DELAY_MAX);
   value = HAL_ADC_GetValue(&hadc);
   vol = (float)(value *3.3/4096);
   printf("%.2f",vol);
   HAL_Delay(1000);
   /*USER CODE END WHILE*/
}

2、DMA中断方式 

当ADC采样方式配置为连续采样时,可以借助DMA对采样值进行存储,当DMA传输完成时产生中断,再在中断函数中对采样到的数据进行处理。具体步骤是:在CubeMX中配置DMA Request为ADC,对应的选择通道DMA1 Channel1,数据宽度选择word(因为ADC采样值类型为uint32_t),generate code。在main函数中调用HAL_ADC_Start_DMA(),配置DMA数据存储的位置以及传输的数据个数。假设设置数据个数为100,则当ADC采样并转换100个数据后,DMA这边接收到100个数据后则会产生DMA中断。而当DMA中断产生时,HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)先是判断是传输一半数据中断标志还是传输完成中断标志,再根据绑定的句柄调用相应的回调函数。而当选择ADC DMA传输时,DMA传输完成后其回调函数会调用 HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc),因此只需重写该函数进行数据处理即可。当DMA传输完成时会调用ADC_DMAConvCplt(),而该函数里最终是调用HAL_ADC_ConvCpltCallback()函数来处理采样所得的数据。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
   uint32_t value = 0;
   float vol = 0;
   value = ADC_Data[0];
   vol = (float)(3.3*value);
   vol = (float)vol/4096;
   printf("%.3f",vol);
   printf("\r\n");
}

 

 

  • 13
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下面是使用HAL库编写的在STM32F407上使用定时器触发ADC采样的示例代码。 首先需要配置ADC和定时器的初始化参数。 ```c ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig; /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void MX_TIM2_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; htim2.Instance = TIM2; htim2.Init.Prescaler = 8399; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 1999; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } } ``` 在主函数中,开启定时器和ADC: ```c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); MX_ADC1_Init(); HAL_TIM_Base_Start(&htim2); HAL_ADC_Start(&hadc1); while (1) { if (HAL_ADC_PollForConversion(&hadc1, 1000) == HAL_OK) { uint32_t adc_value = HAL_ADC_GetValue(&hadc1); printf("ADC value: %ld\n", adc_value); } } } ``` 在这个示例中,定时器的时钟频率为84MHz / (8399 + 1) = 10 kHz,定时器的周期为(1999 + 1) / 10 kHz = 200ms,ADC采样时间为3个时钟周期,因此每200ms会触发一次ADC采样。 需要注意的是,这个示例中使用了轮询模式进行ADC采样,也可以使用DMA模式进行采样以提高效率。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值