日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式客棧
[導(dǎo)讀]關(guān)注、星標(biāo)嵌入式客棧,精彩及時(shí)送達(dá)[導(dǎo)讀]朋友們,大家好,我是逸珺。今天分享一下如何在用戶空間操作IIO設(shè)備。IIO設(shè)備能實(shí)現(xiàn)很多有價(jià)值的應(yīng)用,有興趣的一起來看看~什么是IIO設(shè)備IIO是IndustrialI/O的縮寫,是Linux下為工業(yè)輸入輸出所設(shè)計(jì)的子系統(tǒng)。其主要目的是為...

關(guān)注、星標(biāo)嵌入式客棧,精彩及時(shí)送達(dá)[導(dǎo)讀] 朋友們,大家好,我是逸珺。

今天分享一下如何在用戶空間操作IIO設(shè)備。IIO設(shè)備能實(shí)現(xiàn)很多有價(jià)值的應(yīng)用,有興趣的一起來看看~

什么是IIO設(shè)備

IIO是 Industrial I/O 的縮寫,是Linux下為工業(yè)輸入輸出所設(shè)計(jì)的子系統(tǒng)。其主要目的是為模數(shù)轉(zhuǎn)換 (ADC) 或數(shù)模轉(zhuǎn)換 (DAC) 或兩者兼而有之的設(shè)備提供設(shè)備驅(qū)動(dòng)支持。Linux下原來有Hwmon以及輸入子系統(tǒng),但這兩個(gè)子系統(tǒng)不能很好的涵蓋上面需求。而IIO子系統(tǒng)就是為了填補(bǔ)這一空白而設(shè)計(jì)的。

什么是Hwmon?針對(duì)用于監(jiān)測(cè)和控制系統(tǒng)本身的低采樣率傳感器,如風(fēng)扇速度控制或溫度測(cè)量。

而輸入子系統(tǒng)(Input subsystem), 顧名思義,主要抽象人機(jī)交互輸入設(shè)備(鍵盤、鼠標(biāo)、觸摸屏)。當(dāng)然,從這些描述來看,這兩個(gè)需求與 IIO 之間存在相當(dāng)大的重疊。

而IIO子系統(tǒng)則主要管理抽象這些類別的設(shè)備:

  • 模數(shù)轉(zhuǎn)換器(ADC)
  • 加速度計(jì)(Accelerometers)
  • 陀螺儀(Gyros)
  • 慣性測(cè)量單元 IMUs)
  • 電容數(shù)字轉(zhuǎn)換器 (CDC)
  • 壓力傳感器
  • 顏色、光線和接近傳感器
  • 溫度傳感器
  • 磁力計(jì)(Magnetometers)
  • 數(shù)模轉(zhuǎn)換器(DAC)
  • 直接數(shù)字合成器(DDS)
  • 鎖相環(huán)(PLL)
  • 可變/可編程增益放大器(VGA、PGA)
  • ....
此類設(shè)備,一般會(huì)通過I2C/SPI總線連接到處理器,SPI/I2C通常用來傳輸控制信息,而這些設(shè)備的輸入輸出應(yīng)用數(shù)據(jù)則是通過其他的接口與處理器進(jìn)行通信,比如采用LVDS。以AD9467為例:

三線制SPI則是控制信息,用于配置ADC的寄存器,而采樣數(shù)據(jù)則是通過LVDS上傳給處理器的。

IIO設(shè)備長(zhǎng)什么樣?

IIO設(shè)備一般也會(huì)在/dev下創(chuàng)建一個(gè)設(shè)備文件,比如:

然后在sys下也會(huì)創(chuàng)建文件,比如在/sys/bus下就會(huì)創(chuàng)建一條名為iio的總線:

進(jìn)入到iio之后:

在devices下,則有:

如果有多個(gè)iio設(shè)備,則會(huì)這樣編號(hào):

iio:device0??iio:device1??iio:device2??......
進(jìn)入到iio:device0后

則可以看到有mode,scale,of_node,frequeceny等屬性。進(jìn)到scan_elements下:

scan_elements用于描述掃描樣本的相關(guān)屬性:

  • in_voltage0_en:使能控制,設(shè)置為1為使能,為0則關(guān)閉
  • in_voltage0_index :索引
  • in_voltage0_type:采樣類型,本設(shè)備該值為le:S16/16>>0,表示是小端有符號(hào)整型
