嵌入式Linux多通道数据采集方案

  使用英利工控主板进行简单的扩展,可以构成一个多通道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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值