蓝桥杯嵌入式ADC检测篇章

        我们在本次ADC检测篇,使用的是DMA传输方式,DMA的使用可以减少CPU将外设数据搬运到RAM中,可以减少CPU资源的使用。首先是ADC1的初始化部分。

uint16_t adc11_value[10];  //ADC数据缓冲区
ADC_HandleTypeDef hadc1;   //ADC1的结构体
void MX_ADC1_Init(void)
{
  ADC_MultiModeTypeDef multimode = {0};  
  ADC_ChannelConfTypeDef sConfig = {0};  //规则组配置

  hadc1.Instance = ADC1; //ADC1
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV12;  //时钟分频
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;  //12位转换
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;  //数据右对齐
  hadc1.Init.GainCompensation = 0;  
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;  //扫描模式开启
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;  //关闭eoc中断
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;  //连续转换模式
  hadc1.Init.NbrOfConversion = 1;  //转换通道数量
  hadc1.Init.DiscontinuousConvMode = DISABLE;  //禁止不连续转换
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;  //软件触发
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;  //外部触发设为NONE
  hadc1.Init.DMAContinuousRequests = ENABLE;  //DMA请求
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;  //ADC过载
  hadc1.Init.OversamplingMode = DISABLE;

  sConfig.Channel = ADC_CHANNEL_11;  //通道11
  sConfig.Rank = ADC_REGULAR_RANK_1;  //规则组通道一
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;  //转换周期
  sConfig.SingleDiff = ADC_SINGLE_ENDED;  //单端模式
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
 
  HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);  //ADC自校准
  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc11_value,10);  //DMA传输
}

初始化部分根据cubemx设置好,选择连续转换,DMA请求。单端模式转换一个通道的电压值。

hdma_adc1.Instance = DMA1_Channel1;  //DMA1
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;  //ADC1请求DMA
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;  //外设到内存
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;  //外设自增
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;  //内存地址自增
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设半字传输
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;  //内存半字传输
hdma_adc1.Init.Mode = DMA_CIRCULAR;  //DMA循环传输
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;  //优先级低

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);   //外设连接

轮询方法

        轮询方法的关键点在于要在while循环中进行ADC转换,由于是软件触发,可以在我们需要的时候,开启ADC转换,避免了在不需要知道电压的情况下,ADC不停地转换。

uint32_t get_adc(ADC_HandleTypeDef *hadc)
{
		HAL_ADC_Start(hadc);  //开启ADC转换
		while(HAL_ADC_PollForConversion(hadc,1)) //判断ADC是否转换完成
		return HAL_ADC_GetValue(hadc);  //返回ADC值
}

float get_adc_adverage(ADC_HandleTypeDef *hadc,uint8_t ch, uint8_t time)
{
		    uint16_t ADC_PRIO = 0;  //静态变量
			uint32_t ADC_SUM = 0;
			for(int i=0;i<time;i++)
			{
				ADC_PRIO = get_adc(hadc);  //保存上一回的ADC的值
				ADC_SUM += ADC_PRIO;       //均值滤波算法
			}
			return ADC_SUM*3.3/4096/time;  //返回电压值
}

DMA中断模式

uint32_t adc_sum_filter,adc_sum=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc->Instance == ADC1)
	{
		for(int i=0;i<10;i++)
		{
			adc_sum += adc11_value[i];	//DMA存放数据的地址		
		}
		adc_sum_filter = adc_sum;       //保存转换值
		adc_sum = 0;
	}
}

        DMA中断结束的标志是在HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc11_value,10);10个数据发送完毕的时候,进入DMA中断,也就是进入ADC中断回调函数。处理我们收到的数据组,均值滤波。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值