<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • 嵌入式Linux多通道數據采集方案

     2011-7-12             

            使用英利工控主板進行簡單的擴展,可以構成一個多通道AD數據采集方案。這一方案的原理是通過英利工控主板的精簡ISA總線擴展一片TLC2543,,即可以實現8路模擬量輸入。其中輸入量程0-5V,AD轉換精度12bit,AD轉換速度100Ksps。

     

    硬件部分
            該方案的主要硬件構成如下:

     

    嵌入式Linux多通道數據采集方案

     

            其中TLC2543通過4線制SPI接口與英利工控主板連接,具體信號定義如下:
            (1)SPI_CS:SPI片選信號,低電平有效;從英利工控主板輸出,接到TLC2543 
            (2)SPI_CK:SPI接口的同步時鐘信號;從英利工控主板輸出,接到TLC2543 
            (3)SPI_DO:SPI接口數據輸出,從英利工控主板輸出的轉換命令,輸入到TLC2543 
            (4)SPI_DI:SPI接口數據輸入,從AD芯片輸出的轉換數據,輸入到英利工控主板

     

            此時可以采用英利工控主板的GPIO模擬出SPI接口(以EM9160為例):
            #define SPI_CS    GPIO15
            #define SPI_CLK   GPIO14
            #define SPI_DOUT  GPIO13
            #define SPI_DIN   GPIO12
            #define SPI_EOC   GPIO10

     

            除AD輸入以外,該應用底板還有如下接口: 
            (1)1個10M/100M以太網接口 
            (2)4個帶隔離RS485總線接口,1個RS232串口,1個TTL串口 
            (3)2個USB Host接口,1個USB Device接口 
            (4)單色點陣液晶接口(支持LCD對比度調節和背光控制) 
            (5)矩陣鍵盤和LED接口 
            (6)精簡ISA總線接口

     

            該應用底板和英利工控主板配套,已經可以滿足一般的數采應用需求。如果客戶需要更多的數據輸入,可以參考該應用底板的方式進一步擴展;如果客戶需要更多的其他功能,可以參考英利的開發評估底板和功能擴展模塊進行設計。

     

    軟件部分
            TLC2543是4線制SPI接口,因此它的讀寫操作是同時進行的,即所謂全雙工串行數據傳輸。在構造函數時,需要仔細研究AD芯片數據手冊上提供的SPI接口時序關系,如下圖所示:

     

     

            軟件開發過程中需注意以下幾點:
            1、在SPI_CS片選有效后,TLC2543將把上次AD轉換的數據,按MSB在先的順序,呈現在SPI_DI信號線上,并在SPI_CK的
                  下降沿更新數據
            2、SPI_CK的上升沿將把對AD芯片的操作指令鎖存到AD芯片,輸出的數據也是按MSB在先的順序
            3、輸入AD的操作指令只有8個bit,而從AD讀出的轉換數據有12個bit,在讀入低4bit時,輸入指令用“0”填充
            4、芯片數據手冊中串行輸入輸出數據與我們的定義SPI_DO和SPI_DI是正好相反的
            5、讀出的數據須經過格式轉換,才能轉為通常所見的電壓值

     

            據上所述,可以構建相應的操作函數如下:

     

    // TLC2543的SPI接口初始化函數
    int SPI_Init( int fd )
    {
            SPI_OutEnable( fd, SPI_CS );
            SPI_OutEnable( fd, SPI_CLK );
            SPI_OutEnable( fd, SPI_DOUT );
            SPI_OutDisable( fd, SPI_DIN );
            SPI_OutDisable( fd, SPI_EOC );

            SPI_OutSet( fd, SPI_CS );
            SPI_OutClear( fd, SPI_CLK );

            return 1;
    }

    // 輸出使能
    int SPI_OutEnable( int fd, unsigned int dwEnBits )
    {
            int rc;

            rc = ioctl( fd, EM9X60_GPIO_IOCTL_OUT_ENABLE, &dwEnBits ); 
            return rc;
    }

    // 輸出禁止
    int SPI_OutDisable( int fd, unsigned int dwDisBits )
    {
            int rc;

            rc = ioctl( fd, EM9X60_GPIO_IOCTL_OUT_DISABLE, &dwDisBits );
            return rc;
    }

    // 位置高
    int SPI_OutSet( int fd, unsigned int dwSetBits )
    {
            int rc;

            rc = ioctl( fd, EM9X60_GPIO_IOCTL_OUT_SET, &dwSetBits );
            return rc;
    }

    // 位置低
    int SPI_OutClear( int fd, unsigned int dwClearBits )
    {
            int rc;

            rc = ioctl( fd, EM9X60_GPIO_IOCTL_OUT_CLEAR, &dwClearBits );
            return rc;
    }

    // 讀取位狀態
    int SPI_PinState( int fd, unsigned int* pPinState )

            int rc; 
            unsigned int dwCurrPinState;

            rc = ioctl( fd, EM9X60_GPIO_IOCTL_PIN_STATE, &dwCurrPinState );

            if( rc == 0 )
                    *pPinState = dwCurrPinState;

            return rc;
    }

    // 格式轉換為電壓值
    float GetDeltaV( )
    {
            int i1;
            unsigned int i2 = 0;

            for( i1=0; i1<10; i1++ )
                    i2 += ADData[i1];

            result = (i2/10) * DeltaV;
            return result;

     

            該應用方案程序的核心部分是數據處理函數int ReadAD( int ChNum ),該函數將模擬量讀出并轉換為浮點數格式,其相關處理代碼如下:

     

    int ReadAD( int ChNum )
    {
            unsigned int i1 = 0;
            int i2, i3;
            unsigned int dwPinState;
            unsigned int CtrlBit;

            // 將控制字轉換為標準的12位
            CtrlBit = (unsigned int)ChNum << 4;
            SPI_OutClear( fd, SPI_CS );

            // 等待轉換完成
            for( i2=0; i2<100; i2++ )
            {
                    SPI_PinState( fd, &dwPinState );
                    if( dwPinState & SPI_EOC );
                            break;
            }

            // 轉換失敗處理
            if( i2 >= 100 )
            {
                    SPI_OutSet( fd, SPI_CS );
                    return -14;
            }

            // 第一次讀出的是無效數據,讀出并且扔掉
            for( i2=0; i2<12; i2++ )
            {
                    i1 = i1 << 1;

                    SPI_PinState( fd, &dwPinState );
                    if( dwPinState & SPI_DIN )
                            i1 = i1 | 0x01;

                    if( CtrlBit & 0x800 )
                            SPI_OutSet( fd, SPI_DOUT );
                    else
                            SPI_OutClear( fd, SPI_DOUT );

                    SPI_OutSet( fd, SPI_CLK );
                    SPI_OutClear( fd, SPI_CLK );

                    CtrlBit = CtrlBit << 1;
            }

            // 正式讀取數據,讀十次,交由后面的GetDeltaV( )函數取平均值并轉換為電壓
            for( i3=0; i3<10; i3++ )
            {
                    i1 = 0;
                    CtrlBit = (unsigned int)ChNum << 4;
                    for( i2=0; i2<100; i2++ )
                    {
                            SPI_PinState( fd, &dwPinState );
                            if( dwPinState & SPI_EOC );
                                    break;
                    }

                    if( i2 >= 100 )
                    {
                            SPI_OutSet( fd, SPI_CS );
                            return -12;
                    }

                    for( i2=0; i2<12; i2++ )
                    {
                            i1 = i1 << 1;

                            SPI_PinState( fd, &dwPinState );
                            if( dwPinState & SPI_DIN )
                                    i1 = i1 | 0x01;

                            if( CtrlBit & 0x800 )
                                    SPI_OutSet( fd, SPI_DOUT ); 
                            else
                                    SPI_OutClear( fd, SPI_DOUT );

                            SPI_OutSet( fd, SPI_CLK );
                            SPI_OutClear( fd, SPI_CLK );

                            CtrlBit = CtrlBit << 1;
                    }

                    ADData[i3] = i1; 
            }

            SPI_OutSet( fd, SPI_CS );
            GetDeltaV( );
            return 1;
    }

     

            該方案的主流程如下:

     

    int main( )
    {
            int i;
            // 定義8個數據輸入通道
            int AIN[8] = {0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70};

            fd = open( '/dev/em9x60_gpio', O_RDWR );
            printf( 'open file = %d\n', fd );

            // 初始化SPI端口
            SPI_Init( fd );
            // 嵌入式程序,總是無限循環執行
            for( ; ; )
            {
                    // 循環讀取八個通道的數據
                    for( i=0; i<8; i++ )
                    {
                            ReadAD( AIN[i] );
                            printf( 'the result = %.2f V\n', result );
                    }
                    printf( '\n' );
                    sleep( 2 );
            }

            return 1;
    }

    亚洲精品美女久久久久99| 久久久国产成人精品| 99精品热女视频专线| 牛牛在线精品观看免费正| 一本一道久久a久久精品综合 | 国产精品揄拍一区二区久久| 国产精品国产三级国产AⅤ| 国内精品免费麻豆网站91麻豆 | 亚洲精品中文字幕乱码| 国产精品国产三级国产潘金莲| 成人区精品一区二区不卡亚洲| 国产精品毛多多水多| 在线亚洲精品福利网址导航| 精品videossexfreeohdbbw| 四虎国产成人永久精品免费| 亚洲精品亚洲人成在线| 国产成人精品AA毛片| 国产精品无码亚洲一区二区三区 | 国产精品乱码在线观看| 国产精品久久久久久久久| 久久这里只精品热免费99| 国产精品videossex白浆| 精品伊人久久大香线蕉网站| 亚洲无线观看国产精品| 国产91精品在线| 国产69精品久久久久9999| 国产精品久久无码一区二区三区网| 中国精品videossex中国高清| 国产美女精品一区二区三区| 国产精品九九久久免费视频| 国产午夜精品1区2区3福利| 久热综合在线亚洲精品| 在线精品无码字幕无码AV| 日韩精品一区二区三区中文字幕| 国产四虎免费精品视频| 无码人妻精品一区二区三区在线| 野狼第一精品社区| 97精品国产91久久久久久| 精品一区二区三区免费视频| 国产99视频免费精品是看6| 精品剧情v国产在免费线观看|