這些不是唯一的兩種選擇,第二種選擇似乎不理想。
我的第一種方法是對一個簡單的循環隊列,並從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 ... */
}
}
}
我想我的第一選擇。在程序中,環形緩衝區看起來像是很多工作中的頭部/尾部簿記... 我在主循環中沒有做太多計算。 MCU的時鐘頻率爲4MHz,線路波特率爲9600bps – itisravi 2010-06-11 12:07:52