1

我对在 AM335X Cortex A8 处理器上运行的 beaglebone black world 有点陌生,我想使用 PRU 以尽可能最大的采样率进行快速模拟读取。

我想以循环形式读取所有 7 个输入,例如:

while( n*7 < sampling_rate){ //initial value for n = 0
    read(AIN0); //and store it in shared memory(7*n + 0)
    read(AIN1); //and store it in shared memory(7*n + 1)
    read(AIN2); //and store it in shared memory(7*n + 2)
    read(AIN3); //and store it in shared memory(7*n + 3)
    read(AIN4); //and store it in shared memory(7*n + 4)
    read(AIN5); //and store it in shared memory(7*n + 5)
    read(AIN6); //and store it in shared memory(7*n + 6)
    n++;
}

这样我就可以从主处理器上运行的主机程序中读取它们。知道怎么做吗?我尝试从名为 AM335x_pru_package 的包中使用名为 ADCCollector.c 的现成代码,但我不知道如何获取所用寄存器的所有地址和值。

这是我试图修改的代码(ADCCollector.p):

.origin 0 // offset of the start of the code in PRU memory
.entrypoint START // program entry point, used by debugger only

#include "ADCCollector.hp"

#define BUFF_SIZE 0x00000fa0 //Total buff size: 4kbyte(Each buffer has 2kbyte: 500 piece of data
#define HALF_SIZE BUFF_SIZE / 2

#define SAMPLING_RATE 1 //Sampling rate(16khz) //***//16000
#define DELAY_MICRO_SECONDS (1000000 / SAMPLING_RATE) //Delay by sampling rate
#define CLOCK 200000000 // PRU is always clocked at 200MHz
#define CLOCKS_PER_LOOP 2 // loop contains two instructions, one clock each
#define DELAYCOUNT DELAY_MICRO_SECONDS * CLOCK / CLOCKS_PER_LOOP / 1000 / 1000 * 3  //if sampling rate = 98000 --> = 3061.224

.macro DELAY
    MOV r10, DELAYCOUNT
    DELAY:
        SUB r10, r10, 1
        QBNE DELAY, r10, 0
.endm

.macro READADC
    //Initialize buffer status (0: empty, 1: first buffer is ready, 2: second buffer is ready)
    MOV r2, 0
    SBCO r2, CONST_PRUSHAREDRAM, 0, 4 

    INITV:
        MOV r5, 0 //Shared RAM address of ADC Saving position 
        MOV r6, BUFF_SIZE  //Counting variable 

    READ:
        //Read ADC from FIFO0DATA
        MOV r2, 0x44E0D100 
        LBBO r3, r2, 0, 4 
        //Add address counting
        ADD r5, r5, 4
        //Write ADC to PRU Shared RAM
        SBCO r3, CONST_PRUSHAREDRAM, r5, 4 

        DELAY

        SUB r6, r6, 4
        MOV r2, HALF_SIZE
        QBEQ CHBUFFSTATUS1, r6, r2 //If first buffer is ready
        QBEQ CHBUFFSTATUS2, r6, 0 //If second buffer is ready
        QBA READ

    //Change buffer status to 1
    CHBUFFSTATUS1:
        MOV r2, 1 
        SBCO r2, CONST_PRUSHAREDRAM, 0, 4
        QBA READ

    //Change buffer status to 2
    CHBUFFSTATUS2:
        MOV r2, 2
        SBCO r2, CONST_PRUSHAREDRAM, 0, 4
        QBA INITV

    //Send event to host program
    MOV r31.b0, PRU0_ARM_INTERRUPT+16 
    HALT
.endm

// Starting point
START:
    // Enable OCP master port
    LBCO r0, CONST_PRUCFG, 4, 4      //#define CONST_PRUCFG      C4     taken from ADCCollector.hp
    CLR r0, r0, 4
    SBCO r0, CONST_PRUCFG, 4, 4

    //C28 will point to 0x00012000 (PRU shared RAM)
    MOV r0, 0x00000120
    MOV r1, CTPPR_0
    ST32 r0, r1

    //Init ADC CTRL register
    MOV r2, 0x44E0D040
    MOV r3, 0x00000005
    SBBO r3, r2, 0, 4

    //Enable ADC STEPCONFIG 1
    MOV r2, 0x44E0D054
    MOV r3, 0x00000002
    SBBO r3, r2, 0, 4



    //Init ADC STEPCONFIG 1
    MOV r2, 0x44E0D064
    MOV r3, 0x00000001 //continuous mode
    SBBO r3, r2, 0, 4

    //Read ADC and FIFOCOUNT
    READADC

另一个问题是:如果我只是将 (.p) 文件中的 #define Sampling_rate 从 16000 更改为低于或等于 200000 的任何其他数字,我会得到该采样率吗?还是我应该改变其他东西?

提前致谢。

4

2 回答 2

0

我使用了 libpruio 的 c 包装器:http ://www.freebasic.net/forum/viewtopic.php?f=14&t=22501

然后使用此代码获取我所有的 ADC 值:

#include "stdio.h"
#include "c_wrapper/pruio.h" // include header
#include "sys/time.h"

//! The main function.
int main(int argc, char **argv) {
    struct timeval start, now;
    long mtime, seconds, useconds;    
    gettimeofday(&start, NULL);
    int i,x;
    pruIo *io = pruio_new(PRUIO_DEF_ACTIVE, 0x98, 0, 1); //! create new driver structure
    if (pruio_config(io, 1, 0x1FE, 0, 4)){ // upload (default) settings, start IO mode
      printf("config failed (%s)\n", io->Errr);}
    else {

        do {
            gettimeofday(&now, NULL);
            seconds  = now.tv_sec  - start.tv_sec;
            useconds = now.tv_usec - start.tv_usec;
            mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
            printf("%lu",mtime);
            for(i = 1; i < 9; i++) {
                printf(",%d", io->Adc->Value[i]); //0-66504 for 0-1.8v
            }
            printf("\n"); 

            x++;
        }while (mtime < 100);

        printf("count: %d \n", x);

        pruio_destroy(io);        /* destroy driver structure */
    }
    return 0;
}
于 2015-01-09T20:27:13.900 回答
0

在您的示例中,您在 IO 模式(同步)下使用 libpruio,因此您无法控制采样率,因为主机 CPU 无法实时工作。

要获得最大采样率(如 OP 中所述),您必须使用 RB 或 MM 模式。在这些模式下,libpruio 在内存中缓冲样本,主机可以异步访问它们。请参阅 libpruio 包中的示例 rb_file.c(或 triggers.bas)。

于 2015-01-12T16:03:42.137 回答