buffer中的屬性為:

  • data_available :有多少數(shù)量的數(shù)據(jù)準(zhǔn)備好了
  • enable :激活緩沖區(qū)捕獲,設(shè)置為1則開始緩沖區(qū)捕獲
  • length:緩沖區(qū)可以存儲(chǔ)的數(shù)據(jù)樣本總數(shù)
  • length_align_bytes:?對(duì)齊要求,用于設(shè)置DMA的對(duì)齊要求。
  • watermark:此屬性從內(nèi)核版本 4.2 開始可用。它是一個(gè)正數(shù),指定阻塞讀取應(yīng)等待多少個(gè)掃描元素。如果使用輪詢,它將阻塞直到達(dá)到watermark設(shè)定值。只有當(dāng)watermark大于請(qǐng)求的讀取量時(shí)才有意義。它不會(huì)影響非阻塞讀取。
在用戶空間讀取iio設(shè)備的數(shù)據(jù),有掃描方法或者觸發(fā)方法,這里主要分享一下連續(xù)掃描讀取。

  • 首先將scan_elements中in_voltage0_en設(shè)置為1
root@idaq:/sys/bus/iio/devices/iio:device0/scan_elements#?echo?1?>?in_voltage0_en
root@idaq:/sys/bus/iio/devices/iio:device0/scan_elements#?cat?in_voltage0_en
1
  • 然后將buffer中的enable,也設(shè)置為1。驅(qū)動(dòng)就開始工作了。marked complete 表示一次DMA傳輸結(jié)束。
root@idaq:/sys/bus/iio/devices/iio:device0/buffer#?echo?1?>?enable
iio?iio:device0:?iio_dma_buffer_enable
dma-axi-dmac?43c20000.axi_dmac:?vchan?(ptrval):?txd?(ptrval)[2]:?submitted
dma-axi-dmac?43c20000.axi_dmac:?txd?(ptrval)[2]:?marked?complete
  • 然后就可以標(biāo)準(zhǔn)文件操作直接讀取/dev/iio:device0了

代碼實(shí)現(xiàn)

有了前面的介紹,就有具體實(shí)現(xiàn)的思路了。這里以QT為例,設(shè)計(jì)一個(gè)類先進(jìn)行文件操作,然后不停讀取文件即可。

下面是頭文件:

#ifndef?_IIO_DEVICE_H_
#define?_IIO_DEVICE_H_
#include?
#include?
#include?
//繼承自QThread
class?IIODevice?:?public?QThread
{
????Q_OBJECT
public:
????explicit?IIODevice(QObject?*parent?=?0,
???????????????????????QString?fName="iio:device0",
???????????????????????QByteArray?*pBuffer=nullptr,
???????????????????????QMutex?*pMutex=nullptr)
;
????~IIODevice();

????int??openDevice(void);
????int??closeDevice(void);
????void?startSample();
????void?stopSample(void);
????int??readDevice(unsigned?char?*?buffer,int?size);
????bool?isStarted(void);

public?slots:

protected:
????void?run();

private:
????int?fd;
????QString?fileName;
????bool?m_abort;
????//用于緩存數(shù)據(jù)
????QByteArray?*buffer;
????QMutex?*mutex;
????bool?m_started;
};

#endif
實(shí)現(xiàn)文件如下:

IIODevice::IIODevice(QObject?*parent,QString?fName,QByteArray?*pBuffer,QMutex?*pMutex)?:
????QThread(parent),
????fileName(fName),
????buffer(pBuffer),
????mutex(pMutex)
{??
????m_abort?=?false;
????m_started?=?false;??
}

int?IIODevice::openDevice(void)
{
????//使能in_voltage0_en
????QString?cmdStr?=?"echo?1?>?/sys/bus/iio/devices/" fileName "/scan_elements/in_voltage0_en";
????QByteArray?cmdBuffer?=?cmdStr.toLocal8Bit();
????char?*?cmd?=?cmdBuffer.data();
????system(cmd);

????//使能采集
????cmdStr?=?"echo?1?>?/sys/bus/iio/devices/" fileName "/buffer/enable";
????cmdBuffer?=?cmdStr.toLocal8Bit();
????cmd?=?cmdBuffer.data();
????system(cmd);

????QString?path?=?"/dev/" fileName;
????QFile?*?file?=?new?QFile();
????file->setFileName(path);
????if(?!file->exists()?){
????????qDebug()?<"file?does?not?exist";
????????return?-1;
????}

????//O_NONBLOCK方式打開文件
????fd?=?open(path.toUtf8().data(),?O_RDONLY|O_NONBLOCK);
????if(?fd==-1?){
????????qDebug()?<"can?not?open?file";
????????return?-2;
????}

????return?0;
}

