99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

手把手教如何用Linux下IIO設備(附代碼)

今天分享一下如何在用戶空間操作IIO設備。IIO設備能實現很多有價值的應用,有興趣的一起來看看~

什么是IIO設備

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

什么是Hwmon?針對用于監測和控制系統本身的低采樣率傳感器,如風扇速度控制或溫度測量。

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

而IIO子系統則主要管理抽象這些類別的設備:

  • 模數轉換器(ADC)
  • 加速度計(Accelerometers)
  • 陀螺儀(Gyros)
  • 慣性測量單元 IMUs)
  • 電容數字轉換器 (CDC)
  • 壓力傳感器
  • 顏色、光線和接近傳感器
  • 溫度傳感器
  • 磁力計(Magnetometers)
  • 數模轉換器(DAC)
  • 直接數字合成器(DDS)
  • 鎖相環(PLL)
  • 可變/可編程增益放大器(VGA、PGA)
  • ....

此類設備,一般會通過I2C/SPI總線連接到處理器,SPI/I2C通常用來傳輸控制信息,而這些設備的輸入輸出應用數據則是通過其他的接口與處理器進行通信,比如采用LVDS。以AD9467為例:

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

IIO設備長什么樣?

IIO設備一般也會在/dev下創建一個設備文件,比如:

然后在sys下也會創建文件,比如在/sys/bus下就會創建一條名為iio的總線:

進入到iio之后:

在devices下,則有:

如果有多個iio設備,則會這樣編號:

iio:device0  iio:device1  iio:device2  ......

進入到iio:device0后

則可以看到有mode,scale,of_node,frequeceny等屬性。進到scan_elements下:

scan_elements用于描述掃描樣本的相關屬性:

  • in_voltage0_en:使能控制,設置為1為使能,為0則關閉
  • in_voltage0_index :索引
  • in_voltage0_type:采樣類型,本設備該值為le:S16/16>>0,表示是小端有符號整型

buffer中的屬性為:

  • data_available :有多少數量的數據準備好了
  • enable :激活緩沖區捕獲,設置為1則開始緩沖區捕獲
  • length:緩沖區可以存儲的數據樣本總數
  • length_align_bytes: 對齊要求,用于設置DMA的對齊要求。
  • watermark:此屬性從內核版本 4.2 開始可用。它是一個正數,指定阻塞讀取應等待多少個掃描元素。如果使用輪詢,它將阻塞直到達到watermark設定值。只有當watermark大于請求的讀取量時才有意義。它不會影響非阻塞讀取。

在用戶空間讀取iio設備的數據,有掃描方法或者觸發方法,這里主要分享一下連續掃描讀取。

  • 首先將scan_elements中in_voltage0_en設置為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,也設置為1。驅動就開始工作了。marked complete 表示一次DMA傳輸結束。
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
  • 然后就可以標準文件操作直接讀取/dev/iio:device0了

代碼實現

有了前面的介紹,就有具體實現的思路了。這里以QT為例,設計一個類先進行文件操作,然后不停讀取文件即可。

下面是頭文件:

#ifndef _IIO_DEVICE_H_
#define _IIO_DEVICE_H_
#include <QObject>
#include <QMutex>
#include <QThread>
//繼承自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;
    //用于緩存數據
    QByteArray *buffer;
    QMutex *mutex;
    bool m_started;
};

#endif

實現文件如下:

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.關閉文件
    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();
    
  //完全關閉線程的寫法
  wait();
}

#define TEMP_BUFFER_SIZE 4096
//開辟線程用于讀取
void IIODevice::run()
{
  int bytes = 0;
  unsigned char devBuf[TEMP_BUFFER_SIZE];
  while(1) {
      bytes = 4096;//假定內部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用于線程間數據保護,由于該類是一個線程類,實際使用的時候可能是另一個線程讀取IIO設備的采集數據,用于傳輸或者后續應用處理,兩個線程操作同一個QByteArray對象,存在并發競態,所以需要做互斥訪問保護。

如此一來,外界的物理信號就經由ADC芯片,進入Linux內核設備iio:device0,再由用戶空間的IIODevice類所例化的對象,傳遞到用戶空間,從而可以在Linux下實現采樣應用了,整個信號傳遞可以用下面這個圖來描述。

總結一下

IIO設備在很多工業儀器類非常有用,如前所說,不僅僅能實現AD采樣,還可以實現DA,DDS等很多非常有應用價值的設備。要用好IIO設備,可能涉及到設備驅動、信號鏈設計、用戶空間應用程序編寫等等技術。本文以一個AD采樣IIO設備為例,分享一下如何從用戶空間訪問控制IIO設備,希望對有興趣的朋友們有所幫助。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 1
收藏 3
關注 79
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 中文字幕免费亚洲 | 免费不卡欧美自拍视频 | 中文在线精品 | 亚州日本乱码一区二区三区 | 久久久成人999亚洲区美女 | 欧美黑人粗暴多交高潮水最多 | 国内毛片毛片毛片毛片毛片毛片 | 日韩高清在线观看 | 温柔少妇的高潮呻吟 | 中文字幕第15页 | 精品无码aⅤ无码免费专区 美国一级毛片a | 偷妻无码一区二区三区动漫 | 久久久久久久久无码精品亚洲日韩 | 日本A级作爱片金瓶双艳 | 中文一二三区 | 91精品国产9 | 一性一交一伦一色一情人 | 日韩欧美大片在线观看 | 亚洲色精品VR一区二区 | 久久婷av | 国产精品自产拍在线观看55亚洲 | 麻豆视频免费 | 91网页入口| 亚洲高清不卡一区 | 亚洲欧洲日本无在线码天堂 | 国产福利在线观看视频 | 91在线观看网站 | 欧美少妇在线观看 | 温柔少妇的高潮呻吟 | eeuss影院www在线播放 | 中文字幕永久在线 | 午夜影院日韩 | 久久这里精品国产99丫e6 | 久久国产热视频 | 久久免费视频国产 | 色啪视频| 国产精品久久久久婷婷五月 | 日韩av片子 | 国产香蕉一区二区在线网站 | 亚洲成AV人片在线观看橙子 | 亚洲国产综合精品中久 |