stm32之ADC

ADC是什么?模拟数字转换器(Analog-to-Digital Converter)。

一、ADC概述

        stm32f013c8t6有两个ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道、2个内部通道(温度传感器、内部参考电压)。实际stm32f013c8t6只有10个通道(IN0-IN9)+ 2个内部通道。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右 对齐方式存储在16位数据寄存器中。

        ADC的输入时钟不得超过14MHz(常用12MHz),它是由PCLK2经分频产生。

1.1、电压输入范围

        ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由 VREF-VREF+ VDDA VSSA、这四个外部引脚决定。一般把 VSSA VREF- 接地,把 VREF+ VDDA 3V3,得到 ADC 的输入电压范围为:0~3.3V

1.2、通道

外部的 16 个通道在转换时又分为规则通道注入通道,其中规则通道最多有 16 路,注入通道最多
4 路。
规则通道: 规则通道就是很规矩的意思,常用的就是规则通道
注入通道: 可以理解为VIP,有特权的人,可以插队

1.3、转换顺序

        每个ADC 只有一个数据寄存器(DR), 16 个通道一起共用这个寄存器,所以需要指定规则转换通道的转换顺序。规则通道中的转换顺序由三个寄存器控制:SQR1 SQR2 SQR3 ,它们都是 32 位寄存器。 SQR 寄存器控制着转换通道的数目和转换顺序,只要在对应的寄存器位SQx 中写入相应的通道,这个通道就是第x 个转换。
注入通道的转换顺序也是通过注入寄存器来控制

1.4、触发源

        ADC 转换可以由 ADC_CR2(控制寄存器) 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候停止转换。
        ADC 还支持触发转换,这个触发包括内部定时器触发和外部 IO 触发。具体选择哪一种触发源,由 ADC_CR2(控制寄存器 ) 的 EXTSEL[2:0] JEXTSEL[2:0] 位来控制

1.5、转换时间

       ADC是挂载在APB2总线(PCLK2)上的,经过分频器得到ADC时钟(ADCCLK),最高 14 MHz

转换时间  采样时间  + 12.5 个周期
 12.5 个周期是固定的,一般我们设置 PCLK2=72M ,经过 ADC 预分频器能分频到最大的时钟只能
12M ,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us

 

1.6、数据寄存器

规则组的数据放在 ADC_DR 寄存器, 注入组的数据放在 JDRx

1.7、模式

扫描模式
关闭:只转换 ADC_SQRx ADC_JSQR 选中的第一个通道
打开:扫描所有被 ADC_SQRx ADC_JSQR 选中的所有通道
单次转换:
        ADC只执行一次转换。该模式既可通过设置 ADC_CR2 寄存器的 ADON ( 只适用于规则通道) 启动也可通过外部触发启动 ( 适用于规则通道或注入通道 ) ,这时 CONT 位为 0 。 一旦选择通道的转换完成:
● 如果一个规则通道被转换:
        ─ 转换数据被储存在 16 ADC_DR 寄存器中
        ─ EOC( 转换结束 ) 标志被设置
        ─ 如果设置了 EOCIE ,则产生中断。
● 如果一个注入通道被转换:
        ─ 转换数据被储存在 16 位的 ADC_DRJ1 寄存器中
        ─ JEOC( 注入转换结束 ) 标志被设置
        ─ 如果设置了 JEOCIE 位,则产生中断。
连续转换:转换一次之后,立马进行下一次转换,此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。每个转换后:
● 如果一个规则通道被转换:
        ─ 转换数据被储存在 16 位的 ADC_DR 寄存器中
        ─ EOC( 转换结束 ) 标志被设置
        ─ 如果设置了 EOCIE ,则产生中断。
● 如果一个注入通道被转换:
        ─ 转换数据被储存在 16 位的 ADC_DRJ1 寄存器中
        ─ JEOC( 注入转换结束 ) 标志被设置
        ─ 如果设置了 JEOCIE 位,则产生中断

二、单规则通道 case

描述: PA0(ADC通道0) 接入MQ2(烟雾传感器)的A0口,然后通过串口打印出来
CubeMX主要配置:
main函数主要代码如下:
int main(void)
{
  uint32_t result;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();

  while (1)
  {
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, 50);
	result = HAL_ADC_GetValue(&hadc1);
	printf("result = %f\r\n", 3.3/4096 * result);
	HAL_Delay(500);
  }
}

2.1、 MX_ADC1_Init

主要是来装配数据,并初始化,两个主要的步骤是HAL_ADC_InitHAL_ADC_ConfigChannel

void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig = {0};


  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  // adc 通用配置
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  
  // 规则通道配置
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

2.2、HAL_ADC_Init

2.3、HAL_ADC_ConfigChannel

2.4、HAL_ADC_Start

2.5、HAL_ADC_PollForConversion

以上函数暂时不分析了,等有时间再处理,ADC代码太长了。。。

三、双规则通道 case

描述:
PA0(ADC通道0) 接入MQ2(烟雾传感器)的A0口,然后通过串口打印出来
PA1(ADC通道1) 接入轨迹检测传感器(烟雾传感器)的A0口,然后通过串口打印出来
CubeMX主要配置:
主要代码如下:
int main(void)
{
  uint32_t result;
  uint32_t result1;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  HAL_ADCEx_Calibration_Start(&hadc1);
  while (1)
  {
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, 50);
	result = HAL_ADC_GetValue(&hadc1);

	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, 50);
	result1 = HAL_ADC_GetValue(&hadc1);
		
	printf("result = %f\r\n", 3.3/4096 * result);
	printf("result1 = %f\r\n", 3.3/4096 * result1);
	HAL_ADC_Stop(&hadc1);
	HAL_Delay(1000);
  }
}

四、双规则通道 case(关闭扫描模式)

完整代码

核心代码如下

uint16_t ADC_Read(uint32_t Channel)
{
	ADC_ChannelConfTypeDef sConfig = {0};
	sConfig.Channel = Channel;                                         /* 通道 */
	sConfig.Rank = ADC_REGULAR_RANK_1;                              
	sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;                  /* 采样时间 */
	if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)             
	{
		Error_Handler();
	}
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
	return (uint16_t)HAL_ADC_GetValue(&hadc1);
}


  while (1)
  {
	result = ADC_Read(ADC_CHANNEL_0);
	result1 = ADC_Read(ADC_CHANNEL_1);
	printf("result = %f\r\n", 3.3/4096 * result);
	printf("result1 = %f\r\n", 3.3/4096 * result1);
	HAL_Delay(1000);
  }

五、注入通道

待补充

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俯仰一世_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值