stm32F407的ADC

stm32连接各种外设的传感器,如:红外测距、温度、气压等传感器,都是通过ADC接口连接的。

一、任务

  1. 测量按键(WAKE_UP)的按下和放开的电压
  2. 测量外接的红外测距仪感应的距离和电压
  3. 两个LED灯分别用于显示测量过程中

二、硬件

  1. LED:指示灯
    • LED7<-->PF7
    • LED8<-->PF8
  2. 红外测距仪
    • OUT引脚<-->PF6(此引脚设置为ADC3的IN4)
    • GND<-->GND(开发板上任意一个)
    • VCC<-->3.3V(开发板上任意一个)
  3. 轻触开关
    • WAKE_UP<-->PA0(此引脚设置为ADC1的IN0)

三、配置

  1. SYS、RCC、USART等配置同之前的配置;
  2. ADC配置:Analog标签下
    • ADC1:ADC1-->IN0-->Parameter Setting(默认)-->NVIC Setting(启用中断)-->GPIO setting(系统默认引出为PA0引脚)
    • ADC3:GPIO-->PF6-->鼠标点击-->ADC3_IN4-->其他设置同ADC1即可
    • 在GPIO标签和Analog标签下,都可以启用ADC功能,一个根据ADC的通道进行配置(ADC的通道已经绑定了引脚对应的引脚号),一个是根据GPIO的引脚号进行配置,方式都是一样的。
    • ADC的中断功能一定要开启

四、程序流程

同中断、USART、TIM等功能开发,ADC的开发也涉及到中断,因此也是通过调用回调函数实现功能。

main.c-->stm32f4xx_hal_adc.c-->main.c

main.c(启动ADC)

main.c文件中,通过调用ADC中断启动函数,开启ADC功能。

  1. 非阻塞式启动ADC(中断,推荐)

    HAL_ADC_Start_IT(&hadc3);
    
  2. 阻塞式启动ADC:

    HAL_ADC_Start(&hadc1);
    

main.c(实现回调函数或数据接收)

  1. 非阻塞式(重写回调函数)
    • HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)是一个虚函数,在stm32f4xx_hal_adc.c文件中
    • 同TIM\USART等,回调函数只有一个,因此,第一步是需要判断传入结构体是哪个ADC接口
    • 下面代码中ADC1用于检测按键电压,ADC3用于检测红外测距仪电压
    • HAL_ADC_GetValue函数用户获取ADC的值,单位是毫伏
    • 注意电压的换算方式:ADC是12位,因此最大值4096(2的12次方)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    if(hadc->Instance==ADC1) {
        ADC_Value=HAL_ADC_GetValue(&hadc1);
        ADC_Volt=ADC_Value*3.3*1000/4096;
        send_USART_Data();
        led7_off();
    }
    if(hadc->Instance==ADC3) {
        ADC_Value=HAL_ADC_GetValue(&hadc3);
        ADC_Volt=ADC_Value*3.3*1000/4096;
        send_USART_Data();
        led8_off();
    }
}
  1. 阻塞式调用

    阻塞式调用分为两个步骤:启动对应的ADC,然后进行判断ADC是否执行成功,执行成功后就活区ADC的值。

    • HAL_ADC_Start(&hadc1);启动ADC1
    • (HAL_ADC_PollForConversion(&hadc1, 10)==HAL_OK)判断ADC1是在规定超时时间内否执行成功
    • HAL_ADC_GetValue(&hadc1);获取ADC1的值
void get_ADC_Value() {
    HAL_ADC_Start(&hadc1);
    led7_on();
    if(HAL_ADC_PollForConversion(&hadc1, 10)==HAL_OK) {
        ADC_Value=HAL_ADC_GetValue(&hadc1);
        ADC_Volt=ADC_Value*3.3*1000/4096;
    }
    send_USART_Data();
    led7_off();
    HAL_ADC_Stop(&hadc1);
}

五、其他

  1. 推荐使用非阻塞模式,更加优雅而且效果更好;
  2. 开发板自带的adc转换器式12位长度,这也是转换精度
  3. 几个常用ADC的函数:

    • 启动函数:

      //查询,阻塞方式,启动ADC
      HAL_StatusTypeDef    HAL_ADC_Start(ADC_HandleTypeDef* hadc);
      //查询,阻塞方式,停止ADC
      HAL_StatusTypeDef    HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
      //中断,非阻塞方式,启动ADC
      HAL_StatusTypeDef    HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
      //中断,非阻塞方式,停止ADC
      HAL_StatusTypeDef    HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
      
    • 读取ADC数据函数 ~~~C uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);

    • 参数1:hadc,ADC实例指针。
    • 返回值:uint32_t,ADC转换结果。 ~~~
    • 查询方式,阻塞式A/D转换HAL库函数

      HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);
      参数1:hadc,ADC实例指针。
      参数2:Timeout,超时时间。
      返回值:HAL_StatusTypeDef,函数执行状态。
      
    • 中断方式,非阻塞式回调

      void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
      
  4. ADC的几个概念

     * 量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。
     * 转换位数:量化过程中的量化位数n。 A/D转换后的输出结果用n位二进制数来表示。
     【例】:10位ADC的输出值就是0~1023。
     * 分辨率:ADC能够分辨的模拟信号最小变化量。计算公式是,分辨率 = 量程 / 2的n次方
     【例】:量程为单极性0-5V,8位ADC的分辨率是,5 / 256 = 0.0195V
     * 转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。
    

results matching ""

    No results matching ""

    results matching ""

      No results matching ""