Неровности указателя кругового буфера - PullRequest
1 голос
/ 01 декабря 2009

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

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

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

1024 * инициализация *

// 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/255 секунды. В течение этого времени в буфере приема UART будет отправлено не менее 7 значений.

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

Ответы [ 2 ]

1 голос
/ 03 декабря 2009

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

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

1 голос
/ 01 декабря 2009

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

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

...