这段时间在调试AM4378的ADC问题,发现采样到的数据和真实输入波形有所出入,比如输入是1ms的周期,50%占空比的信号,但是采样的数据描点总是偏差较大,数据如下
iio device number being used is 0 scan_size:2 read_size:40 ADC value:1821 1820 1819 1820 1820 864 8 0 0 0 0 1823 0 0 0 1835 1816 1818 1825 1817 ADC AVG Value: 1823 read_size:40 ADC value:1817 24 0 2 0 0 1841 1818 1820 1818 1818 1820 0 0 0 0 1823 1819 1819 1818 ADC AVG Value: 1821 read_size:40 ADC value:1818 1821 0 0 0 0 0 1824 1830 1819 1820 1818 1820 1817 1819 1821 1816 97 5 0 ADC AVG Value: 1822 read_size:40 ADC value:10 0 1855 1824 1820 1817 1822 1820 233 0 0 0 1819 2 0 0 0 0 1830 1820 ADC AVG Value: 1825 read_size:40 ADC value:1817 1832 1817 1819 6 0 0 0 0 1844 1821 1820 0 0 1821 1820 1818 1822 1819 619 ADC AVG Value: 1825 read_size:40 ADC value:0 0 0 0 0 1823 1820 1818 1818 1824 1822 0 1819 1818 1816 16 0 2 0 0
而DTS的设置如下
status = "okay" adc { ti, adc-channels = <5, 6, 7>; ti, chan-step-opendelay = <0x0 0x0 0x0>; ti, chan-step-sampledelay = <0xff 0xff 0xff>; ti, chan-step-avg = <1 1 1>; };
采样目标:采样20次,2个周期,也就是2ms, 数据点均匀分布。
问题:在20次基本保持两个周期的情况下,opendelay+sampledelay+other cycles并不符合ADC 24MHz clock的情况,且20次采样并未均匀分布。经过在TI社区咨询发现存在如下问题:
- 如果不打算做采样平均,那么chan-step-avg不应该设置为1,而是0
- ADC计算频率并不是24MHz,而是3MHz
-------------------------------------------------------分界线----------------------------------------------------------------
首先, 从Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt中可以查到如下信息
- opendelay maximum为0x3FFFF cycles
- sampledelay maximum为0xFF cycles
其次, 从TI的数据手册可以看到如下信息,最快的一次采样,在Sampledelay=1, opendelay=0的情况下,为15cycles
在者,从驱动文件driver/mfd/ti_am335x_tscadc.c中可以看到如下代码段
tscadc->clk_div = clock_rate / ADC_CLK; ADC_CLK = 3000000
tscadc->clk_div会被写入ADC的DIV分频寄存器,也就是说,clock_rate = 24MHz并不是ADC的真实clock, ADC_CLK才是,也就是3MHz 。
基于以上信息,我们就有如下计算:
1/3MHz = 333.33ns ADC clock period --> 333.33ns * 15 ADC clocks = 5us sample period --> 1 / 5us = 200ksps sampling rate
也就说,最快的ADC采样频率是200ksps,而且是所有通道。也就说1个通道,则采样频率为200ksps; 如果2个通道,则采样频率为100ksps, 以此类推.......
关于chan-step-avg变量
在driver/iio/adc/ti_am335x_adc.c中有如下代码段, 可知AVG默认是0,且当chan-step-avg=0时,寄存器数据为0。 (根据代码段,这里当chan-step-avg=1, 好像写到寄存器的值也是0,不知为什么最终效果确实像做了2个数的平均)
if(adc_dev->step_avg[i]) stepconfig = STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | STEPCONFIG_FIFO1; else stepconfig = STEPCONFIG_FIFO1;
和如下的Datasheet
所以基于上面的采样目标,有如下设置即可, 因为只采用channel6,(0x11D + 15cycles)*333ns=100us. 也就是2ms内完成20次采样。333ns由上面的ADC clock得出。
status = "okay" adc { ti, adc-channels = <6>; ti, chan-step-opendelay = <0x11D>; ti, chan-step-sampledelay = <0x1>; ti, chan-step-avg = <0>; };
打印结果如下, 可以看出来已经比较均匀了。
ADC value:1 0 3679 3667 3657 3666 3658 17 0 0 0 0 3678 3664 3659 3674 3662 0 0 3 ADC AVG Value: 3673 read_size:40 ADC value:0 6 3663 3662 3660 3658 3673 0 3 0 0 0 3661 3662 3666 3671 210 0 7 0 ADC AVG Value: 3666 read_size:40 ADC value:0 3710 3671 3664 3656 3660 154 2 0 0 0 3694 3662 3658 3659 3659 10 0 0 8 ADC AVG Value: 3676 read_size:40 ADC value:0 3674 3668 3662 3658 3660 7 0 0 5 0 3670 3658 3659 3667 3659 7 3 0 0 ADC AVG Value: 3668 read_size:40 ADC value:0 3664 3658 3658 3674 3658 0 0 0 0 0 3669 3662 3656 3660 222 0 0 3 0 ADC AVG Value: 3665 read_size:40 ADC value:3706 3662 3664 3673 3654 168 0 0 5 0 3699 3665 3660 3659 3660 11 5 0 7 5 ADC AVG Value: 3679 read_size:40 ADC value:3671 3660 3657 3658 3660 19 0 8 0 5 3674 3672 3661 3658 3662 0 0 0 0 3 ADC AVG Value: 3668 read_size:40 ADC value:3664 3671 3662 3658 3658 0 0 0 0 0 3664 3662 3660 3672 260 0 3 0 0 3718 ADC AVG Value: 3669 read_size:40 ADC value:3660 3656 3671 3667 180 0 0 3 0 3717 3659 3658 3662 3654 14 0 3 7 0 3686