IMX6ULL一共有两个ADC,每个ADC都有八个通道,但他们共用一个ADC控制器
1.设备树
在imx6ull.dtsi文件中已经帮我们定义好了adc1的节点部分信息
adc1: adc@02198000 {
compatible = "fsl,imx6ul-adc", "fsl,vf610-adc";
reg = <0x02198000 0x4000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ADC1>;
num-channels = <2>;
clock-names = "adc";
status = "disabled";
};
注意 num-channels = <2>;,这个表示指定使用ADC1的两个通道,即通道1和通道2
如果你要使用多个ADC通道,修改这个值即可
配置ADC引脚的 pinctrl,在自己的设备树(.dts)中引用adc1并指定 pinctrl子系统,也就是指定引脚
首先在根节点下定义 pinctrl
/* chenshao ADC1_CH1 GPIO1_IO01 */
pinctrl_adc1: adc1grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
>;
};
接着在 regulators 节点下设置ADC的参考电压,设置为5V(因为MQ135输出最大模拟电压是5V)
/* chenshao ADC vref 5.0V */
reg_vref_adc: regulator@2 {
compatible = "regulator-fixed";
regulator-name = "VREF_5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
最后在根节点之外引用adc1节点,并指定引脚可参考电压节点
/* chenshao ADC1 */
&adc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_adc1>;
num-channels = <2>; /* 2个通道,gpio1_io0占用一个 */
vref-supply = <®_vref_adc>;
status = "okay";
};
2.直接查看ADC值
1.进入iio总线下的设备目录
cd /sys/bus/iio/devices/iio:device0/
2.ls查看
------------------------
dev of_node
in_voltage0_raw power
in_voltage1_raw sampling_frequency_available
in_voltage_sampling_frequency subsystem
in_voltage_scale uevent
name
3.查看ADC通道1原始值(由于IMX6ULL ADC为12位,所以最小值为0,最大值为4095(2^12),分别对应0V,3.3V或5V)
cat in_voltage1_raw
721
4.查看电压规模
cat in_voltage_scale
1.220703125
5.计算实际电压
in_voltage1_raw * in_voltage_scale 即可,注意单位是毫伏
3.应用程序获取ADC和电压
读取 /sys/bus/iio/devices/iio:device0/in_voltage1_raw 文件得到ADC原始值
读取 /sys/bus/iio/devices/iio:device0/in_voltage_scale 文件得到电源规模值
两者相乘,再除以1000即可得到电压值(单位V)
PS:
读取文件前使用 rewind函数 将光标移到最开头,
可以使用 fscanf 读取文件
利用 atoi 和 atof 库函数转换类型
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
const char *voltage1_raw = "/sys/bus/iio/devices/iio:device0/in_voltage1_raw";
const char *voltage_scale = "/sys/bus/iio/devices/iio:device0/in_voltage_scale";
int main(int argc, char *argv[])
{
FILE *raw_fd, *scale_fd;
int len1, len2, res;
char data[20];
int raw;
double scale;
while(1){
/* 1.打开文件 */
raw_fd = fopen(voltage1_raw, "r");
if(raw_fd == NULL){
printf("open raw_fd failed!\n");
return -1;
}
scale_fd = fopen(voltage_scale, "r");
if(scale_fd == NULL){
printf("open scale_fd failed!\n");
return -2;
}
/* 2.读取文件 */
rewind(raw_fd); // 将光标移回文件开头
res = fscanf(raw_fd, "%s", data);
raw = atoi(data);
memset(data, 0, sizeof(data));
rewind(scale_fd); // 将光标移回文件开头
res = fscanf(scale_fd, "%s", data);
scale = atof(data);
printf("ADC原始值:%d,电压值:%.3fV\r\n", raw, raw * scale / 1000.f);
fclose(raw_fd);
fclose(scale_fd);
sleep(2);
}
return 0;
}
测试成功
# ./adcApp
ADC原始值:390,电压值:0.476V
ADC原始值:399,电压值:0.487V
ADC原始值:413,电压值:0.504V
ADC原始值:416,电压值:0.508V
ADC原始值:410,电压值:0.500V
ADC原始值:407,电压值:0.497V