English 中文(简体)
Circular buffer pointer irregularities
原标题:

This is a follow up on this question: Display previously received UART values.

After implementing a circular buffer on the microcontroller, it seems that there is a problem with the pointers.

Sent on RS-232: ADE1234
Received (buffer = 8): E24AE2 / E2AE24 (Flips between the two) Received (buffer = 16): D234E1 (A is skipped, since it is a synchro byte)
Received (RX_BufSize = 32): DE1223 / DEE123 / DE1234 / DE12E1 (flips randomly)
Expected receive: DE1234

Initialization

// Source: Thème 207 BTS électronique – Académie de Strasbourg
#define RX_BufSize 8            // Taille du Buffer_RX
char Buffer_RX[RX_BufSize];     // Buffer circulaire de réception
char *ptrRX_WRdata = Buffer_RX; // Pointeur d écriture dans Buffer_RX
char *ptrRX_RDdata = Buffer_RX; // Pointeur de lecture dans Buffer_RX
unsigned char Buffer_Cmd[7];

Debug values displayed on LCD

//Printed debug values. Decoded output is seen via U2buf
disp_string(-62, 17, 0, "Ply2");
char U2buf[] = {slave_command, slave_pal_d, slave_bal_x,
                slave_bal_y, slave_point_a, slave_point_b,   };
disp_string(-37, 17, 1, U2buf);

char U3buf[] = {Buffer_RX[0], Buffer_RX[1], Buffer_RX[2], 
                  Buffer_RX[3], Buffer_RX[4], Buffer_RX[5], 
                  Buffer_RX[6], Buffer_RX[7],   };
disp_string(-37, 27, 1, U3buf);

char U4buf[] = {Buffer_Cmd[0], Buffer_Cmd[1], Buffer_Cmd[2], 
                  Buffer_Cmd[3], Buffer_Cmd[4], Buffer_Cmd[5], 
                  Buffer_Cmd[6],   };
disp_string(-37, 7, 1, U4buf);

Receive interrupt

void _ISR _NOPSV _U1RXInterrupt(void){
IFS0bits.U1RXIF = 0;    
while(U1STAbits.URXDA){
        *ptrRX_WRdata++=U1RXREG;
        if (ptrRX_WRdata == Buffer_RX+RX_BufSize) ptrRX_WRdata = Buffer_RX;
    }
    if (U1STAbits.OERR){
        U1STAbits.OERR = 0;
    }
}

Functions from source

int ReadRXD(char *c){
    if (ptrRX_RDdata==ptrRX_WRdata) return(0); // Pas de caractère reçu
    else{
        *c=*ptrRX_RDdata++;
        if (ptrRX_RDdata==Buffer_RX+RX_BufSize) ptrRX_RDdata=Buffer_RX;
        return(1);
    }
}


void Detect_Cmd_RXD(void){
    int i;
    char c;
    if (!ReadRXD(&c)) return;
    ACL_XY_AFFICHER_CARACTERE(5, 3,256+ Z ,1);
    ACL_XY_AFFICHER_CARACTERE(25, 3,256+c,1);
    for (i=1; i<7; i++) Buffer_Cmd[i-1]=Buffer_Cmd[i];
    Buffer_Cmd[6]=c;
    if (Buffer_Cmd[0]== A ){ //&& (Buffer_Cmd[4]==0xAA)){
        ACL_XY_AFFICHER_CARACTERE(15, 3,256+ Q ,1);

        slave_command = Buffer_Cmd[1];
        slave_pal_d = Buffer_Cmd[2];
        if (system_player == 2){
            slave_bal_x = Buffer_Cmd[3];
            slave_bal_y = Buffer_Cmd[4];
            slave_point_a = Buffer_Cmd[5];
            slave_point_b = Buffer_Cmd[6];
        }
    }
}

Detect_Cmd_RXD is called every 1/256th of a second. During that time, at least 7 values will have been sent in the UART receive buffer.

Could it be possible that the write process is so fast that it catches up on the read pointer? What can I do to solve this problem besides calling Detect_Cmd_RXD more often?

问题回答

First step: Set a flag in the interrupt routine if the buffer overruns, and check for overruns in the Detect_Cmd_RXD routine. See how changing the buffer size affects the number of overruns.

Second step: If you get to a buffer size where there are no overruns, and still have corruption, take a good look at the interrupt routine. UARTs can be quite sensitive to how quickly you access their registers, or the order of operations. Check the hardware datasheet and verify that you are reading it correctly - better still, find some sample code that does similar things to what you want to do. The repeated characters when buffer size is 32 could be you reading the data register twice before the status bit has had a chance to settle down.

Shouldn t IFS0bits.U1RXIF = 0; be set at the end of the routine?

Afaik it ends the interrupt and allows a new one.





相关问题
C: Accessing a pointer from outside a function

I have the following code: int takeEven(int *nums, int numelements, int *newlist) { newlist = malloc(numelements * sizeof *newlist); int i, found = 0; for(i = 0; i < numelements; ++i, ...

Scheme, getting the pointer from pointed struct

Assume I have a such struct: (define-struct node (value next)) ;and making 2 nodes, parent pointing to child as next. (define child (make-node 2 null)) (define parent (make-node 1 child)) Under ...

DO s and Donts while using pointers

Its a simple but important question. What are the do s and donts while using a pointers in C and C++ so as to make sure SEGMENTATION FAULT is avoided on AIX? Where char * are preferred over character ...

确保点名不删除

我 st卑地 something了我可以说出的东西,因此,我认为,在更大的C++图像中,我没有东西。

C#: Using pointer types as fields?

In C#, it s possible to declare a struct (or class) that has a pointer type member, like this: unsafe struct Node { public Node* NextNode; } Is it ever safe (err.. ignore for a moment that ironic ...

Data Destruction In C++

So, for class I m (constantly re-inventing the wheel) writing a bunch of standard data structures, like Linked Lists and Maps. I ve got everything working fine, sort of. Insertion and removal of ...

Question regarding de-referencing structure pointers

I am compiling this piece of code and I get compilation errors saying " dereferencing pointer to incomplete type" . I get the errors for the last print statement and before that where I try to point (...

热门标签