The common folder libraries from keil LPC11Uxx code bundle
uart.c@0:05d110ee258e, 2012-05-27 (annotated)
- Committer:
- alexan_e
- Date:
- Sun May 27 23:59:30 2012 +0000
- Revision:
- 0:05d110ee258e
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
alexan_e | 0:05d110ee258e | 1 | /**************************************************************************** |
alexan_e | 0:05d110ee258e | 2 | * $Id:: uart.c 9188 2012-02-16 20:53:43Z nxp41306 $ |
alexan_e | 0:05d110ee258e | 3 | * Project: NXP LPC11Uxx UART example |
alexan_e | 0:05d110ee258e | 4 | * |
alexan_e | 0:05d110ee258e | 5 | * Description: |
alexan_e | 0:05d110ee258e | 6 | * This file contains UART code example which include UART |
alexan_e | 0:05d110ee258e | 7 | * initialization, UART interrupt handler, and related APIs for |
alexan_e | 0:05d110ee258e | 8 | * UART access. |
alexan_e | 0:05d110ee258e | 9 | * |
alexan_e | 0:05d110ee258e | 10 | **************************************************************************** |
alexan_e | 0:05d110ee258e | 11 | * Software that is described herein is for illustrative purposes only |
alexan_e | 0:05d110ee258e | 12 | * which provides customers with programming information regarding the |
alexan_e | 0:05d110ee258e | 13 | * products. This software is supplied "AS IS" without any warranties. |
alexan_e | 0:05d110ee258e | 14 | * NXP Semiconductors assumes no responsibility or liability for the |
alexan_e | 0:05d110ee258e | 15 | * use of the software, conveys no license or title under any patent, |
alexan_e | 0:05d110ee258e | 16 | * copyright, or mask work right to the product. NXP Semiconductors |
alexan_e | 0:05d110ee258e | 17 | * reserves the right to make changes in the software without |
alexan_e | 0:05d110ee258e | 18 | * notification. NXP Semiconductors also make no representation or |
alexan_e | 0:05d110ee258e | 19 | * warranty that such application will be suitable for the specified |
alexan_e | 0:05d110ee258e | 20 | * use without further testing or modification. |
alexan_e | 0:05d110ee258e | 21 | |
alexan_e | 0:05d110ee258e | 22 | * Permission to use, copy, modify, and distribute this software and its |
alexan_e | 0:05d110ee258e | 23 | * documentation is hereby granted, under NXP Semiconductors |
alexan_e | 0:05d110ee258e | 24 | * relevant copyright in the software, without fee, provided that it |
alexan_e | 0:05d110ee258e | 25 | * is used in conjunction with NXP Semiconductors microcontrollers. This |
alexan_e | 0:05d110ee258e | 26 | * copyright, permission, and disclaimer notice must appear in all copies of |
alexan_e | 0:05d110ee258e | 27 | * this code. |
alexan_e | 0:05d110ee258e | 28 | |
alexan_e | 0:05d110ee258e | 29 | ****************************************************************************/ |
alexan_e | 0:05d110ee258e | 30 | |
alexan_e | 0:05d110ee258e | 31 | #include "LPC11Uxx.h" |
alexan_e | 0:05d110ee258e | 32 | #include "type.h" |
alexan_e | 0:05d110ee258e | 33 | #include "uart.h" |
alexan_e | 0:05d110ee258e | 34 | |
alexan_e | 0:05d110ee258e | 35 | volatile uint32_t UARTStatus; |
alexan_e | 0:05d110ee258e | 36 | volatile uint8_t UARTTxEmpty = 1; |
alexan_e | 0:05d110ee258e | 37 | volatile uint8_t UARTBuffer[BUFSIZE]; |
alexan_e | 0:05d110ee258e | 38 | volatile uint32_t UARTCount = 0; |
alexan_e | 0:05d110ee258e | 39 | |
alexan_e | 0:05d110ee258e | 40 | #if AUTOBAUD_ENABLE |
alexan_e | 0:05d110ee258e | 41 | volatile uint32_t UARTAutoBaud = 0, AutoBaudTimeout = 0; |
alexan_e | 0:05d110ee258e | 42 | #endif |
alexan_e | 0:05d110ee258e | 43 | |
alexan_e | 0:05d110ee258e | 44 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 45 | ** Function name: UART_IRQHandler |
alexan_e | 0:05d110ee258e | 46 | ** |
alexan_e | 0:05d110ee258e | 47 | ** Descriptions: UART interrupt handler |
alexan_e | 0:05d110ee258e | 48 | ** |
alexan_e | 0:05d110ee258e | 49 | ** parameters: None |
alexan_e | 0:05d110ee258e | 50 | ** Returned value: None |
alexan_e | 0:05d110ee258e | 51 | ** |
alexan_e | 0:05d110ee258e | 52 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 53 | void UART_IRQHandler(void) |
alexan_e | 0:05d110ee258e | 54 | { |
alexan_e | 0:05d110ee258e | 55 | uint8_t IIRValue, LSRValue; |
alexan_e | 0:05d110ee258e | 56 | uint8_t Dummy = Dummy; |
alexan_e | 0:05d110ee258e | 57 | |
alexan_e | 0:05d110ee258e | 58 | IIRValue = LPC_USART->IIR; |
alexan_e | 0:05d110ee258e | 59 | |
alexan_e | 0:05d110ee258e | 60 | IIRValue >>= 1; /* skip pending bit in IIR */ |
alexan_e | 0:05d110ee258e | 61 | IIRValue &= 0x07; /* check bit 1~3, interrupt identification */ |
alexan_e | 0:05d110ee258e | 62 | if (IIRValue == IIR_RLS) /* Receive Line Status */ |
alexan_e | 0:05d110ee258e | 63 | { |
alexan_e | 0:05d110ee258e | 64 | LSRValue = LPC_USART->LSR; |
alexan_e | 0:05d110ee258e | 65 | /* Receive Line Status */ |
alexan_e | 0:05d110ee258e | 66 | if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI)) |
alexan_e | 0:05d110ee258e | 67 | { |
alexan_e | 0:05d110ee258e | 68 | /* There are errors or break interrupt */ |
alexan_e | 0:05d110ee258e | 69 | /* Read LSR will clear the interrupt */ |
alexan_e | 0:05d110ee258e | 70 | UARTStatus = LSRValue; |
alexan_e | 0:05d110ee258e | 71 | Dummy = LPC_USART->RBR; /* Dummy read on RX to clear |
alexan_e | 0:05d110ee258e | 72 | interrupt, then bail out */ |
alexan_e | 0:05d110ee258e | 73 | return; |
alexan_e | 0:05d110ee258e | 74 | } |
alexan_e | 0:05d110ee258e | 75 | if (LSRValue & LSR_RDR) /* Receive Data Ready */ |
alexan_e | 0:05d110ee258e | 76 | { |
alexan_e | 0:05d110ee258e | 77 | /* If no error on RLS, normal ready, save into the data buffer. */ |
alexan_e | 0:05d110ee258e | 78 | /* Note: read RBR will clear the interrupt */ |
alexan_e | 0:05d110ee258e | 79 | UARTBuffer[UARTCount++] = LPC_USART->RBR; |
alexan_e | 0:05d110ee258e | 80 | if (UARTCount == BUFSIZE) |
alexan_e | 0:05d110ee258e | 81 | { |
alexan_e | 0:05d110ee258e | 82 | UARTCount = 0; /* buffer overflow */ |
alexan_e | 0:05d110ee258e | 83 | } |
alexan_e | 0:05d110ee258e | 84 | } |
alexan_e | 0:05d110ee258e | 85 | } |
alexan_e | 0:05d110ee258e | 86 | else if (IIRValue == IIR_RDA) /* Receive Data Available */ |
alexan_e | 0:05d110ee258e | 87 | { |
alexan_e | 0:05d110ee258e | 88 | /* Receive Data Available */ |
alexan_e | 0:05d110ee258e | 89 | UARTBuffer[UARTCount++] = LPC_USART->RBR; |
alexan_e | 0:05d110ee258e | 90 | if (UARTCount == BUFSIZE) |
alexan_e | 0:05d110ee258e | 91 | { |
alexan_e | 0:05d110ee258e | 92 | UARTCount = 0; /* buffer overflow */ |
alexan_e | 0:05d110ee258e | 93 | } |
alexan_e | 0:05d110ee258e | 94 | } |
alexan_e | 0:05d110ee258e | 95 | else if (IIRValue == IIR_CTI) /* Character timeout indicator */ |
alexan_e | 0:05d110ee258e | 96 | { |
alexan_e | 0:05d110ee258e | 97 | /* Character Time-out indicator */ |
alexan_e | 0:05d110ee258e | 98 | UARTStatus |= 0x100; /* Bit 9 as the CTI error */ |
alexan_e | 0:05d110ee258e | 99 | } |
alexan_e | 0:05d110ee258e | 100 | else if (IIRValue == IIR_THRE) /* THRE, transmit holding register empty */ |
alexan_e | 0:05d110ee258e | 101 | { |
alexan_e | 0:05d110ee258e | 102 | /* THRE interrupt */ |
alexan_e | 0:05d110ee258e | 103 | LSRValue = LPC_USART->LSR; /* Check status in the LSR to see if |
alexan_e | 0:05d110ee258e | 104 | valid data in U0THR or not */ |
alexan_e | 0:05d110ee258e | 105 | if (LSRValue & LSR_THRE) |
alexan_e | 0:05d110ee258e | 106 | { |
alexan_e | 0:05d110ee258e | 107 | UARTTxEmpty = 1; |
alexan_e | 0:05d110ee258e | 108 | } |
alexan_e | 0:05d110ee258e | 109 | else |
alexan_e | 0:05d110ee258e | 110 | { |
alexan_e | 0:05d110ee258e | 111 | UARTTxEmpty = 0; |
alexan_e | 0:05d110ee258e | 112 | } |
alexan_e | 0:05d110ee258e | 113 | } |
alexan_e | 0:05d110ee258e | 114 | #if AUTOBAUD_ENABLE |
alexan_e | 0:05d110ee258e | 115 | if (LPC_USART->IIR & IIR_ABEO) /* End of Auto baud */ |
alexan_e | 0:05d110ee258e | 116 | { |
alexan_e | 0:05d110ee258e | 117 | LPC_USART->IER &= ~IIR_ABEO; |
alexan_e | 0:05d110ee258e | 118 | /* clear bit ABEOInt in the IIR by set ABEOIntClr in the ACR register */ |
alexan_e | 0:05d110ee258e | 119 | LPC_USART->ACR |= IIR_ABEO; |
alexan_e | 0:05d110ee258e | 120 | UARTAutoBaud = 1; |
alexan_e | 0:05d110ee258e | 121 | } |
alexan_e | 0:05d110ee258e | 122 | else if (LPC_USART->IIR & IIR_ABTO)/* Auto baud time out */ |
alexan_e | 0:05d110ee258e | 123 | { |
alexan_e | 0:05d110ee258e | 124 | LPC_USART->IER &= ~IIR_ABTO; |
alexan_e | 0:05d110ee258e | 125 | AutoBaudTimeout = 1; |
alexan_e | 0:05d110ee258e | 126 | /* clear bit ABTOInt in the IIR by set ABTOIntClr in the ACR register */ |
alexan_e | 0:05d110ee258e | 127 | LPC_USART->ACR |= IIR_ABTO; |
alexan_e | 0:05d110ee258e | 128 | } |
alexan_e | 0:05d110ee258e | 129 | #endif |
alexan_e | 0:05d110ee258e | 130 | return; |
alexan_e | 0:05d110ee258e | 131 | } |
alexan_e | 0:05d110ee258e | 132 | |
alexan_e | 0:05d110ee258e | 133 | #if MODEM_TEST |
alexan_e | 0:05d110ee258e | 134 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 135 | ** Function name: ModemInit |
alexan_e | 0:05d110ee258e | 136 | ** |
alexan_e | 0:05d110ee258e | 137 | ** Descriptions: Initialize UART0 port as modem, setup pin select. |
alexan_e | 0:05d110ee258e | 138 | ** |
alexan_e | 0:05d110ee258e | 139 | ** parameters: None |
alexan_e | 0:05d110ee258e | 140 | ** Returned value: None |
alexan_e | 0:05d110ee258e | 141 | ** |
alexan_e | 0:05d110ee258e | 142 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 143 | void ModemInit( void ) |
alexan_e | 0:05d110ee258e | 144 | { |
alexan_e | 0:05d110ee258e | 145 | |
alexan_e | 0:05d110ee258e | 146 | LPC_IOCON->PIO0_7 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 147 | LPC_IOCON->PIO0_7 |= 0x01; /* UART CTS */ |
alexan_e | 0:05d110ee258e | 148 | LPC_IOCON->PIO0_17 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 149 | LPC_IOCON->PIO0_17 |= 0x01; /* UART RTS */ |
alexan_e | 0:05d110ee258e | 150 | #if 1 |
alexan_e | 0:05d110ee258e | 151 | LPC_IOCON->PIO1_13 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 152 | LPC_IOCON->PIO1_13 |= 0x01; /* UART DTR */ |
alexan_e | 0:05d110ee258e | 153 | LPC_IOCON->PIO1_14 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 154 | LPC_IOCON->PIO1_14 |= 0x01; /* UART DSR */ |
alexan_e | 0:05d110ee258e | 155 | LPC_IOCON->PIO1_15 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 156 | LPC_IOCON->PIO1_15 |= 0x01; /* UART DCD */ |
alexan_e | 0:05d110ee258e | 157 | LPC_IOCON->PIO1_16 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 158 | LPC_IOCON->PIO1_16 |= 0x01; /* UART RI */ |
alexan_e | 0:05d110ee258e | 159 | |
alexan_e | 0:05d110ee258e | 160 | #else |
alexan_e | 0:05d110ee258e | 161 | LPC_IOCON->PIO1_19 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 162 | LPC_IOCON->PIO1_19 |= 0x01; /* UART DTR */ |
alexan_e | 0:05d110ee258e | 163 | LPC_IOCON->PIO1_20 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 164 | LPC_IOCON->PIO1_20 |= 0x01; /* UART DSR */ |
alexan_e | 0:05d110ee258e | 165 | LPC_IOCON->PIO1_21 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 166 | LPC_IOCON->PIO1_21 |= 0x01; /* UART DCD */ |
alexan_e | 0:05d110ee258e | 167 | LPC_IOCON->PIO1_22 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 168 | LPC_IOCON->PIO1_22 |= 0x01; /* UART RI */ |
alexan_e | 0:05d110ee258e | 169 | #endif |
alexan_e | 0:05d110ee258e | 170 | LPC_USART->MCR = 0xC0; /* Enable Auto RTS and Auto CTS. */ |
alexan_e | 0:05d110ee258e | 171 | return; |
alexan_e | 0:05d110ee258e | 172 | } |
alexan_e | 0:05d110ee258e | 173 | #endif |
alexan_e | 0:05d110ee258e | 174 | |
alexan_e | 0:05d110ee258e | 175 | /*********************************************************************** |
alexan_e | 0:05d110ee258e | 176 | * |
alexan_e | 0:05d110ee258e | 177 | * Function: uart_set_divisors |
alexan_e | 0:05d110ee258e | 178 | * |
alexan_e | 0:05d110ee258e | 179 | * Purpose: Determines best dividers to get a target clock rate |
alexan_e | 0:05d110ee258e | 180 | * |
alexan_e | 0:05d110ee258e | 181 | * Processing: |
alexan_e | 0:05d110ee258e | 182 | * See function. |
alexan_e | 0:05d110ee258e | 183 | * |
alexan_e | 0:05d110ee258e | 184 | * Parameters: |
alexan_e | 0:05d110ee258e | 185 | * UARTClk : UART clock |
alexan_e | 0:05d110ee258e | 186 | * baudrate : Desired UART baud rate |
alexan_e | 0:05d110ee258e | 187 | * |
alexan_e | 0:05d110ee258e | 188 | * Outputs: |
alexan_e | 0:05d110ee258e | 189 | * baudrate : Sets the estimated buadrate value in DLL, DLM, and FDR. |
alexan_e | 0:05d110ee258e | 190 | * |
alexan_e | 0:05d110ee258e | 191 | * Returns: Error status. |
alexan_e | 0:05d110ee258e | 192 | * |
alexan_e | 0:05d110ee258e | 193 | * Notes: None |
alexan_e | 0:05d110ee258e | 194 | * |
alexan_e | 0:05d110ee258e | 195 | **********************************************************************/ |
alexan_e | 0:05d110ee258e | 196 | uint32_t uart_set_divisors(uint32_t UARTClk, uint32_t baudrate) |
alexan_e | 0:05d110ee258e | 197 | { |
alexan_e | 0:05d110ee258e | 198 | uint32_t uClk; |
alexan_e | 0:05d110ee258e | 199 | uint32_t calcBaudrate = 0; |
alexan_e | 0:05d110ee258e | 200 | uint32_t temp = 0; |
alexan_e | 0:05d110ee258e | 201 | |
alexan_e | 0:05d110ee258e | 202 | uint32_t mulFracDiv, dividerAddFracDiv; |
alexan_e | 0:05d110ee258e | 203 | uint32_t diviser = 0 ; |
alexan_e | 0:05d110ee258e | 204 | uint32_t mulFracDivOptimal = 1; |
alexan_e | 0:05d110ee258e | 205 | uint32_t dividerAddOptimal = 0; |
alexan_e | 0:05d110ee258e | 206 | uint32_t diviserOptimal = 0; |
alexan_e | 0:05d110ee258e | 207 | |
alexan_e | 0:05d110ee258e | 208 | uint32_t relativeError = 0; |
alexan_e | 0:05d110ee258e | 209 | uint32_t relativeOptimalError = 100000; |
alexan_e | 0:05d110ee258e | 210 | |
alexan_e | 0:05d110ee258e | 211 | /* get UART block clock */ |
alexan_e | 0:05d110ee258e | 212 | uClk = UARTClk >> 4; /* div by 16 */ |
alexan_e | 0:05d110ee258e | 213 | /* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers |
alexan_e | 0:05d110ee258e | 214 | * The formula is : |
alexan_e | 0:05d110ee258e | 215 | * BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL) |
alexan_e | 0:05d110ee258e | 216 | * It involves floating point calculations. That's the reason the formulae are adjusted with |
alexan_e | 0:05d110ee258e | 217 | * Multiply and divide method.*/ |
alexan_e | 0:05d110ee258e | 218 | /* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions: |
alexan_e | 0:05d110ee258e | 219 | * 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */ |
alexan_e | 0:05d110ee258e | 220 | for (mulFracDiv = 1; mulFracDiv <= 15; mulFracDiv++) |
alexan_e | 0:05d110ee258e | 221 | { |
alexan_e | 0:05d110ee258e | 222 | for (dividerAddFracDiv = 0; dividerAddFracDiv <= 15; dividerAddFracDiv++) |
alexan_e | 0:05d110ee258e | 223 | { |
alexan_e | 0:05d110ee258e | 224 | temp = (mulFracDiv * uClk) / ((mulFracDiv + dividerAddFracDiv)); |
alexan_e | 0:05d110ee258e | 225 | diviser = temp / baudrate; |
alexan_e | 0:05d110ee258e | 226 | if ((temp % baudrate) > (baudrate / 2)) |
alexan_e | 0:05d110ee258e | 227 | diviser++; |
alexan_e | 0:05d110ee258e | 228 | |
alexan_e | 0:05d110ee258e | 229 | if (diviser > 2 && diviser < 65536) |
alexan_e | 0:05d110ee258e | 230 | { |
alexan_e | 0:05d110ee258e | 231 | calcBaudrate = temp / diviser; |
alexan_e | 0:05d110ee258e | 232 | |
alexan_e | 0:05d110ee258e | 233 | if (calcBaudrate <= baudrate) |
alexan_e | 0:05d110ee258e | 234 | relativeError = baudrate - calcBaudrate; |
alexan_e | 0:05d110ee258e | 235 | else |
alexan_e | 0:05d110ee258e | 236 | relativeError = calcBaudrate - baudrate; |
alexan_e | 0:05d110ee258e | 237 | |
alexan_e | 0:05d110ee258e | 238 | if ((relativeError < relativeOptimalError)) |
alexan_e | 0:05d110ee258e | 239 | { |
alexan_e | 0:05d110ee258e | 240 | mulFracDivOptimal = mulFracDiv ; |
alexan_e | 0:05d110ee258e | 241 | dividerAddOptimal = dividerAddFracDiv; |
alexan_e | 0:05d110ee258e | 242 | diviserOptimal = diviser; |
alexan_e | 0:05d110ee258e | 243 | relativeOptimalError = relativeError; |
alexan_e | 0:05d110ee258e | 244 | if (relativeError == 0) |
alexan_e | 0:05d110ee258e | 245 | break; |
alexan_e | 0:05d110ee258e | 246 | } |
alexan_e | 0:05d110ee258e | 247 | } /* End of if */ |
alexan_e | 0:05d110ee258e | 248 | } /* end of inner for loop */ |
alexan_e | 0:05d110ee258e | 249 | if (relativeError == 0) |
alexan_e | 0:05d110ee258e | 250 | break; |
alexan_e | 0:05d110ee258e | 251 | } /* end of outer for loop */ |
alexan_e | 0:05d110ee258e | 252 | |
alexan_e | 0:05d110ee258e | 253 | if (relativeOptimalError < (baudrate / 30)) |
alexan_e | 0:05d110ee258e | 254 | { |
alexan_e | 0:05d110ee258e | 255 | /* Set the `Divisor Latch Access Bit` and enable so the DLL/DLM access*/ |
alexan_e | 0:05d110ee258e | 256 | /* Initialise the `Divisor latch LSB` and `Divisor latch MSB` registers */ |
alexan_e | 0:05d110ee258e | 257 | LPC_USART->DLM = (diviserOptimal >> 8) & 0xFF; |
alexan_e | 0:05d110ee258e | 258 | LPC_USART->DLL = diviserOptimal & 0xFF; |
alexan_e | 0:05d110ee258e | 259 | |
alexan_e | 0:05d110ee258e | 260 | /* Initialise the Fractional Divider Register */ |
alexan_e | 0:05d110ee258e | 261 | LPC_USART->FDR = ((mulFracDivOptimal & 0xF) << 4) | (dividerAddOptimal & 0xF); |
alexan_e | 0:05d110ee258e | 262 | return( TRUE ); |
alexan_e | 0:05d110ee258e | 263 | } |
alexan_e | 0:05d110ee258e | 264 | return ( FALSE ); |
alexan_e | 0:05d110ee258e | 265 | } |
alexan_e | 0:05d110ee258e | 266 | |
alexan_e | 0:05d110ee258e | 267 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 268 | ** Function name: UARTInit |
alexan_e | 0:05d110ee258e | 269 | ** |
alexan_e | 0:05d110ee258e | 270 | ** Descriptions: Initialize UART0 port, setup pin select, |
alexan_e | 0:05d110ee258e | 271 | ** clock, parity, stop bits, FIFO, etc. |
alexan_e | 0:05d110ee258e | 272 | ** |
alexan_e | 0:05d110ee258e | 273 | ** parameters: UART baudrate |
alexan_e | 0:05d110ee258e | 274 | ** Returned value: None |
alexan_e | 0:05d110ee258e | 275 | ** |
alexan_e | 0:05d110ee258e | 276 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 277 | void UARTInit(uint32_t baudrate) |
alexan_e | 0:05d110ee258e | 278 | { |
alexan_e | 0:05d110ee258e | 279 | #if !AUTOBAUD_ENABLE |
alexan_e | 0:05d110ee258e | 280 | uint32_t Fdiv; |
alexan_e | 0:05d110ee258e | 281 | #endif |
alexan_e | 0:05d110ee258e | 282 | volatile uint32_t regVal; |
alexan_e | 0:05d110ee258e | 283 | |
alexan_e | 0:05d110ee258e | 284 | UARTTxEmpty = 1; |
alexan_e | 0:05d110ee258e | 285 | UARTCount = 0; |
alexan_e | 0:05d110ee258e | 286 | |
alexan_e | 0:05d110ee258e | 287 | NVIC_DisableIRQ(UART_IRQn); |
alexan_e | 0:05d110ee258e | 288 | /* Select only one location from below. */ |
alexan_e | 0:05d110ee258e | 289 | #if 1 |
alexan_e | 0:05d110ee258e | 290 | LPC_IOCON->PIO0_18 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 291 | LPC_IOCON->PIO0_18 |= 0x01; /* UART RXD */ |
alexan_e | 0:05d110ee258e | 292 | LPC_IOCON->PIO0_19 &= ~0x07; |
alexan_e | 0:05d110ee258e | 293 | LPC_IOCON->PIO0_19 |= 0x01; /* UART TXD */ |
alexan_e | 0:05d110ee258e | 294 | #endif |
alexan_e | 0:05d110ee258e | 295 | #if 0 |
alexan_e | 0:05d110ee258e | 296 | LPC_IOCON->PIO1_14 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 297 | LPC_IOCON->PIO1_14 |= 0x03; /* UART RXD */ |
alexan_e | 0:05d110ee258e | 298 | LPC_IOCON->PIO1_13 &= ~0x07; |
alexan_e | 0:05d110ee258e | 299 | LPC_IOCON->PIO1_13 |= 0x03; /* UART TXD */ |
alexan_e | 0:05d110ee258e | 300 | #endif |
alexan_e | 0:05d110ee258e | 301 | #if 0 |
alexan_e | 0:05d110ee258e | 302 | LPC_IOCON->PIO1_17 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 303 | LPC_IOCON->PIO1_17 |= 0x02; /* UART RXD */ |
alexan_e | 0:05d110ee258e | 304 | LPC_IOCON->PIO1_18 &= ~0x07; |
alexan_e | 0:05d110ee258e | 305 | LPC_IOCON->PIO1_18 |= 0x02; /* UART TXD */ |
alexan_e | 0:05d110ee258e | 306 | #endif |
alexan_e | 0:05d110ee258e | 307 | #if 0 |
alexan_e | 0:05d110ee258e | 308 | LPC_IOCON->PIO1_26 &= ~0x07; /* UART I/O config */ |
alexan_e | 0:05d110ee258e | 309 | LPC_IOCON->PIO1_26 |= 0x02; /* UART RXD */ |
alexan_e | 0:05d110ee258e | 310 | LPC_IOCON->PIO1_27 &= ~0x07; |
alexan_e | 0:05d110ee258e | 311 | LPC_IOCON->PIO1_27 |= 0x02; /* UART TXD */ |
alexan_e | 0:05d110ee258e | 312 | #endif |
alexan_e | 0:05d110ee258e | 313 | |
alexan_e | 0:05d110ee258e | 314 | /* Enable UART clock */ |
alexan_e | 0:05d110ee258e | 315 | LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); |
alexan_e | 0:05d110ee258e | 316 | LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */ |
alexan_e | 0:05d110ee258e | 317 | |
alexan_e | 0:05d110ee258e | 318 | LPC_USART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ |
alexan_e | 0:05d110ee258e | 319 | #if !AUTOBAUD_ENABLE |
alexan_e | 0:05d110ee258e | 320 | #if FDR_CALIBRATION |
alexan_e | 0:05d110ee258e | 321 | if ( uart_set_divisors(SystemCoreClock/LPC_SYSCON->UARTCLKDIV, baudrate) != TRUE ) |
alexan_e | 0:05d110ee258e | 322 | { |
alexan_e | 0:05d110ee258e | 323 | Fdiv = ((SystemCoreClock/LPC_SYSCON->UARTCLKDIV)/16)/baudrate ; /*baud rate */ |
alexan_e | 0:05d110ee258e | 324 | LPC_USART->DLM = Fdiv / 256; |
alexan_e | 0:05d110ee258e | 325 | LPC_USART->DLL = Fdiv % 256; |
alexan_e | 0:05d110ee258e | 326 | LPC_USART->FDR = 0x10; /* Default */ |
alexan_e | 0:05d110ee258e | 327 | } |
alexan_e | 0:05d110ee258e | 328 | #else |
alexan_e | 0:05d110ee258e | 329 | Fdiv = ((SystemCoreClock/LPC_SYSCON->UARTCLKDIV)/16)/baudrate ; /*baud rate */ |
alexan_e | 0:05d110ee258e | 330 | LPC_USART->DLM = Fdiv / 256; |
alexan_e | 0:05d110ee258e | 331 | LPC_USART->DLL = Fdiv % 256; |
alexan_e | 0:05d110ee258e | 332 | LPC_USART->FDR = 0x10; /* Default */ |
alexan_e | 0:05d110ee258e | 333 | #endif |
alexan_e | 0:05d110ee258e | 334 | #endif |
alexan_e | 0:05d110ee258e | 335 | LPC_USART->LCR = 0x03; /* DLAB = 0 */ |
alexan_e | 0:05d110ee258e | 336 | LPC_USART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */ |
alexan_e | 0:05d110ee258e | 337 | |
alexan_e | 0:05d110ee258e | 338 | /* Read to clear the line status. */ |
alexan_e | 0:05d110ee258e | 339 | regVal = LPC_USART->LSR; |
alexan_e | 0:05d110ee258e | 340 | |
alexan_e | 0:05d110ee258e | 341 | /* Ensure a clean start, no data in either TX or RX FIFO. */ |
alexan_e | 0:05d110ee258e | 342 | while (( LPC_USART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) ); |
alexan_e | 0:05d110ee258e | 343 | while ( LPC_USART->LSR & LSR_RDR ) |
alexan_e | 0:05d110ee258e | 344 | { |
alexan_e | 0:05d110ee258e | 345 | regVal = LPC_USART->RBR; /* Dump data from RX FIFO */ |
alexan_e | 0:05d110ee258e | 346 | } |
alexan_e | 0:05d110ee258e | 347 | |
alexan_e | 0:05d110ee258e | 348 | /* Enable the UART Interrupt */ |
alexan_e | 0:05d110ee258e | 349 | NVIC_EnableIRQ(UART_IRQn); |
alexan_e | 0:05d110ee258e | 350 | |
alexan_e | 0:05d110ee258e | 351 | #if TX_INTERRUPT |
alexan_e | 0:05d110ee258e | 352 | LPC_USART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */ |
alexan_e | 0:05d110ee258e | 353 | #else |
alexan_e | 0:05d110ee258e | 354 | LPC_USART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */ |
alexan_e | 0:05d110ee258e | 355 | #endif |
alexan_e | 0:05d110ee258e | 356 | #if AUTOBAUD_ENABLE |
alexan_e | 0:05d110ee258e | 357 | LPC_USART->IER |= IER_ABEO | IER_ABTO; |
alexan_e | 0:05d110ee258e | 358 | #endif |
alexan_e | 0:05d110ee258e | 359 | return; |
alexan_e | 0:05d110ee258e | 360 | } |
alexan_e | 0:05d110ee258e | 361 | |
alexan_e | 0:05d110ee258e | 362 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 363 | ** Function name: UARTSend |
alexan_e | 0:05d110ee258e | 364 | ** |
alexan_e | 0:05d110ee258e | 365 | ** Descriptions: Send a block of data to the UART 0 port based |
alexan_e | 0:05d110ee258e | 366 | ** on the data length |
alexan_e | 0:05d110ee258e | 367 | ** |
alexan_e | 0:05d110ee258e | 368 | ** parameters: buffer pointer, and data length |
alexan_e | 0:05d110ee258e | 369 | ** Returned value: None |
alexan_e | 0:05d110ee258e | 370 | ** |
alexan_e | 0:05d110ee258e | 371 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 372 | void UARTSend(uint8_t *BufferPtr, uint32_t Length) |
alexan_e | 0:05d110ee258e | 373 | { |
alexan_e | 0:05d110ee258e | 374 | |
alexan_e | 0:05d110ee258e | 375 | while ( Length != 0 ) |
alexan_e | 0:05d110ee258e | 376 | { |
alexan_e | 0:05d110ee258e | 377 | /* THRE status, contain valid data */ |
alexan_e | 0:05d110ee258e | 378 | #if !TX_INTERRUPT |
alexan_e | 0:05d110ee258e | 379 | while ( !(LPC_USART->LSR & LSR_THRE) ); |
alexan_e | 0:05d110ee258e | 380 | LPC_USART->THR = *BufferPtr; |
alexan_e | 0:05d110ee258e | 381 | #else |
alexan_e | 0:05d110ee258e | 382 | /* Below flag is set inside the interrupt handler when THRE occurs. */ |
alexan_e | 0:05d110ee258e | 383 | while ( !(UARTTxEmpty & 0x01) ); |
alexan_e | 0:05d110ee258e | 384 | LPC_USART->THR = *BufferPtr; |
alexan_e | 0:05d110ee258e | 385 | UARTTxEmpty = 0; /* not empty in the THR until it shifts out */ |
alexan_e | 0:05d110ee258e | 386 | #endif |
alexan_e | 0:05d110ee258e | 387 | BufferPtr++; |
alexan_e | 0:05d110ee258e | 388 | Length--; |
alexan_e | 0:05d110ee258e | 389 | } |
alexan_e | 0:05d110ee258e | 390 | return; |
alexan_e | 0:05d110ee258e | 391 | } |
alexan_e | 0:05d110ee258e | 392 | |
alexan_e | 0:05d110ee258e | 393 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 394 | ** Function name: print_string |
alexan_e | 0:05d110ee258e | 395 | ** |
alexan_e | 0:05d110ee258e | 396 | ** Descriptions: print out string on the terminal |
alexan_e | 0:05d110ee258e | 397 | ** |
alexan_e | 0:05d110ee258e | 398 | ** parameters: pointer to the string end with NULL char. |
alexan_e | 0:05d110ee258e | 399 | ** Returned value: none. |
alexan_e | 0:05d110ee258e | 400 | ** |
alexan_e | 0:05d110ee258e | 401 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 402 | void print_string( uint8_t *str_ptr ) |
alexan_e | 0:05d110ee258e | 403 | { |
alexan_e | 0:05d110ee258e | 404 | while(*str_ptr != 0x00) |
alexan_e | 0:05d110ee258e | 405 | { |
alexan_e | 0:05d110ee258e | 406 | while((LPC_USART->LSR & 0x60) != 0x60); |
alexan_e | 0:05d110ee258e | 407 | LPC_USART->THR = *str_ptr; |
alexan_e | 0:05d110ee258e | 408 | str_ptr++; |
alexan_e | 0:05d110ee258e | 409 | } |
alexan_e | 0:05d110ee258e | 410 | return; |
alexan_e | 0:05d110ee258e | 411 | } |
alexan_e | 0:05d110ee258e | 412 | |
alexan_e | 0:05d110ee258e | 413 | /***************************************************************************** |
alexan_e | 0:05d110ee258e | 414 | ** Function name: get_key |
alexan_e | 0:05d110ee258e | 415 | ** |
alexan_e | 0:05d110ee258e | 416 | ** Descriptions: Get a character from the terminal |
alexan_e | 0:05d110ee258e | 417 | ** |
alexan_e | 0:05d110ee258e | 418 | ** parameters: None |
alexan_e | 0:05d110ee258e | 419 | ** Returned value: character, zero is none. |
alexan_e | 0:05d110ee258e | 420 | ** |
alexan_e | 0:05d110ee258e | 421 | *****************************************************************************/ |
alexan_e | 0:05d110ee258e | 422 | uint8_t get_key( void ) |
alexan_e | 0:05d110ee258e | 423 | { |
alexan_e | 0:05d110ee258e | 424 | uint8_t dummy; |
alexan_e | 0:05d110ee258e | 425 | |
alexan_e | 0:05d110ee258e | 426 | while ( !(LPC_USART->LSR & 0x01) ); |
alexan_e | 0:05d110ee258e | 427 | dummy = LPC_USART->RBR; |
alexan_e | 0:05d110ee258e | 428 | if ((dummy>=65) && (dummy<=90)) |
alexan_e | 0:05d110ee258e | 429 | { |
alexan_e | 0:05d110ee258e | 430 | /* convert capital to non-capital character, A2a, B2b, C2c. */ |
alexan_e | 0:05d110ee258e | 431 | dummy +=32; |
alexan_e | 0:05d110ee258e | 432 | } |
alexan_e | 0:05d110ee258e | 433 | /* echo */ |
alexan_e | 0:05d110ee258e | 434 | LPC_USART->THR = dummy; |
alexan_e | 0:05d110ee258e | 435 | return(dummy); |
alexan_e | 0:05d110ee258e | 436 | } |
alexan_e | 0:05d110ee258e | 437 | |
alexan_e | 0:05d110ee258e | 438 | /****************************************************************************** |
alexan_e | 0:05d110ee258e | 439 | ** End Of File |
alexan_e | 0:05d110ee258e | 440 | ******************************************************************************/ |