Firefly-RK3399開發板上的 AD 接口有兩種,分別為:溫度傳感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。其中:
-
TS-ADC(Temperature Sensor):支持兩通道,時鐘頻率必須低于800KHZ
-
SAR-ADC(Successive Approximation Register):支持六通道單端10位的SAR-ADC,時鐘頻率必須小于13MHZ。
內核采用工業 I/O 子系統來控制 ADC,該子系統主要為 AD 轉換或者 DA 轉換的傳感器設計。 下面以SAR-ADC為例子,介紹 ADC 的基本配置方法。
Firefly-RK3399 SAR-ADC 的 DTS 節點在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 文件中定義,如下所示:
用戶首先需在DTS文件中添加ADC的資源描述:
kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi : adc_demo: adc_demo{ status = "disabled"; compatible = "firefly,rk3399-adc"; io-channels = <&saradc 3>; };
這里申請的是SARADC通道3.
用戶驅動可參考Firefly adc demo :kernel/drivers/adc/adc-firefly-demo.c,這是一個偵測Firefly-rk3399風扇狀態的驅動。 首先在驅動文件中定義 of_device_id 結構體數組:
static const struct of_device_id firefly_adc_match[] = { { .compatible = "firefly,rk3399-adc" }, {}, };
然后將該結構體數組填充到要使用 ADC 的 platform_driver 中:
static struct platform_driver firefly_adc_driver = { .probe = firefly_adc_probe, .remove = firefly_adc_remove, .driver = { .name = "firefly_adc", .owner = THIS_MODULE, .of_match_table = firefly_adc_match, }, };
接著在firefly_adc_probe中對DTS所添加的資源進行解析:
static int firefly_adc_probe(struct platform_device *pdev) { printk("firefly_adc_probe!\n"); 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;}
struct iio_channel *chan; //定義 IIO 通道結構體chan = iio_channel_get(&pdev->dev, NULL); //獲取 IIO 通道結構體
注:iio_channel_get 通過 probe 函數傳進來的參數 pdev 獲取 IIO 通道結構體,probe 函數如下:
static int XXX_probe(struct platform_device *pdev);
int val,ret; ret = iio_read_channel_raw(chan, &val);
調用 iio_read_channel_raw 函數讀取 AD 采集的原始數據并存入 val 中。
使用標準電壓將 AD 轉換的值轉換為用戶所需要的電壓值。其計算公式如下:
Vref / (2^n-1) = Vresult / raw
注:
-
Vref 為標準電壓
-
n 為 AD 轉換的位數
-
Vresult 為用戶所需要的采集電壓
-
raw 為 AD 采集的原始數據
例如,標準電壓為 1.8V,AD 采集位數為 10 位,AD 采集到的原始數據為 568,則:
Vresult = (1800mv * 568) / 1023;
struct iio_channel *iio_channel_get(struct device *dev, const char *consumer_channel);
-
功能:獲取 iio 通道描述
-
參數:
-
dev: 使用該通道的設備描述指針
-
consumer_channel: 該設備所使用的 IIO 通道描述指針
-
void iio_channel_release(struct iio_channel *chan);
-
功能:釋放 iio_channel_get 函數獲取到的通道
-
參數:
-
chan:要被釋放的通道描述指針
-
int iio_read_channel_raw(struct iio_channel *chan, int *val);
-
功能:讀取 chan 通道 AD 采集的原始數據。
-
參數:
-
chan:要讀取的采集通道指針
-
val:存放讀取結果的指針
-
在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi中使能adc_demo,將”disabled” 改為 “okay”:
adc_demo: adc_demo{ status = "okay"; compatible = "firefly,rk3399-adc"; io-channels = <&saradc 3>; };
編譯內核,燒錄內核到Firefly-RK3399 開發板上,然后插拔風扇時,會打印內核log信息如下:
[ 85.158104] Fan insert! raw= 135 Voltage= 237mV [ 88.422124] Fan out! raw= 709 Voltage=1247mV
有個便捷的方法可以查詢到每個SARADC的值:
cat /sys/bus/iio/devices/iio\:device0/in_voltage*_raw
驅動需要獲取ADC通道來使用時,需要對驅動的加載時間進行控制,必須要在saradc初始化之后。saradc是使用module_platform_driver()進行平臺設備驅動注冊,最終調用的是module_init()。所以用戶的驅動加載函數只需使用比module_init()優先級低的,例如:late_initcall(),就能保證驅動的加載的時間比saradc初始化時間晚,可避免出錯。
-
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35331 -
Firefly
+關注
關注
2文章
538瀏覽量
7043
發布評論請先 登錄
相關推薦
評論