int?IIODevice::closeDevice(void)
{
????QString?cmdStr;
????QByteArray?cmdBuffer;
????//1.禁止采樣
????cmdStr?=?"echo?0?>?/sys/bus/iio/devices/" fileName "/buffer/enable";
????cmdBuffer?=?cmdStr.toLocal8Bit();
????char?*?cmd?=?cmdBuffer.data();
????system(cmd);

????//2.禁止in_voltage0_en
????cmdStr?=?"echo?0?>?/sys/bus/iio/devices/" fileName "/scan_elements/in_voltage0_en";
????cmdBuffer?=?cmdStr.toLocal8Bit();
????cmd?=?cmdBuffer.data();
????
????system(cmd);
????//3.關(guān)閉文件
????if(fd)?{
?????close(fd);
?????fd?=?-1;????
????}???
??
????return?0;
}

int?IIODevice::readDevice(unsigned?char?*?buffer,int?size)
{
????int?length?=?0;
????length?=?read(fd,buffer,size);
????return?length;
}

IIODevice::~IIODevice(void)
{
??if(fd)
????close(fd);
}

void?IIODevice::startSample()
{
??mutex->lock();
??m_abort?=?false;
??m_started?=?true;
??if(!buffer->isEmpty())
?????buffer->remove(0,buffer->size());
??mutex->unlock();
??openDevice();
??start();
}

bool?IIODevice::isStarted()
{
??return?m_started;
}

void?IIODevice::stopSample()
{
??mutex->lock();
??m_abort?=?true;
??m_started?=?false;
??closeDevice();
??mutex->unlock();
????
??//完全關(guān)閉線程的寫法
??wait();
}

#define?TEMP_BUFFER_SIZE?4096
//開辟線程用于讀取
void?IIODevice::run()
{
??int?bytes?=?0;
??unsigned?char?devBuf[TEMP_BUFFER_SIZE];
??while(1)?{
??????bytes?=?4096;//假定內(nèi)部buffer為4096
??????while(bytes==4096)
??????{
????????bytes?=?readDevice(devBuf,TEMP_BUFFER_SIZE);
????????mutex->lock();
????????buffer->append((const?char?*)devBuf,bytes);
????????mutex->unlock();
??????}

??????if?(m_abort)
????????return;
??????//周期性掃描
??????usleep(600);
??}
}
QMutex用于線程間數(shù)據(jù)保護(hù),由于該類是一個(gè)線程類,實(shí)際使用的時(shí)候可能是另一個(gè)線程讀取IIO設(shè)備的采集數(shù)據(jù),用于傳輸或者后續(xù)應(yīng)用處理,兩個(gè)線程操作同一個(gè)QByteArray對(duì)象,存在并發(fā)競(jìng)態(tài),所以需要做互斥訪問保護(hù)。

如此一來,外界的物理信號(hào)就經(jīng)由ADC芯片,進(jìn)入Linux內(nèi)核設(shè)備iio:device0,再由用戶空間的IIODevice類所例化的對(duì)象,傳遞到用戶空間,從而可以在Linux下實(shí)現(xiàn)采樣應(yīng)用了,整個(gè)信號(hào)傳遞可以用下面這個(gè)圖來描述。

總結(jié)一下

IIO設(shè)備在很多工業(yè)儀器類非常有用,如前所說,不僅僅能實(shí)現(xiàn)AD采樣,還可以實(shí)現(xiàn)DA,DDS等很多非常有應(yīng)用價(jià)值的設(shè)備。要用好IIO設(shè)備,可能涉及到設(shè)備驅(qū)動(dòng)、信號(hào)鏈設(shè)計(jì)、用戶空間應(yīng)用程序編寫等等技術(shù)。本文以一個(gè)AD采樣IIO設(shè)備為例,分享一下如何從用戶空間訪問控制IIO設(shè)備,希望對(duì)有興趣的朋友們有所幫助。

—— The End?—


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