目录
ADC设备
前言
ADC(Analog-to-Digital Converter) 指模数转换器。是指将连续变化的模拟信号转换为离散的数字信号的器件。
对于ADC的详细介绍和在STM32中的裸机应用可参考以下博客
ADC电压采集(基于STM32hal库)(详细介绍)_竹烟淮雨的博客-CSDN博客
ADC电压采集(基于STM32hal库)(保姆级应用)_竹烟淮雨的博客-CSDN博客
ADC相关参数说明
- 分辨率:
分辨率以二进制(或十进制)数的位数来表示,一般有 8 位、10 位、12 位、16 位等,它说明模数转换器对输入信号的分辨能力,位数越多,表示分辨率越高,恢复模拟信号时会更精确。
比如电压访问在0-3.3V,如果使用12Bit的分辨率的话,最大表示的数字量为2^11-1=4095(范围为0-4095),也就是把3.3V分为4096份,实际电压值=模拟电压值/4095*3.3V
- 精度:
精度表示 ADC 器件在所有的数值点上对应的模拟值和真实值之间的最大误差值,也就是输出数值偏离线性最大的距离。
- 转换速率:
转换速率是指 A/D 转换器完成一次从模拟到数字的 AD 转换所需时间的倒数。例如,某 A/D 转换器的转换速率为 1MHz,则表示完成一次 AD 转换时间为 1 微秒。
访问ADC设备
应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC 硬件,相关接口如下所示:
- 查找 ADC 设备
rt_device_t rt_device_find(const char* name);
- 使能 ADC 通道
rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel)
@dev ADC 设备句柄
@channel ADC 通道
- 读取 ADC 通道采样值(读取到的是模拟量转成数字量后的值)
rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel);
@dev ADC 设备句柄
@channel ADC 通道
- 关闭 ADC 通道
rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel);
仅仅有这些函数接口,并不能够实现ADC设备的功能,我们还需要进行相应的配置。
配置ADC设备
打开我们的工程源码中的board.h,关于芯片的一些外设的配置基本上都在board.h中去配置,关于我们之前的时钟、串口配置,以及IIC、SPI、PWM等等的配置。
打开board.h找到ADC的相关配置步骤描述
/** if you want to use adc you can use the following instructions.
*
* STEP 1, open adc driver framework support in the RT-Thread Settings file
*
* STEP 2, define macro related to the adc
* such as #define BSP_USING_ADC1
*
* STEP 3, copy your adc init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
* such as void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
*
* STEP 4, modify your stm32xxxx_hal_config.h file to support adc peripherals. define macro related to the peripherals
* such as #define HAL_ADC_MODULE_ENABLED
*
*/
- 步骤一:开启ADC驱动框架的支持
- 步骤二:定义一个ADC设备相关的宏
共有三种选择
根据我们的STM32开发板公有三个ADC外设,这里选择使用ADC1
- 步骤三:拷贝ADC初始化函数,通过CubeMX生成stm32xxxx_hal_msp.c后,将相应的初始化函数拷贝到board.c中
- 步骤四:修改hal层配置文件,使其支持ADC外设
ADC实例
我们在这里以ADC的独立模式单通道采集模式为例,来使用我们RTT的ADC设备。
硬件设计
我们的霸道开发板板载了一个贴片滑动变阻器,滑动变阻器的滑片端连接到了 STM32 的 PC1 引脚。
贴片滑动变阻器的动触点通过连接至 STM32 芯片的 ADC 通道引脚。当我们旋转滑动变阻器调 节旋钮时,其动触点电压也会随之改变,电压变化范围为 0~3.3V,亦是开发板默认的 ADC 电压 采集范围。
软件设计
我们接着前面配置ADC设备的步骤进行。
1.首先寻找ADC1设备句柄
2.接着如果查找到ADC,则打开我们的ADC设备,这里使用专属的使能函数,注意我们需要对dev进行类型转换为rt_adc_device_t
3.使能完成之后,我们就可以继续数据读取了。这里我们开启一个线程来读取ADC1的通道11。
(1)动态创建线程
(2)设置入口函数
(3)开启线程
4.在线程处理函数中,通过rt_adc_read函数进行ADC通道数据的读取
5.此外要注意在线程处理中加上延时,这样可以让线程主动释放CPU资源,让CPU去调度其它线程
6.完善打印结果
7.将我们的CubeMX生成的代码复制到board.c中
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**ADC1 GPIO Configuration
PC1 ------> ADC1_IN11
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* ADC1 interrupt Init */
HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
8.编译下载,注意要加上adc.h头文件
运行结果,调节电压旋钮,模拟量正常输出,但数字量输出是%f???
(这个问题琢磨半天尚未解决,rt_kprintf("Analog val:%.3f\n\r\n",(float)val/4096.0*3.3);输出的结果是%f???,同样我将%.3f换成%d或%u输出的结果却是很大的随机数,希望有大佬可以帮忙解决!!)