UART 接受数据对FIFO处理技巧

  1. 理由8bit数的溢出效果和FIFO长度2^n
    #define ILEN 8 // size of serial receiving buffer
    unsigned char istart; // receiving buffer start index
    unsigned char iend; // receiving buffer end index
    char idata inbuf[ILEN]; // storage for receiving buffer
  2. 写入处理
    //----- Received data interrupt. -----
    if (RI) {
    c = SBUF; // read character
    RI = 0; // clear interrupt request flag
    if (istart + ILEN != iend) {
    inbuf[iend++ & (ILEN-1)] = c; // put character into buffer
    }
    }
    istart 和 iend 之间的差就是接收到的数据长度,所以可以使用 if (istart + ILEN != iend)来判定FIFO是不是填满。
  3. 【iend++ & (ILEN-1)】可以巧妙的使用 取低n位来处理FIFO的正确位置。
  4. 取数据时,判断iend和istart是不是相等就可以决定FIFO是不是为空
    while (iend == istart) {
    ; // wait until there are characters
    }
    ES = 0; // disable serial interrupts during buffer update
    c = inbuf[istart++ & (ILEN-1)];
    ES = 1;

附 keil help中UART的串口FIFO处理程序:

#include
#include

#define XTAL 11059200 // CPU Oscillator Frequency
#define baudrate 9600 // 9600 bps communication baudrate

#define OLEN 8 // size of serial transmission buffer
unsigned char ostart; // transmission buffer start index
unsigned char oend; // transmission buffer end index
char idata outbuf[OLEN]; // storage for transmission buffer

#define ILEN 8 // size of serial receiving buffer
unsigned char istart; // receiving buffer start index
unsigned char iend; // receiving buffer end index
char idata inbuf[ILEN]; // storage for receiving buffer

bit sendfull; // flag: marks transmit buffer full
bit sendactive; // flag: marks transmitter active

/*--------------------------------------------------------------------------------

  • Serial Interrupt Service Routine
    ------------------------------------------------------------------------------/
    static void com_isr (void) interrupt 4 using 1 {
    char c;

//----- Received data interrupt. -----
if (RI) {
c = SBUF; // read character
RI = 0; // clear interrupt request flag
if (istart + ILEN != iend) {
inbuf[iend++ & (ILEN-1)] = c; // put character into buffer
}
}

//----- Transmitted data interrupt. -----
if (TI != 0) {
TI = 0; // clear interrupt request flag
if (ostart != oend) { // if characters in buffer and
SBUF = outbuf[ostart++ & (OLEN-1)]; // transmit character
sendfull = 0; // clear ‘sendfull’ flag
}
else { // if all characters transmitted
sendactive = 0; // clear ‘sendactive’
}
}
}

/*--------------------------------------------------------------------------------

  • Function to initialize the serial port and the UART baudrate.
    ------------------------------------------------------------------------------/
    void com_initialize (void) {
    istart = 0; // empty transmit buffers
    iend = 0;
    ostart = 0; // empty transmit buffers
    oend = 0;
    sendactive = 0; // transmitter is not active
    sendfull = 0; // clear ‘sendfull’ flag

                                            // Configure timer 1 as a baud rate generator
    

PCON |= 0x80; // 0x80=SMOD: set serial baudrate doubler
TMOD |= 0x20; // put timer 1 into MODE 2

TH1 = (unsigned char) (256 - (XTAL / (16L * 12L * baudrate)));

TR1 = 1; // start timer 1

SCON = 0x50; // serial port MODE 1, enable serial receiver
ES = 1; // enable serial interrupts
}

/*--------------------------------------------------------------------------------

  • putbuf: write a character to SBUF or transmission buffer
    ------------------------------------------------------------------------------/
    void putbuf (char c) {
    if (!sendfull) { // transmit only if buffer not full
    if (!sendactive) { // if transmitter not active:
    sendactive = 1; // transfer first character direct
    SBUF = c; // to SBUF to start transmission
    }
    else {
    ES = 0; // disable serial interrupts during buffer update
    outbuf[oend++ & (OLEN-1)] = c; // put char to transmission buffer
    if (((oend ^ ostart) & (OLEN-1)) == 0) {
    sendfull = 1;
    } // set flag if buffer is full
    ES = 1; // enable serial interrupts again
    }
    }
    }

/*--------------------------------------------------------------------------------

  • Replacement routine for the standard library putchar routine.
  • The printf function uses putchar to output a character.
    ------------------------------------------------------------------------------/
    char putchar (char c) {
    if (c == ‘\n’) { // expand new line character:
    while (sendfull); // wait until there is space in buffer
    putbuf (0x0D); // send CR before LF for
    }
    while (sendfull); // wait until there is space in buffer
    putbuf ©; // place character into buffer
    return ©;
    }

/*--------------------------------------------------------------------------------

  • Replacement routine for the standard library _getkey routine.
  • The getchar and gets functions uses _getkey to read a character.
    ------------------------------------------------------------------------------/
    char _getkey (void) {
    char c;
    while (iend == istart) {
    ; // wait until there are characters
    }
    ES = 0; // disable serial interrupts during buffer update
    c = inbuf[istart++ & (ILEN-1)];
    ES = 1; // enable serial interrupts again
    return ©;
    }

/*--------------------------------------------------------------------------------

  • Main C function that start the interrupt-driven serial I/O.
    ------------------------------------------------------------------------------/
    void main (void) {
    EA = 1; // enable global interrupts
    com_initialize (); // initialize interrupt driven serial I/O
    while (1) {
    char c;
    c = getchar ();
    printf ("\nYou typed the character %c.\n", c);
    }
    }

你可能感兴趣的:(UART 接受数据对FIFO处理技巧)