带有128KB缓存的AD7606模拟采集板

举报
tsinghuazhuoqing 发表于 2021/12/26 23:21:05 2021/12/26
【摘要】 01简介 构建多路16bit的AD采集器,并可以进行高速缓存,对于采集静态电压,还是动态波形都非常有利。在23LC1024四线访问数据博文中介绍了对扩展SPI接口RAM(128kB)的四线制高速访问的方...

01简介

构建多路16bit的AD采集器,并可以进行高速缓存,对于采集静态电压,还是动态波形都非常有利。在23LC1024四线访问数据博文中介绍了对扩展SPI接口RAM(128kB)的四线制高速访问的方法。在AD7606八通道AD采集模块测试博文中给出了基于AD7606芯片的AD采集电路模块的测量。在博文扩展32KRAM的STC8H8K信号采集版中给出了利用WiFi-UART模块,实现采集数据的高速无线传送。

▲ 插图|来自网络

▲ 插图|来自网络

下面给出了该系统的设计以及相关调试结果。


02电路系统设计

1. 电路设计

就在23LC1024四线访问数据的基础上1,增加WiFi接口,完成模块的设计。

▲ 电路原理图

▲ 电路原理图

铺设PCB适合于单面PCB快速制版。

▲ PCB图

▲ PCB图

 


03电路测试

1.硬件测试

在正式下载程序之前,对电路施加5V工作电源,测量对应的静态工作电流,LM1117输出的3.3V电压信号。

1)对单片机的硬件配置

参考在“23LC1024四线访问数据”中对单片机的配置,设置单片机IRC工作频率为35MHz.

▲ 通电后的电路

▲ 通电后的电路

2) 下载程序进行交互测试23

下位机中的响应交互程序代码片段为,这是用来测试23LC1024串行SPI接口的RAM功能。

    else IFARG0("rm") {
        ucChar = LC1024ReadMode();
        printf("LC1024 mode:%bx\r\n", ucChar);
        
    } else IFARG0("wm") {
        sscanf(SDA(1), "%bx", &ucChar);
        LC1024WriteMode(ucChar);
        ucChar = LC1024ReadMode();
        printf("LC1024 mode:%bx\r\n", ucChar);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

通过使用rd, wr来对23L1024进行读写测试。,验证读写正常。

2.测试AD转换功能

交互代码如下:

    } else IFARG0("data") {
    
        AD7606Convert();
        AD7606ReadData(nAD, 4);        
        
        for(i = 0; i < 8; i ++) {
            printf("%d ", nAD[i]);
            
        }
        printf("\r\n");
    } else IFARG0("datamean") {
        sscanf(SDA(1), "%d", &nSize);
        
        if(nSize == 0) nSize = 1;

        for(i = 0; i < 8; i ++) lnADSigma[i] = 0;
        
        for(i = 0; i < nSize; i ++) {
            AD7606Convert();
            AD7606ReadData(nAD, 4);
            for(j = 0; j < 8; j ++) 
                lnADSigma[j] += nAD[j];
        }
        
        for(i = 0; i < 8; i ++) {
            printf("%d ", (int)(lnADSigma[i] / nSize));            
        }
        printf("\r\n");
    
    } else IFARG0("rangeon") {
        ON(AD7606_RANGE);
          
    } else IFARG0("rangeoff") {
        OFF(AD7606_RANGE);
        
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

▲ 连接有AD7606测试系统

▲ 连接有AD7606测试系统

  • 使用data:获取当前采样一次的数值;
  • 使用datamean:获取相近采集平均数据。命令: datamean , 其中参数你标示采集数据平均的结果。
  • rangeon: 设置采集电压范围 ± 10 V \pm 10V ±10V
  • rangeoff:设置采集电压范围: ± 5 V \pm 5V ±5V

3.测试中断内采集

使用Timer2实现10kHz的中断频率。在其中断程序里完成AD7606的8路16bit数据采集,并存储在23LC1024中。

1) 设置Timer2

//==============================================================================
#if TIME2_INT_EN
//------------------------------------------------------------------------------
void Timer2Init(void) {

    AUXR |= 0x04;		
    T2L = 0x54;		
    T2H = 0xF2;		
    IE2 |= 0x4;                         // 7:ETKSU1 6:ET4: 5:ET3: 4:ES4: 3:ES3, 2:ET2, 1:ESPI, 0:ES2
    AUXR |= 0x10;		

    //--------------------------------------------------------------------------
    g_nTimer2IntCount = 0;    
    
    
}

void Timer2ISR(void) interrupt 12 using 1 {
    int nAD[8];
    unsigned char * p;
    unsigned char i;
    
    g_nTimer2IntCount ++;
    //----------------------------------------------------------------------    
    
    if(g_ucADSampleFlag) {
        AD7606Convert();
        AD7606ReadData(nAD, 4);
        
        p = (unsigned char *)nAD;
        LC1024WriteBegin(g_ucAdd2, g_ucAdd1, g_ucAdd0);
        
        for(i = 0; i < 16; i ++) 
            LC1024Write(*(p ++));
        
        LC1024ReadWriteEnd();
        
        g_ucAdd0 += 16;
        if(g_ucAdd0 == 0) {
            g_ucAdd1 ++;
            if(g_ucAdd1 == 0)
                g_ucAdd2 ++;
        }
    }
}
#endif // TIME2_INT_EN

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

在STC8G指令中,上述使用unsigned char 的指针来访问int数字,将相应的8个short整型数据写入SPI接口的23LC1024内部。在C51中是按照Big-Endian模式存储数据的。所以在通过bytes回复int16的过程中,是高字节在前,低字节在后。

▲ Big-Endian vs. Little-Endian

▲ Big-Endian vs. Little-Endian

2) 测量转换时间

在实验“AD7606八通道AD采集模块测试”中,测量了AD7606转换函数AD7606Convert的执行时间大约为 T A D = 4.17 μ s T_{AD} = 4.17\mu s TAD=4.17μs

通过测量LC1024的片选信号CS信号可以测量LC1024写入16个字节所需要的时间。在23LC1024四线访问数据中给出了LC1024的片选信号在PIN1。

▲ 测量LC1024的CS信号,确定写入16个字节所需要的时间

▲ 测量LC1024的CS信号,确定写入16个字节所需要的时间

LC1024连续写入16个字节(AD7606转换的8个16bitAD结果)所需要的时间为: T W R = 24.3 μ s T_{WR} = 24.3\mu s TWR=24.3μs.。

那么在Timer2的10k中断的时间 T i n t = 100 μ s T_{{\mathop{\rm int}} } = 100\mu s Tint=100μs内,所需要执行的AD转换和存储所需要的总时间大约为: T T 2 = T A D + T W R = 4.17 + 24.3 = 28.47 μ s T_{T2} = T_{AD} + T_{WR} = 4.17 + 24.3 = 28.47\mu s TT2=TAD+TWR=4.17+24.3=28.47μs

占用中断时间大太阳30%的时间。

3)修改UART1优先级

由于TImer2占用了30% 的时间,就影响了UART1通过460800波特率接收对应的上位机的指令,出现了丢失字符的现象。
需要通过修改Timer2,UART1的优先级来进行调整。使得UART1能够中断Timer2接收上位机的指令。

STC8G内部的中断源定义如下图所示。总共分为4个中断优先级别。0:为最低,3:为最高优先级。

▲ STC8G 内部中断源的定义

▲ STC8G 内部中断源的定义

UART1的优先级是由IP,IPH中的4bit定义; Timer2的优先级始终为0(最低)。
▲ UART,TIMER2

▲ UART,TIMER2

通过将IP,IPH中的PS,PSH修改成1, 定义为优先级为3(最高),就可以使得UART1中断Timer2完成串行命令的接受el。
▲ 确定串口优先级的IP,IPH寄存机对应的位定义

▲ 确定串口优先级的IP,IPH寄存机对应的位定义

在原来的C51Basic中UARInit()函数中增加如下代码,对其中IP, IPH修改其中的bit4。

    //--------------------------------------------------------------------------
#if UART1_INT_EN
    IP |= 0x10;                             // Set Serial1 Interrupt prority as 3
    IPH |= 0x10;
    
    g_ucUART1BufferHead = g_ucUART1BufferTail = 0;
    g_ucTIFlag = 0;
    
    ES = 1;
#endif //  UART1_INT_EN    

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

修改完之后,便可以解决原来接收上位机指令丢失字符的问题了。

4. 获取采集的信号波形

在串口命令中增加了如下控制命令,可以获得AD采集到的波形信号。

▲ 采集的信号波形,使用示波器观察到的480

▲ 采集的信号波形,使用示波器观察到的

▲ 获得采集后的信号波形

▲ 获得采集后的信号波形

更换三角波形:
▲ 输入三角波形

▲ 输入三角波形

▲ AD7606采集到的三角形好的波形

