📄 io.c
字号:
/*C**************************************************************************
* NAME: io.c
*----------------------------------------------------------------------------
* PURPOSE:
* Functions dedicated to the HEX file reception from the host via the Uart.
* These functions provide uart initialization, interrupt handling and
* Rx circular buffer management.
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
#include "compiler.h"
#include "config.h"
#include "isp.h"
/*_____ M A C R O S ________________________________________________________*/
/* XON / XOFF Contro characters */
#define XON 17
#define XOFF 19
/* Must be 2^y for modulo computation */
#define RX_BUF_SIZE 16
/* XOFF when only 50% buffer size left */
/* XON when 25% rx buffer full */
#define XOFF_THRESH (RX_BUF_SIZE - (RX_BUF_SIZE / 2) )
#define XON_THRESH (RX_BUF_SIZE / 4)
/* Wait for end of Tx over the Uart */
#define WAIT_EO_TX {while (TI==0); TI=0;}
/*_____ D E F I N I T I O N ________________________________________________*/
static Uchar rx_buffer[RX_BUF_SIZE]; /* Rx circular buffer */
static Uchar rx_index_wr; /* Rx circular buffer indexes */
static Uchar rx_index_rd;
static Bool tx_off; /* XOFF state indicator */
Uchar nb_rx_data; /* Number of data in the Rx buffer */
/*_____ D E C L A R A T I O N ______________________________________________*/
void rx_buffer_wr(Uchar rx_data);
/*F**************************************************************************
* NAME: uart
*----------------------------------------------------------------------------
* PURPOSE:
* Uart interrupt handler: processes Rx uart events only.
*****************************************************************************/
Interrupt(void uart(void),4)
{
if (RI == 1) /* Processes Rx event only, not Tx */
{
rx_buffer_wr(SBUF); /* Writes the received data into the Rx buffer */
RI = 0;
}
}
/*F**************************************************************************
* NAME: uart_tx
*----------------------------------------------------------------------------
* PURPOSE:
* Send a character over the serial link. Exit when the character
* transmission is over.
*****************************************************************************/
void uart_tx(Uchar tx_data)
{
SBUF = tx_data;
WAIT_EO_TX;
}
/*F**************************************************************************
* NAME: uart_init
*----------------------------------------------------------------------------
* PURPOSE:
* Set the C51 Uart in 8-bit data, 9600 bauds, no parity operating mode.
*****************************************************************************/
void uart_init(void)
{
SCON = 0x50;
TMOD = TMOD | 0x20 ; /* Timer1 in mode 2 & not gated */
TH1 = 0xFD; /* 9600 bauds at 11.059200 MHZ */
TL1 = 0xFD;
PCON = PCON & 0X80;
TCON |= 0x40;
TI=1;
}
/*F**************************************************************************
* NAME: uart_rx_enable
*----------------------------------------------------------------------------
* PURPOSE:
* Initializes Uart for data reception: circular buffer reset, XON/XOFF
* protocol initialization and interrupt enabled.
*****************************************************************************/
void uart_rx_enable(void)
{
rx_index_wr = rx_index_rd = nb_rx_data = 0;
WAIT_EO_TX; /* Wait any previous transmission (printf) */
uart_tx(XON);
ES = 1;
}
/*F**************************************************************************
* NAME: uart_rx_disable
*----------------------------------------------------------------------------
* PURPOSE:
* Disable Rx reception upon interrupts.
*****************************************************************************/
void uart_rx_disable(void)
{
ES = 0;
TI = 1; /* Enable Tx for printf (polling) */
}
/*F**************************************************************************
* NAME: rx_buffer_empty
*----------------------------------------------------------------------------
* PARAMS:
* return: TRUE when Rx buffer is empty.
*----------------------------------------------------------------------------
* PURPOSE:
* Check if new Rx data have been stored in the Rx buffer.
*****************************************************************************/
Bool rx_buffer_empty(void)
{
if (nb_rx_data == 0)
return TRUE;
else
return FALSE;
}
/*F**************************************************************************
* NAME: rx_buffer_wr
*----------------------------------------------------------------------------
* PARAMS:
* rx_data: Rx data to store in the buffer.
*----------------------------------------------------------------------------
* PURPOSE:
* Stores the newly received data in the buffer and keep indexes updated.
*****************************************************************************/
void rx_buffer_wr(Uchar rx_data)
{
nb_rx_data++;
rx_buffer[rx_index_wr] = rx_data;
/* Circular buffer index computation */
rx_index_wr = (rx_index_wr + 1) % RX_BUF_SIZE;
/* Stops host transmission when more than XOFF_THRES characters are stored
* in the Rx buffer */
if ((tx_off==FALSE) && (nb_rx_data > XOFF_THRESH))
{
uart_tx(XOFF);
tx_off = TRUE;
}
}
/*F**************************************************************************
* NAME: rx_buffer_rd
*----------------------------------------------------------------------------
* PARAMS:
* return: the next data available from the Rx buffer.
*----------------------------------------------------------------------------
* PURPOSE:
* Retrieve the next data from the RX buffer.
*****************************************************************************
* NOTE:
* All interrupts are disabled when updating rx_data because a Rx interrupt
* may occur and disturb the computation (rx_data also updated in the Uart
* interrupt handler.
*****************************************************************************/
Uchar rx_buffer_rd(void)
{
static Uchar data_cnt=0; /* For progression dots */
Uchar rx_data;
EA=0; /* Avoid conflicts with rx_buffer_wr() */
nb_rx_data--;
EA=1;
rx_data = rx_buffer[rx_index_rd];
/* Circular buffer index computation */
rx_index_rd = (rx_index_rd + 1) % RX_BUF_SIZE;
/* Progression dots every 256 data */
data_cnt++;
if (data_cnt == 0)
uart_tx('.');
/* Resumes host transmission when less than XON_THRES characters are stored
* in the Rx buffer */
EA = 0;
if ((tx_off == TRUE) && (nb_rx_data < XON_THRESH))
{
uart_tx(XON);
tx_off = FALSE;
}
EA = 1;
return(rx_data);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -