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如下所示,将其与风扇的引脚使用杜邦线相连

20.ARMLinux上ADC的驱动和使用方法_第1张图片

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

你可能感兴趣的:(linux,嵌入式硬件,arm开发)