【IMX6ULL驱动开发学习】22.IMX6ULL开发板读取ADC(以MQ-135为例)

IMX6ULL一共有两个ADC,每个ADC都有八个通道,但他们共用一个ADC控制器

1.设备树

在imx6ull.dtsi文件中已经帮我们定义好了adc1的节点部分信息

c 复制代码
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

c 复制代码
/* chenshao ADC1_CH1 GPIO1_IO01 */
pinctrl_adc1: adc1grp {
	fsl,pins = <
		MX6UL_PAD_GPIO1_IO01__GPIO1_IO01   0xb0 
	>;
};

接着regulators 节点下设置ADC的参考电压,设置为5V(因为MQ135输出最大模拟电压是5V)

c 复制代码
/* 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节点,并指定引脚可参考电压节点

c 复制代码
/* chenshao ADC1 */
&adc1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_adc1>;
	num-channels = <2>;             /* 2个通道,gpio1_io0占用一个 */
	vref-supply = <&reg_vref_adc>;
	status = "okay";	
};

2.直接查看ADC值

c 复制代码
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 库函数转换类型

c 复制代码
#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;
}

测试成功

c 复制代码
# ./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
相关推荐
qxqxa1 小时前
cfg80211是怎么配置无线设备的AP的?
网络·驱动开发
玉树临风江流儿5 小时前
Linux驱动开发(速记版)--设备模型
linux·驱动开发
憧憬一下17 小时前
驱动中的device和device_driver结构体
驱动开发·嵌入式
玉树临风江流儿2 天前
Linux驱动开发(速记版)--设备树插件
linux·驱动开发
Svan.2 天前
基于Arduino的宠物食物分配器
驱动开发·硬件工程·宠物
不会编程的小江江4 天前
【Linux】Linux内核结构基础
linux·驱动开发
OH五星上将4 天前
【移植】一种快速移植OpenHarmony Linux内核的方法
linux·运维·驱动开发·嵌入式硬件·harmonyos·openharmony·鸿蒙内核
IT永勇5 天前
基于Arduino的L298N电机驱动模块使用
驱动开发·单片机·嵌入式硬件·arduino·电子设计
OH五星上将5 天前
OpenHarmony(鸿蒙南向)——平台驱动指南【MIPI CSI】
linux·驱动开发·嵌入式硬件·移动开发·harmonyos·鸿蒙嵌入式
eric_dma6 天前
查看 .so 库(共享对象库)的依赖
驱动开发