2015-09-25 2 views
1
  • Микроконтроллер: dsPIC33EP512MU810
  • Компилятор: MikroC

Я пытаюсь запросить несколько байт из удаленного устройства через UART. Чтобы получить необходимую информацию, вы отправляете один байт запроса, чтобы получить один байт данных. У меня возникают трудности с идентификацией байтов данных при запросе более одного.MikroC, UART. Запрашивающая несколько байт

УАПП Принимающий обрабатывается с помощью прерывания:

void UART2RXInterrupt() iv IVT_ADDR_U2RXINTERRUPT 
{ 
    uart_rd2[LoopVar0] = UART2_Read();  //Read into buffer 
    LoopVar0++; 
    if (LoopVar0 >= 1) 
    { 
     LoopVar0 = 0; 
     ready0 = 1; 
    } 
    U2RXIF_bit = 0;       //Reset interrupt flag 
} 

Мой код для одного байта данных выглядит следующим образом:

UART2_Write(0x11); //Request byte 
if (ready0 == 1)  //Data received and ready 
{ 
    //Parse data byte 
    ready0 = 0;   //Reset data received bit 
} 

Это прекрасно работает.

Если мне нужно больше, чем просто байт один данных я делаю следующим образом

UART2_Write(0x11); //Request byte 11h 
if (ready0 == 1)  //Data received and ready 
{ 
    //Parse data byte 
    ready0 = 0;   //Reset data received bit 
} 
UART2_Write(0x14); //Request byte 14h 
if (ready0 == 1)  //Data received and ready 
{ 
    //Parse data byte 
    ready0 = 0;   //Reset data received bit 
} 

Проблема этого метода состоит в том, что следующий запрос байт может быть уже передан не будучи уверенным, что последний байт данных правильно получено.

Это приводит к тому, что данные становятся «скремблированными». Это означает, что байт данных из последнего запроса может быть проанализирован в текущем запросе и так далее.

Я не могу найти подходящее решение для этого. Любые предложения были бы замечательными!

Круговая реализация буфера:

UART прерываний:

void UART2RXInterrupt() iv IVT_ADDR_U2RXINTERRUPT 
{ 
    uart_rcv[write_buffer_pointer0] = UART2_Read(); // put received char in circular buffer 
    write_buffer_pointer0++;    // increment pointer 
    if (write_buffer_pointer0 > 511) { 
    write_buffer_pointer0 = 0;   // reset pointer 
    } 

    U2RXIF_bit = 0; 
} 

Основная обработка петли:

void service_UART() 
{ 
UART_send(0x14);  //MAP request 
UART_send(0x1D);  //ECT request 

if (read_buffer_pointer0 != write_buffer_pointer0) { // new data in circular buffer 
    ser_in();        // handle incoming serial data 
    } 
} 

УАПП отправить рутина:

void UART_send(volatile char data0) 
{ 
uart_snd[write_buffer_pointer1] = data0; 
write_buffer_pointer1++;    // increment pointer 
if (write_buffer_pointer1 > 511) { 
    write_buffer_pointer1 = 0;   // reset pointer 
} 
UART2_Write(data0); 
} 

Обработка полученных данных:

void ser_in() 
{ 
volatile char rqst; 
volatile char resp; 

resp = uart_rcv[read_buffer_pointer0]; // read next character from buffer 
read_buffer_pointer0++;     // increment read buffer pointer 
if (read_buffer_pointer0 > 511) {  // if pointer past end of buffer 
    read_buffer_pointer0 = 0;   // reset pointer 
} 
rqst = uart_snd[read_buffer_pointer1]; 
read_buffer_pointer1++; 
if (read_buffer_pointer1 > 511) { 
    read_buffer_pointer1 = 0; 
} 
// do something with the data here. 
if (rqst == 0x14) //If MAP request 
{ 
//Handle MAP Data 
} 
if (rqst == 0x1D) //If ECT request 
{ 
//Handle ECT Data 
} 
} 
+0

Что вы за платформа? Какова ваша платформа/SDK? Как и где управляется 'ready0'? Нам нужно больше информации и кода, которые помогут вам. – LPs

+0

Я добавил информацию. Thnx! – Felix

+0

Зачем вам сбросить свой индекс буфера каждый раз, когда получен байтов? – LPs

ответ

1

Реализовать два circular queues с головой и хвостом указатели (индексы), достаточно большой, чтобы разместить пропускную. Определите минимальное время, требуемое ответчиком между запросами и уважение к нему. Каждый раз, когда вы отправляете запрос, добавьте его в первую очередь, «очередь отправленных запросов». Когда приходит ответ, добавьте его во вторую очередь в вашей процедуре прерывания и увеличьте указатель на голову. Это ваша «полученная ответная очередь».

Затем вы можете обрабатывать транзакции асинхронно в своем основном цикле. Сравните вторую очередь очереди с хвостом. Каждый раз, когда вторая очередь становится несбалансированной (голова не равна хвосту), вы получили хотя бы один ответ. Первая очередь сообщает вам запрос, на который он ответил. Каждый раз, когда вы завершаете обработку ответа, продвигайте указатели на хвост обеих очередей.

Возможно, вы захотите сбросить очереди, если вы не получите ответ (если очереди остаются несбалансированными слишком долго) и убедитесь, что очереди не перезаписываются.

+0

Я пытаюсь разобраться в этом, так как я еще не был familiair с круговыми очередями. Если я правильно понял, мне нужно сделать это: ** - ** _ Каждый раз, когда запрос отправляется, добавьте его в очередь запросов ' ** - ** _ Каждый раз, когда очередь «получения» продвигается, потому что Произошло прерывание UART; Dequeue или «pop» из обеих очередей, чтобы получить байт запроса с соответствующими данными byte._ – Felix

+1

@Felix Да, процедура прерывания будет продолжать вводить новые данные в очередь по мере ее поступления, независимо от того, обрабатывает ли предыдущие обмены завершено. Поддержание очереди запросов сообщает вам, к какому запросу относится следующий ответ, к которому принадлежит поп. – jolati

+0

Хорошо. Мне нужно будет найти время для внедрения и тестирования. Это похоже на хорошее решение. Думаете, размер должен быть эквивалентен количеству разных запросов? – Felix

Смежные вопросы