▲ AD7606采集到的三角形好的波形

    } else IFARG0("showad") {
        nSize = 0x100;
        ucChannel =1 ;
        if(STD_NUM > 1) sscanf(SDA(1), "%d", &nSize);
        if(STD_NUM > 2) sscanf(SDA(2), "%bd", &ucChannel);
        STOP_SAMPLE;
        
        //----------------------------------------------------------------------
        lnAddress = GetADAddress();
        lnAddress -= nSize * 16;
        ucAdd2 = (unsigned char)(lnAddress >> 16);
        ucAdd1 = (unsigned char)(lnAddress >> 8);
        ucAdd0 = (unsigned char)lnAddress;
        LC1024ReadBegin(ucAdd2, ucAdd1, ucAdd0);
        
        for(i = 0; i < nSize; i ++) {
            pData = (unsigned char *)nAD;
            for(j = 0; j < 16; j ++) 
                *(pData ++) = LC1024ReadByte();
                              
            for(j = 0; j < ucChannel; j ++) 
                printf("%d ", nAD[j]);

        }
        
        
        LC1024ReadWriteEnd();        
        printf("\r\n"        );
        START_SAMPLE;
    } else IFARG0("showadbin") {
        nSize = 0x100;
        ucChannel =1 ;
        if(STD_NUM > 1) sscanf(SDA(1), "%d", &nSize);
        if(STD_NUM > 2) sscanf(SDA(2), "%bd", &ucChannel);
        STOP_SAMPLE;
        
        //----------------------------------------------------------------------
        lnAddress = GetADAddress();
        lnAddress -= nSize * 16;
        ucAdd2 = (unsigned char)(lnAddress >> 16);
        ucAdd1 = (unsigned char)(lnAddress >> 8);
        ucAdd0 = (unsigned char)lnAddress;
        LC1024ReadBegin(ucAdd2, ucAdd1, ucAdd0);
        
        for(i = 0; i < nSize; i ++) {
            pData = (unsigned char *)nAD;
            for(j = 0; j < 16; j ++) SendChar(LC1024ReadByte());
        }
        
        
        LC1024ReadWriteEnd();        
        START_SAMPLE;
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

下面的代码是不带Buffer版本的外部命令。它可以连续读取AD7606转换的数值。
具体实现是通过 C51-Ver2:NoBuffer。

if(strcmp("hello",                (char *)STD_ARG[0]) == 0)
    printf("%s is ready !\r\n", VERSION_STRING);
else IFARG0("ad") {
    sscanf(SDA(1), "%d", &nNumber);
    sscanf(SDA(2), "%d", &nChannel);
    sscanf(SDA(3), "%d", &nWaitTime);
    g_ucWaitMS = 0;
    for(i = 0; i < nNumber; i ++) {
        while(g_ucWaitMS != nWaitTime);
        g_ucWaitMS = 0;
        AD7606Convert();
        AD7606ReadData(nData, 4);
        for(j = 0; j < nChannel; j ++) {
            nNum = nData[j];
            SendChar((unsigned char)(nNum >> 8));
            SendChar((unsigned char)nNumber);
        }
    }
}
else IFARG0("adtext") {
    sscanf(SDA(1), "%d", &nNumber);
    sscanf(SDA(2), "%d", &nChannel);
    sscanf(SDA(3), "%d", &nWaitTime);
    g_ucWaitMS = 0;
    for(i = 0; i < nNumber; i ++) {
        while(g_ucWaitMS != nWaitTime);
        g_ucWaitMS = 0;
        AD7606Convert();
        AD7606ReadData(nData, 4);
        for(j = 0; j < nChannel; j ++) {
            nNum = nData[j];
            printf("%d ", nNum);
        }
    }
} else IFARG0("ad5v") {
    OFF(AD7606_RANGE);        
} else IFARG0("ad10v") {
    ON(AD7606_RANGE);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

04结论

经过测试,基于AD7606的八路AD采样板基本上达到了设计要求,可以用于之后的信号处理的实验。


  1. 电路工程文件:AD\Test\2020\TestAD7606STC\TestAD7606STC8G.SchDoc ↩︎

  2. C51程序工程Ver1:C51\STC\Test\2020\testAD76068G1K\TestAD76068G.uvproj ↩︎

  3. C51程序-NoBuffer:C51\STC\Tools\AD7606\Sample8G1KNoBuffer\Sample8G1KNoBuffer.uvproj ↩︎

文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。

原文链接:zhuoqing.blog.csdn.net/article/details/105980787

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。