Нарушения указателя кругового буфера

Это продолжение этого вопроса: Отображать ранее полученные значения UART.

После внедрения в микроконтроллер циклического буфера кажется, что есть проблема с указателями.

Отправлено по RS-232: ADE1234
Получено (буфер = 8): E24AE2 / E2AE24 (переключение между ними) Получено (буфер = 16): D234E1 (A пропущен, так как это синхробайт)
Получено (RX_BufSize = 32): DE1223 / DEE123 / DE1234 / DE12E1 (случайно переключается)
Ожидается получение : DE1234

Инициализация

// 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];

Значения отладки отображаются на ЖК-дисплее

//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, '\0'};
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], '\0'};
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], '\0'};
disp_string(-37, 7, 1, U4buf);

Получение прерывания

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;
    }
}

Функции из исходников

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 вызывается каждую 1/256 секунды. За это время в приемный буфер UART будет отправлено не менее 7 значений.

Возможно ли, что процесс записи настолько быстр, что догоняет указатель чтения? Что я могу сделать, чтобы решить эту проблему, помимо более частого вызова Detect_Cmd_RXD?


person JcMaco    schedule 01.12.2009    source источник
comment
Ну, я не мог найти решение вовремя. Итак, я только что вызвал Detect_Cmd_RXD примерно 7 раз в T3Interrupt. Спасибо за ваши ответы.   -  person JcMaco    schedule 24.12.2009


Ответы (2)


Первый шаг: Установите флаг в подпрограмме прерывания, если буфер переполняется, и проверьте наличие переполнения в подпрограмме Detect_Cmd_RXD. Посмотрите, как изменение размера буфера влияет на количество переполнений.

Второй шаг: если вы дошли до размера буфера, при котором нет переполнения, но все еще есть повреждения, внимательно посмотрите на процедуру обработки прерывания. UART могут быть весьма чувствительны к тому, как быстро вы получаете доступ к их регистрам или порядку операций. Проверьте техническое описание оборудования и убедитесь, что вы его правильно читаете, а еще лучше найдите какой-нибудь пример кода, который делает то же, что и вы. Повторяющиеся символы, когда размер буфера равен 32, могут означать, что вы дважды читаете регистр данных, прежде чем бит состояния успевает установиться.

person Tony van der Peet    schedule 01.12.2009

Не должно быть IFS0bits.U1RXIF = 0; быть установлен в конце подпрограммы?

Afaik завершает прерывание и разрешает новое.

person Marco van de Voort    schedule 03.12.2009