Это не единственные два варианта, и второй вариант кажется неоптимальным.
Мой первый подход - создать простую циклическую очередь, вставлять байты в нее из ISR и читать байты в главнойпетля.Таким образом, у вас есть маленький и простой ISR, и вы выполняете обработку в своем основном цикле, не отключая прерывания.
Первый выбор возможен при условии, что вы можете разумно кодировать ISR.Вы, вероятно, хотите иметь тайм-ауты при работе с конструированием пакетов;Вы должны быть в состоянии справиться с этим правильно в вашем ISR.Это зависит от скорости линии, скорости вашего MCU и того, что еще вам нужно сделать.
Обновление:
Делать это в ISR, безусловно, разумно.Тем не менее, использование круговой очереди довольно просто со стандартной реализацией в вашем арсенале трюков.Вот реализация циклической очереди;читатели и писатели могут работать независимо друг от друга.
#ifndef ARRAY_ELEMENTS
#define ARRAY_ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
#endif
#define QUEUE_DEFINE(name, queue_depth, type) \
struct queue_type__##name { \
volatile size_t m_in; \
volatile size_t m_out; \
type m_queue[queue_depth]; \
}
#define QUEUE_DECLARE(name) struct queue_type__##name name
#define QUEUE_SIZE(name) ARRAY_ELEMENTS((name).m_queue)
#define QUEUE_CALC_NEXT(name, i) \
(((name).i == (QUEUE_SIZE(name) - 1)) ? 0 : ((name).i + 1))
#define QUEUE_INIT(name) (name).m_in = (name).m_out = 0
#define QUEUE_EMPTY(name) ((name).m_in == (name).m_out)
#define QUEUE_FULL(name) (QUEUE_CALC_NEXT(name, m_in) == (name).m_out)
#define QUEUE_NEXT_OUT(name) ((name).m_queue + (name).m_out)
#define QUEUE_NEXT_IN(name) ((name).m_queue + (name).m_in)
#define QUEUE_PUSH(name) ((name).m_in = QUEUE_CALC_NEXT((name), m_in))
#define QUEUE_POP(name) ((name).m_out = QUEUE_CALC_NEXT((name), m_out))
Используйте это так:
QUEUE_DEFINE(bytes_received, 64, unsigned char);
QUEUE_DECLARE(bytes_received);
void isr(void)
{
/* Move the received byte into 'c' */
/* This code enqueues the byte, or drops it if the queue is full */
if (!QUEUE_FULL(bytes_received)) {
*QUEUE_NEXT_IN(bytes_received) = c;
QUEUE_PUSH(bytes_received);
}
}
void main(void)
{
QUEUE_INIT(bytes_received);
for (;;) {
other_processing();
if (!QUEUE_EMPTY(bytes_received)) {
unsigned char c = *QUEUE_NEXT_OUT(bytes_received);
QUEUE_POP(bytes_received);
/* Use c as you see fit ... */
}
}
}