📄 serial.c
字号:
/**********************************************************************
* $Id$ serial.c 2011-11-20
*//**
* @file serial.c
* @brief Char output redirection to serial port. This is ported
* over unchanged from the UART interrupt example.
* @version 1.0
* @date 20. Nov. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/
#include "lpc177x_8x_uart.h"
#include "lpc177x_8x_pinsel.h"
#include "application_config.h"
#include "lpc_arch.h"
/** @ingroup LPC177x_8x
*/
#ifdef UART_REDIRECT
#if UART_REDIRECT==-1
/* Null version of re-direction initialization */
void init_redirect (void)
{
/* Do nothing */
;
}
/* Null version of send character */
int sendchar (int ch)
{
return ch;
}
/* Null version of read character */
int getkey (void)
{
return 0;
}
#else
#if UART_REDIRECT == 0
#define _LPC_UART (LPC_UART_TypeDef *)LPC_UART0
#define _UART_IRQ UART0_IRQn
#define _UART_IRQHander UART0_IRQHandler
#endif
#if UART_REDIRECT == 1
#define _LPC_UART (LPC_UART_TypeDef *)LPC_UART1
#define _UART_IRQ UART1_IRQn
#define _UART_IRQHander UART1_IRQHandler
#endif
#if UART_REDIRECT == 2
#define _LPC_UART UART_2
#define _UART_IRQ UART2_IRQn
#define _UART_IRQHander UART2_IRQHandler
#endif
#ifndef _LPC_UART
#error "Re-directed output to UART, but invalid UART selected. Set UART_REDIRECT define in application_config.h"
#else
/************************** PRIVATE DEFINTIONS *************************/
/* buffer size definition */
#define UART_RING_BUFSIZE 256
/* Buf mask */
#define __BUF_MASK (UART_RING_BUFSIZE-1)
/* Check buf is full or not */
#define __BUF_IS_FULL(head, tail) ((tail&__BUF_MASK)==((head+1)&__BUF_MASK))
/* Check buf will be full in next receiving or not */
#define __BUF_WILL_FULL(head, tail) ((tail&__BUF_MASK)==((head+2)&__BUF_MASK))
/* Check buf is empty */
#define __BUF_IS_EMPTY(head, tail) ((head&__BUF_MASK)==(tail&__BUF_MASK))
/* Reset buf */
#define __BUF_RESET(bufidx) (bufidx=0)
#define __BUF_INCR(bufidx) (bufidx=(bufidx+1)&__BUF_MASK)
/************************** PRIVATE TYPES *************************/
/** @brief UART Ring buffer structure */
typedef struct
{
__IO uint32_t tx_head; /*!< UART Tx ring buffer head index */
__IO uint32_t tx_tail; /*!< UART Tx ring buffer tail index */
__IO uint32_t rx_head; /*!< UART Rx ring buffer head index */
__IO uint32_t rx_tail; /*!< UART Rx ring buffer tail index */
__IO uint8_t tx[UART_RING_BUFSIZE]; /*!< UART Tx data ring buffer */
__IO uint8_t rx[UART_RING_BUFSIZE]; /*!< UART Rx data ring buffer */
} UART_RING_BUFFER_T;
/************************** PRIVATE VARIABLES *************************/
/* UART Ring buffer */
UART_RING_BUFFER_T rb;
/* Current Tx Interrupt enable state */
__IO FlagStatus TxIntStat;
/************************** PRIVATE FUNCTIONS *************************/
/* Interrupt service routines */
void _UART_IRQHander(void);
void UART_IntErr(uint8_t bLSErrType);
void UART_IntTransmit(void);
void UART_IntReceive(void);
uint32_t UARTReceive(UART_ID_Type UARTPort, uint8_t *rxbuf, uint32_t buflen);
uint32_t UARTSend(UART_ID_Type UARTPort, uint8_t *txbuf, uint32_t buflen);
void print_menu(void);
void Input_To_Led(uint8_t input)
{
GPIO_OutputValue(3, (1<<24), DISABLE);
GPIO_OutputValue(3, (1<<25), DISABLE);
GPIO_OutputValue(3, (1<<26), DISABLE);
GPIO_OutputValue(3, (1<<27), DISABLE);
GPIO_OutputValue(3, (1<<28), DISABLE);
GPIO_OutputValue(3, (1<<29), DISABLE);
GPIO_OutputValue(3, (1<<31), DISABLE);
switch(input)
{
case 'q':
GPIO_OutputValue(3, (1<<24), ENABLE);
break;
case 'w':
GPIO_OutputValue(3, (1<<25), ENABLE);
break;
case 'e':
GPIO_OutputValue(3, (1<<26), ENABLE);
break;
case 'r':
GPIO_OutputValue(3, (1<<27), ENABLE);
break;
case 't':
GPIO_OutputValue(3, (1<<28), ENABLE);
break;
case 'y':
GPIO_OutputValue(3, (1<<29), ENABLE);
break;
case 'u':
GPIO_OutputValue(3, (1<<31), ENABLE);
break;
default:
break;
}
}
/*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
/*********************************************************************//**
* @brief UART0 interrupt handler sub-routine
* @param[in] None
* @return None
**********************************************************************/
void _UART_IRQHander(void)
{
uint32_t intsrc, tmp, tmp1;
/* Determine the interrupt source */
intsrc = UART_GetIntId(_LPC_UART);
tmp = intsrc & UART_IIR_INTID_MASK;
// Receive Line Status
if (tmp == UART_IIR_INTID_RLS){
// Check line status
tmp1 = UART_GetLineStatus(_LPC_UART);
// Mask out the Receive Ready and Transmit Holding empty status
tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
| UART_LSR_BI | UART_LSR_RXFE);
// If any error exist
if (tmp1) {
UART_IntErr(tmp1);
}
}
// Receive Data Available or Character time-out
if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)){
UART_IntReceive();
}
// Transmit Holding Empty
if (tmp == UART_IIR_INTID_THRE){
UART_IntTransmit();
}
}
/********************************************************************//**
* @brief UART receive function (ring buffer used)
* @param[in] None
* @return None
*********************************************************************/
void UART_IntReceive(void)
{
uint8_t tmpc;
uint32_t rLen;
while(1){
// Call UART read function in UART driver
rLen = UART_Receive(_LPC_UART, &tmpc, 1, NONE_BLOCKING);
//Test from randy, use different input to trigger LED blink
Input_To_Led(tmpc);
// If data received
if (rLen){
/* Check if buffer is more space
* If no more space, remaining character will be trimmed out
*/
if (!__BUF_IS_FULL(rb.rx_head,rb.rx_tail)){
rb.rx[rb.rx_head] = tmpc;
__BUF_INCR(rb.rx_head);
}
}
// no more data
else {
break;
}
}
}
/********************************************************************//**
* @brief UART transmit function (ring buffer used)
* @param[in] None
* @return None
*********************************************************************/
void UART_IntTransmit(void)
{
// Disable THRE interrupt
UART_IntConfig(_LPC_UART, UART_INTCFG_THRE, DISABLE);
/* Wait for FIFO buffer empty, transfer UART_TX_FIFO_SIZE bytes
* of data or break whenever ring buffers are empty */
/* Wait until THR empty */
while (UART_CheckBusy(_LPC_UART) == SET);
while (!__BUF_IS_EMPTY(rb.tx_head,rb.tx_tail))
{
/* Move a piece of data into the transmit FIFO */
if (UART_Send(_LPC_UART, (uint8_t *)&rb.tx[rb.tx_tail], 1, NONE_BLOCKING)){
/* Update transmit ring FIFO tail pointer */
__BUF_INCR(rb.tx_tail);
} else {
break;
}
}
/* If there is no more data to send, disable the transmit
interrupt - else enable it or keep it enabled */
if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
UART_IntConfig(_LPC_UART, UART_INTCFG_THRE, DISABLE);
// Reset Tx Interrupt state
TxIntStat = RESET;
}
else{
// Set Tx Interrupt state
TxIntStat = SET;
UART_IntConfig(_LPC_UART, UART_INTCFG_THRE, ENABLE);
}
}
/*********************************************************************//**
* @brief UART Line Status Error
* @param[in] bLSErrType UART Line Status Error Type
* @return None
**********************************************************************/
void UART_IntErr(uint8_t bLSErrType)
{
uint8_t test;
// Loop forever
while (1){
// For testing purpose
test = bLSErrType;
}
}
/*-------------------------PRIVATE FUNCTIONS------------------------------*/
/*********************************************************************//**
* @brief UART transmit function for interrupt mode (using ring buffers)
* @param[in] UARTPort Selected UART peripheral used to send data,
* should be UART0
* @param[out] txbuf Pointer to Transmit buffer
* @param[in] buflen Length of Transmit buffer
* @return Number of bytes actually sent to the ring buffer
**********************************************************************/
uint32_t UARTSend(UART_ID_Type UARTPort, uint8_t *txbuf, uint32_t buflen)
{
uint8_t *data = (uint8_t *) txbuf;
uint32_t bytes = 0;
/* Temporarily lock out UART transmit interrupts during this
read so the UART transmit interrupt won't cause problems
with the index values */
UART_IntConfig(UARTPort, UART_INTCFG_THRE, DISABLE);
/* Loop until transmit run buffer is full or until n_bytes
expires */
while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head, rb.tx_tail)))
{
/* Write data from buffer into ring buffer */
rb.tx[rb.tx_head] = *data;
data++;
/* Increment head pointer */
__BUF_INCR(rb.tx_head);
/* Increment data count and decrement buffer size count */
bytes++;
buflen--;
}
/*
* Check if current Tx interrupt enable is reset,
* that means the Tx interrupt must be re-enabled
* due to call UART_IntTransmit() function to trigger
* this interrupt type
*/
if (TxIntStat == RESET) {
UART_IntTransmit();
}
/*
* Otherwise, re-enables Tx Interrupt
*/
else {
UART_IntConfig(UARTPort, UART_INTCFG_THRE, ENABLE);
}
return bytes;
}
/*********************************************************************//**
* @brief UART read function for interrupt mode (using ring buffers)
* @param[in] UARTPort Selected UART peripheral used to send data,
* should be UART0
* @param[out] rxbuf Pointer to Received buffer
* @param[in] buflen Length of Received buffer
* @return Number of bytes actually read from the ring buffer
**********************************************************************/
uint32_t UARTReceive(UART_ID_Type UARTPort, uint8_t *rxbuf, uint32_t buflen)
{
uint8_t *data = (uint8_t *) rxbuf;
uint32_t bytes = 0;
/* Temporarily lock out UART receive interrupts during this
read so the UART receive interrupt won't cause problems
with the index values */
UART_IntConfig(UARTPort, UART_INTCFG_RBR, DISABLE);
/* Loop until receive buffer ring is empty or
until max_bytes expires */
while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head, rb.rx_tail))))
{
/* Read data from ring buffer into user buffer */
*data = rb.rx[rb.rx_tail];
data++;
/* Update tail pointer */
__BUF_INCR(rb.rx_tail);
/* Increment data count and decrement buffer size count */
bytes++;
buflen--;
}
/* Re-enable UART interrupts */
UART_IntConfig(UARTPort, UART_INTCFG_RBR, ENABLE);
return bytes;
}
void init_redirect(void)
{
// UART Configuration structure variable
UART_CFG_Type UARTConfigStruct;
// UART FIFO configuration Struct variable
UART_FIFO_CFG_Type UARTFIFOConfigStruct;
uint32_t idx, len;
__IO FlagStatus exitflag;
uint8_t buffer[10];
#if (UART_REDIRECT == 0)
/*
* Initialize UART0 pin connect
* P0.2: U0_TXD
* P0.3: U0_RXD
*/
PINSEL_ConfigPin(0,2,1);
PINSEL_ConfigPin(0,3,1);
#elif (UART_REDIRECT == 1)
/*
* Initialize UART1 pin connect
* P0.15: U1_TXD
* P0.16: U1_RXD
*/
PINSEL_ConfigPin(0,15,1);
PINSEL_ConfigPin(0,16,1);
#elif (UART_REDIRECT == 2)
/*
* Initialize UART2 pin connect
* P0.10: U2_TXD
* P0.11: U2_RXD
*/
PINSEL_ConfigPin(0,10,1);
PINSEL_ConfigPin(0,11,1);
#endif
/* Initialize UART Configuration parameter structure to default state:
* Baudrate = 115200 bps
* 8 data bit
* 1 Stop bit
* None parity
*/
UART_ConfigStructInit(&UARTConfigStruct);
// Initialize UART0 peripheral with given to corresponding parameter
UART_Init(_LPC_UART, &UARTConfigStruct);
/* Initialize FIFOConfigStruct to default state:
* - FIFO_DMAMode = DISABLE
* - FIFO_Level = UART_FIFO_TRGLEV0
* - FIFO_ResetRxBuf = ENABLE
* - FIFO_ResetTxBuf = ENABLE
* - FIFO_State = ENABLE
*/
UART_FIFOConfigStructInit(&UARTFIFOConfigStruct);
// Initialize FIFO for UART0 peripheral
UART_FIFOConfig(_LPC_UART, &UARTFIFOConfigStruct);
// Enable UART Transmit
UART_TxCmd(_LPC_UART, ENABLE);
/* Enable UART Rx interrupt */
UART_IntConfig(_LPC_UART, UART_INTCFG_RBR, ENABLE);
/* Enable UART line status interrupt */
UART_IntConfig(_LPC_UART, UART_INTCFG_RLS, ENABLE);
/*
* Do not enable transmit interrupt here, since it is handled by
* UART_Send() function, just to reset Tx Interrupt state for the
* first time
*/
TxIntStat = RESET;
// Reset ring buf head and tail idx
__BUF_RESET(rb.rx_head);
__BUF_RESET(rb.rx_tail);
__BUF_RESET(rb.tx_head);
__BUF_RESET(rb.tx_tail);
/* preemption = 1, sub-priority = 1 */
NVIC_SetPriority(_UART_IRQ, ((0x01 << 3) | 0x01));
/* Enable Interrupt for UART0 channel */
NVIC_EnableIRQ(_UART_IRQ);
}
/* Implementation of putchar (also used by printf function to output data) */
int sendchar (int ch) { /* Write character to Serial Port */
char sch[2];
if (ch == (int) '\n') {
sch[0] = '\r';
UARTSend(_LPC_UART, sch, 1);
}
sch[0] = (char) ch;
UARTSend(_LPC_UART, sch, 1);
return 1;
}
int getkey (void) { /* Read character from Serial Port */
char rch[2];
int len = 0;
while (len == 0)
len = UARTReceive(_LPC_UART, rch, 1);
return (int) rch[0];
}
#endif
#endif
#endif /* UART_REDIRECT */
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -