ETA104数采模块实现波形信号采集

 2018-6-20     作者:朱贤武         

  ETA104模拟数据采集模块(下文简称:ETA104模块)是基于英创公司SBC840工控应用底板、符合DM5028标准应用扩展模块。ETA104模块上的模数转换功能,采用ADS7871模拟信号转换芯片,占用ESMARC工控主板的SPI总线进行通讯,最高可实现48K的数据转换率,最大支持8路14bit模拟信号转换。


  ETA104模块的A/D转换芯片的数据转换启动方法有2种,一种方法是使用软件写入指令启动数据转换,第二种方法是使用引脚“ADConvert”启动数据转换:在该引脚上产生一个由低到高的上升沿,便可根据最近一次的A/D输入端口配置,启动一次数据转换,同时引脚“ADBUSY”由低电平变为高电平;当前数据转换完成后,引脚信号“ADBUSY”会产生一个由高到低的下降沿,表示当前数据已经转换好。


  根据ETA104模块的这种特点,可以很方便地实现波形数据采样,基本思路如下:1、配置A/D转换芯片,以满足需要采集的模拟信号输入端口与输入方式;2、根据数据采样率需求,配置PWM输出参数,然后启动PWM信号,经由ADConvert信号引脚触发启动A/D数据转换;3、当数据转换完成以后,由ADBUSY信号触发系统IRQ中断;4、系统中断后,启动SPI总线进行当前数据读取。


  ADConvert信号通过ETA104的J1.P25脚接入,连接到ESMARC工控主板的PWM1信号端口;ADBUSY信号通过ETA104的J1.30脚输出,连接到ESMARC工控主板的IRQ1信号端口。ETA104数据采样控制信号所占用的相关引脚,如下表所示:


无标题文档

引脚信号名称功能描述
J1.25GPIO6PWM1信号输出用于等时采样时,启动AD转换,该信号连接到ADConvert
J1.30GPIO24中断输入IRQ1数据转换完成,通过ADBUSY信号输出下降沿到IRQ1
J1.38GPIO28SPI_MISO控制ADC器件的SPI总线信号
J1.40GPIO29SPI_MOSI
J1.42GPIO30SPI_CLK
J1.44GPIO31SPI_CSn


  模拟信号采样流程参考图如下:


ETA104数采模块实现波形信号采集.png


  程序流程说明:

  1、初始化A/D,主要是配置模拟信号输入方式、模拟信号输入通道、A/D片内增益。

  2、要得到高精度的等时采集点的数据,因此使用PWM信号来启动A/D的数据转换,以达到非常高的时间要求精度。

  3、系统使用A/D芯片的BUSY信号的下降沿,触发系统中断,通知系统,当前数据已经准备好。

  4、以上资源初始化好以后,就可以开始启动A/D转换了。直接启动PWM信号输出即可。

  5、等待IRQ中断消息,即表示当前数据转换完成。

  6、利SPI总线读取A/D已转换好的数据并存贮。

  7、检查要采样的数据个数是否已达到,则关闭PWM输出,停止数据采样。然后关才IRQ、PWM相关设备。


  以下是基于ESM9287-WinCE6.0环境的例子程序。由于ESM9287的IRQ响应速度限制,该环境最大数据采样率只能到2Kbps。

  

// 申请一个数据Buff空间,用于存放采样数据结果
       AD_DataBuff = new DWORD[AD_CovCount];
       if(AD_DataBuff == NULL)
              return ;
       
       // 初始化A/D,配置A/C采样通道与信号输入模式
       MyADC_Test.ADS7871_ConfigREG(ADS7818_REG_GainMux,AD_Channel);
 
       // 初始化IRQ,配置中断源IRQ1作为系统触发
       hIRQ1 = CreateFile(_T("IRQ1:"),                          
              GENERIC_READ|GENERIC_WRITE,         
              FILE_SHARE_READ|FILE_SHARE_WRITE,      
              NULL,                                                          
              OPEN_EXISTING,                                    
              FILE_FLAG_RANDOM_ACCESS,                    
              NULL);                                                        
       if(hIRQ1==INVALID_HANDLE_VALUE)
       {
              printf("Open IRQ1 false!\r\n");
              return ;
       }
 
       // 初始化PWM信号,使用PWM1作为A/D转换启动信号
       hPWM = CreateFile( _T("PWM1:"),              
              GENERIC_READ|GENERIC_WRITE,          
              FILE_SHARE_READ|FILE_SHARE_WRITE, 
              NULL,                                                           
              OPEN_EXISTING,                                     
              FILE_FLAG_RANDOM_ACCESS,                     
              NULL);                                                         
       if(hPWM==INVALID_HANDLE_VALUE)
       {
              printf("Open PWM false!\r\n");
              return ;
       }
 
       PwmInfo.dwFreq = AD_CovRate; //设置PWM输出频率为数据采样率,如1000Hz
       PwmInfo.dwDuty = 10;
       PwmInfo.dwResolution = 1;
       dwNumberOfBytesWritten = 0;
       bRet = WriteFile(hPWM, &PwmInfo, sizeof(PWM_INFO), &dwNumberOfBytesWritten, NULL);
       if(!bRet)
       {
              printf("WriteFile failed\n");
              CloseHandle(hPWM);
       }
 
       i1 = 0;
       while(1) //数据采样循环控制
       {
              dwTimeout = 5; //timeout 5ms
              if (!DeviceIoControl(hIRQ1,                  //等待中断触发信号
                    IOCTL_WAIT_FOR_IRQ,                    
                     &dwTimeout,                                        
                     sizeof(DWORD),                            
                     &dwReturn,                                    
                     sizeof(DWORD),                             
                     NULL,                                               
                     NULL))                                             
              {
                     dwReturn =  WAIT_FAILED;
              }
 
              if(dwReturn == WAIT_OBJECT_0)
              {
                     i1++;
                     MyADC_Test.ADS7871_Read( &AD_DataBuff[i1] );//读取AD采样好的数据
                     if(i1>=AD_CovCount) //判断数据采样个数是否已达到设置值
                            break;
              }
       }
 
       PwmInfo.dwFreq = 0; 
       PwmInfo.dwDuty = 10;
       PwmInfo.dwResolution = 1;
       dwNumberOfBytesWritten = 0;
       bRet = WriteFile(hPWM, &PwmInfo, sizeof(PWM_INFO), &dwNumberOfBytesWritten, NULL); //停止PWM输出
 
       CloseHandle(hPWM);//关闭PWM设备
       CloseHandle(hIRQ1); //关闭IRQ设备
       //数据复制/转移到用户数据BUFF
       //......
       delete[] AD_DataBuff;//清理申请的运态数据空单