20.ARMLinux上ADC的驱动和使用方法
ADC(Analog-to-Digital Converter)即模数转换器,是一种将模拟信号转换为数字信号的电子元器件,用于实现模拟信号的数字化处理和采集。在嵌入式系统中,ADC广泛应用于传感器信号采集、电源管理、环境检测等领域。
一、Userspace使用ADC
1.硬件以及规格书
以firefly ROC-RK3588S-PC 开发板为例
ROC-RK3588S-PC 开发板上的 AD 接口有两种,分别为:温度传感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。其中:
- TS-ADC(Temperature Sensor):支持七通道。
- SAR-ADC(Successive Approximation Register):支持八通道单端12位的SAR-ADC,最大转换速率为1MSPS,采用20MHz的A/D转换器时钟。
ROC-RK3588S-PC 的ADC接口通道4如下所示,将其与风扇的引脚使用杜邦线相连
2.设备节点获取ADC的raw值
获取通道4的ADC转换值
# cd /sys/bus/iio/devices/iio:device0
root@firefly:/sys/bus/iio/devices/iio:device0# ls
buffer in_voltage0_raw in_voltage2_raw in_voltage4_raw in_voltage6_raw in_voltage_scale of_node scan_elements trigger dev in_voltage1_raw in_voltage3_raw in_voltage5_raw in_voltage7_raw name power subsystem uevent
# cat in_voltage4_raw
7
二、内核获取ADC
firefly有写好的ADC的demo驱动程序,这里只需要配置好对应的设备树节点
1.添加设备树节点
adc_demo: adc_demo {
compatible = "firefly,rk3588-adc";
status = "okay";
io-channels = <&saradc 4>;
};
2.确保驱动被编译
驱动源文件路径:
drivers/iio/adc/adc-firefly-demo.c
3.接口说明
- 获取 AD 通道
struct iio_channel *chan; #定义 IIO 通道结构体
chan = iio_channel_get(&pdev->dev, NULL); #获取 IIO 通道结构体
- 读取 AD 采集到的原始数据
int val,ret;
ret = iio_read_channel_raw(chan, &val);
调用 iio_read_channel_raw 函数读取 AD 采集的原始数据并存入 val 中。
4.驱动过程梳理
- probe获取设备的ADC通道,初始化队列以及其实现函数
static int firefly_adc_probe(struct platform_device *pdev)
{
printk("firefly_adc_probe!\n");
count = 0;
chan = iio_channel_get(&(pdev->dev), NULL);
if (IS_ERR(chan))
{
chan = NULL;
printk("%s() have not set adc chan\n", __FUNCTION__);
return -1;
}
fan_insert = false;
if (chan) {
INIT_DELAYED_WORK(&adc_poll_work, firefly_demo_adc_poll);
schedule_delayed_work(&adc_poll_work,1000);
}
return 0;
}
- 队列服务函数里读取ADC转换值,并计算实际电压,并延时队列重复时间
#define VREF 5000
static void firefly_demo_adc_poll(struct work_struct *work)
{
int ret,raw;
int result = -1;
ret = iio_read_channel_raw(chan, &raw);
if (ret < 0) {
printk("read hook adc channel() error: %d\n", ret);
return;
}
result = (VREF*raw)/4095 ;//Vref / (2^n-1) = Vresult / raw
printk("Fan insert! raw= %d Voltage= %dmV\n",raw,result);
schedule_delayed_work(&adc_poll_work, 1000);
}
12位ADC 2^12=4096
5.用户空间验证
在50%占空比下测电压,一会测5v,一会测0v,ADC的测量比pwm改变电平的速度要快
[ 1238.836547] Fan insert! raw= 4095 Voltage= 5000mV
[ 1242.250015] Fan insert! raw= 4095 Voltage= 5000mV
[ 1245.663091] Fan insert! raw= 4 Voltage= 4mV
[ 1249.076442] Fan insert! raw= 9 Voltage= 10mV