Как отметил Emerick, memmove()
будет хорошо работать, если у вас есть доступ к нему. Если нет, просто возьмите простую реализацию этого у Google, это не должно занимать слишком много памяти инструкций.
Какая у вас тактовая частота на микроконтроллере? Еще одна вещь, о которой стоит подумать, это то, что, если ваша тактовая частота значительно выше, чем ваша скорость передачи, многие из этих вещей становятся беспроблемными. Например, если ваша тактовая частота составляет 16 МГц, вам действительно не нужно беспокоиться о создании самого короткого ISR в мире, если вы не делаете в нем ничего безумно вычислительного. Кроме того, если вы синхронизируете систему значительно быстрее, чем скорость передачи, опрос также является опцией.
РЕДАКТИРОВАТЬ: еще один вариант, о котором я только что подумал, используя прерывания.
Вы можете сохранить свой буфер в виде массива символов, а затем сохранить глобальный индекс для следующего пустого слота, например:
#define UART_BUF_SIZE 16
char uart_buf[UART_BUF_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0};
char uart_buf_index = 0;
Тогда в вашем ISR все, что вам нужно сделать, это выгрузить новый байт в корзину, на которую указывает индекс, и увеличить индекс. Это автоматически перезапишет самый старый символ в буфере, когда начальная позиция поворачивается обратно вокруг буфера.
void my_isr()
{
uart_buf[uart_buf_index] = get_uart_byte();
uart_buf_index = (uart_buf_index + 1) % UART_BUF_SIZE;
}
По сути, в этот момент у вас есть буфер с вращающейся стартовой позицией, но он избавляет вас от необходимости перемещать 16 байт памяти на каждый ISR. Хитрость заключается в том, чтобы прочитать его обратно, потому что вы должны учитывать обход.
char i;
for (i = uart_buf_index; i < UART_BUF_SIZE; i++)
{
lcd_write_byte(uart_buf[i]);
}
for (i = 0; i < uart_buf_index; i++)
{
lcd_write_byte(uart_buf[i]);
}