在IAR 的EWARM中提供了printf和scanf,但是需要自己提供hardware low level 层的getchar和putchar,才能实现,本例子在EWARM 5.10和LPC 2368调试通过,其code是根据EWARM 5.10中自带的例子程序更改得来的LPC23xx/KEIL-MCB2300/simple/UART,
最主要的是实现
int MyLowLevelPutchar(int x){ *ptr=(BYTE)x; UARTSend( 0, ptr, 1 ); return 1;}
和
int MyLowLevelGetchar(){ while(ReceivedByte==-1); //not received temp=ReceivedByte; ReceivedByte=-1; return temp; }
网上没找到相关资料,自己想了很长时间对将scanf的getchar实现想出来(putchar 较简单)
下面是几个重要的code
/*****************************************************************************
uarttest.c
/*****************************************************************************
#include "LPC230x.h" /* LPC21xx definitions */#include "type.h"#include "irq.h"#include "target.h"#include "uart.h"
#include <stdio.h>
extern volatile DWORD UART0Count;extern volatile BYTE UART0Buffer[BUFSIZE];extern volatile DWORD UART1Count;extern volatile BYTE UART1Buffer[BUFSIZE];
/******************************************************************************* Main Function main()*****************************************************************************/int main (void){ TargetResetInit();
UARTInit(0, 115200); /* baud rate setting */
printf("Hello,World! This demo is modified by hammergo!/n"); printf("Welcome to arm programming world!/n"); int test=0; printf("Please input test value:"); scanf("%d",&test); if(test>0) { printf("test>0"); }else { printf("test<=0"); }
while (1) { /* Loop forever */
} return 0;}
/******************************************************************************* End Of File*****************************************************************************/
/****************************************************************************** uart.c: UART API file for NXP LPC23xx/24xx Family Microprocessors** Copyright(C) 2006, NXP Semiconductor* All rights reserved.** History* 2006.07.12 ver 1.00 Prelimnary version, first Release*******************************************************************************/#include "LPC230x.h" /* LPC23xx/24xx definitions */#include "type.h"#include "target.h"#include "irq.h"#include "uart.h"
#include <intrinsics.h>
volatile DWORD UART0Status;volatile BYTE UART0TxEmpty = 1;volatile BYTE UART0Buffer[BUFSIZE];volatile DWORD UART0Count = 0;extern volatile int ReceivedByte;
/******************************************************************************* Function name: UART0Handler**** Descriptions: UART0 interrupt handler**** parameters: None** Returned value: None** *****************************************************************************/__irq __nested __arm void UART0Handler (void){ BYTE IIRValue, LSRValue; volatile BYTE Dummy; __enable_interrupt(); /* handles nested interrupt */ IIRValue = U0IIR; IIRValue >>= 1; /* skip pending bit in IIR */ IIRValue &= 0x07; /* check bit 1~3, interrupt identification */ if ( IIRValue == IIR_RLS ) /* Receive Line Status */ { LSRValue = U0LSR; /* Receive Line Status */ if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) ) { /* There are errors or break interrupt */ /* Read LSR will clear the interrupt */ UART0Status = LSRValue; Dummy = U0RBR; /* Dummy read on RX to clear interrupt, then bail out */ VICVectAddr = 0; /* Acknowledge Interrupt */ return; } if ( LSRValue & LSR_RDR ) /* Receive Data Ready */ {// /* If no error on RLS, normal ready, save into the data buffer. */// /* Note: read RBR will clear the interrupt */// UART0Buffer[UART0Count] = U0RBR;// UART0Count++;// if ( UART0Count == BUFSIZE )// {// UART0Count = 0; /* buffer overflow */// } if(ReceivedByte==-1) ReceivedByte=U0RBR; } } else if ( IIRValue == IIR_RDA ) /* Receive Data Available */ {// /* Receive Data Available */// UART0Buffer[UART0Count] = U0RBR;// UART0Count++;// if ( UART0Count == BUFSIZE )// {// UART0Count = 0; /* buffer overflow */// } if(ReceivedByte==-1) ReceivedByte=U0RBR; } else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */ { /* Character Time-out indicator */ UART0Status |= 0x100; /* Bit 9 as the CTI error */ } else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty */ { /* THRE interrupt */ LSRValue = U0LSR; /* Check status in the LSR to see if valid data in U0THR or not */ if ( LSRValue & LSR_THRE ) { UART0TxEmpty = 1; } else { UART0TxEmpty = 0; } } VICVectAddr = 0; /* Acknowledge Interrupt */ return;}
/******************************************************************************* Function name: UART1Handler**** Descriptions: UART1 interrupt handler**** parameters: None** Returned value: None** *****************************************************************************/__irq __nested __arm void UART1Handler (void){ BYTE IIRValue, LSRValue; volatile BYTE Dummy; __enable_interrupt(); /* handles nested interrupt */ IIRValue = U1IIR; IIRValue >>= 1; /* skip pending bit in IIR */ IIRValue &= 0x07; /* check bit 1~3, interrupt identification */ if ( IIRValue == IIR_RLS ) /* Receive Line Status */ { LSRValue = U1LSR; /* Receive Line Status */ if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) ) { /* There are errors or break interrupt */ /* Read LSR will clear the interrupt */ //UART1Status = LSRValue; Dummy = U1RBR; /* Dummy read on RX to clear interrupt, then bail out */ VICVectAddr = 0; /* Acknowledge Interrupt */ return; } if ( LSRValue & LSR_RDR ) /* Receive Data Ready */ { /* If no error on RLS, normal ready, save into the data buffer. */ /* Note: read RBR will clear the interrupt */ // UART1Buffer[UART1Count] = U1RBR; //UART1Count++; // if ( UART1Count == BUFSIZE ) // { // UART1Count = 0; /* buffer overflow */ // } } } else if ( IIRValue == IIR_RDA ) /* Receive Data Available */ { /* Receive Data Available */ //UART1Buffer[UART1Count] = U1RBR; // UART1Count++; // if ( UART1Count == BUFSIZE ) // { // UART1Count = 0; /* buffer overflow */ // } } else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */ { /* Character Time-out indicator */ //UART1Status |= 0x100; /* Bit 9 as the CTI error */ } else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty */ { /* THRE interrupt */ LSRValue = U1LSR; /* Check status in the LSR to see if valid data in U0THR or not */ if ( LSRValue & LSR_THRE ) { //UART1TxEmpty = 1; } else { //UART1TxEmpty = 0; } } VICVectAddr = 0; /* Acknowledge Interrupt */}
/******************************************************************************* Function name: UARTInit**** Descriptions: Initialize UART0 port, setup pin select,** clock, parity, stop bits, FIFO, etc.**** parameters: portNum(0 or 1) and UART baudrate** Returned value: true or false, return false only if the ** interrupt handler can't be installed to the ** VIC table** *****************************************************************************/
DWORD UARTInit( DWORD PortNum, DWORD baudrate ){ DWORD Fdiv; if ( PortNum == 0 ) { PINSEL0 = 0x00000050; /* RxD0 and TxD0 */ U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ Fdiv = ( Fpclk / 16 ) / baudrate ; /*baud rate */ U0DLM = Fdiv / 256; U0DLL = Fdiv % 256; U0LCR = 0x03; /* DLAB = 0 */ U0FCR = 0x07; /* Enable and reset TX and RX FIFO. */ if ( install_irq( UART0_INT, (void *)UART0Handler, HIGHEST_PRIORITY ) == FALSE ) { return (FALSE); } U0IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART0 interrupt */ return (TRUE); } else if ( PortNum == 1 ) {#if EA_BOARD_LPC24XX PINSEL7 |= 0x0000000F; /* P3.16 TXD1, P3.17 RXD1 */#else /* Default is Keil MCB2300 board */ PINSEL0 |= 0x40000000; /* Enable TxD1 P0.15 */ PINSEL1 |= 0x00000001; /* Enable RxD1 P0.16 */#endif U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ Fdiv = ( Fpclk / 16 ) / baudrate ; /*baud rate */ U1DLM = Fdiv / 256; U1DLL = Fdiv % 256; U1LCR = 0x03; /* DLAB = 0 */ U1FCR = 0x07; /* Enable and reset TX and RX FIFO. */ if ( install_irq( UART1_INT, (void *)UART1Handler, HIGHEST_PRIORITY ) == FALSE ) { return (FALSE); } U1IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART0 interrupt */ return (TRUE); } return( FALSE ); }
/******************************************************************************* Function name: UARTSend**** Descriptions: Send a block of data to the UART 0 port based** on the data length**** parameters: portNum, buffer pointer, and data length** Returned value: None** *****************************************************************************/void UARTSend( DWORD portNum, BYTE *BufferPtr, DWORD Length ){ if ( portNum == 0 ) { while ( Length != 0 ) { /* THRE status, contain valid data */ while ( !(UART0TxEmpty & 0x01) ); U0THR = *BufferPtr; UART0TxEmpty = 0; /* not empty in the THR until it shifts out */ BufferPtr++; Length--; } } else { // while ( Length != 0 ) // { // /* THRE status, contain valid data */ // while ( !(UART1TxEmpty & 0x01) ); // U1THR = *BufferPtr; // UART1TxEmpty = 0; /* not empty in the THR until it shifts out */ // BufferPtr++; // Length--; // } } return;}
/******************************************************************************** End Of File******************************************************************************/
/***************************************************************************** * irq.c: Interrupt handler C file for NXP LPC230x Family Microprocessors * * Copyright(C) 2006, NXP Semiconductor * All rights reserved. * * History * 2006.07.13 ver 1.00 Prelimnary version, first Release *******************************************************************************/#include "LPC230x.h" /* LPC23XX Peripheral Registers */#include "type.h"#include "irq.h"
/* Initialize the interrupt controller *//******************************************************************************** Function name: init_VIC**** Descriptions: Initialize VIC interrupt controller.** parameters: None** Returned value: None** ******************************************************************************/void init_VIC(void) { DWORD i = 0; DWORD *vect_addr, *vect_cntl; /* initialize VIC*/ VICIntEnClr = 0xffffffff; VICVectAddr = 0; VICIntSelect = 0;
/* set all the vector and vector control register to 0 */ for ( i = 0; i < VIC_SIZE; i++ ) { vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4); vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4); *vect_addr = 0x0; *vect_cntl = 0xF; } return;}
/******************************************************************************** Function name: install_irq**** Descriptions: Install interrupt handler** parameters: Interrupt number, interrupt handler address, ** interrupt priority** Returned value: true or false, return false if IntNum is out of range** ******************************************************************************/DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority ){ DWORD *vect_addr; DWORD *vect_cntl; VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ if ( IntNumber >= VIC_SIZE ) { return ( FALSE ); } else { /* find first un-assigned VIC address for the handler */ vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4); *vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */ *vect_cntl = Priority; VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ return( TRUE ); }}
/******************************************************************************** End Of File******************************************************************************/
/******************* * * Copyright 1998-2003 IAR Systems. All rights reserved. * * $Revision: 3162 $ * * This is a template implementation of the "__write" function used by * the standard library. Replace it with a system-specific * implementation. * * The "__write" function should output "size" number of bytes from * "buffer" in some application-specific way. It should return the * number of characters written, or _LLIO_ERROR on failure. * * If "buffer" is zero then __write should perform flushing of * internal buffers, if any. In this case "handle" can be -1 to * indicate that all handles should be flushed. * * The template implementation below assumes that the application * provides the function "MyLowLevelPutchar". It should return the * character written, or -1 on failure. * ********************/#include <yfuns.h>#include "type.h"#include "uart.h"
_STD_BEGIN
#pragma module_name = "?__write"BYTE ptr[1];int MyLowLevelPutchar(int x){ *ptr=(BYTE)x; UARTSend( 0, ptr, 1 ); return 1;}
/* * If the __write implementation uses internal buffering, uncomment * the following line to ensure that we are called with "buffer" as 0 * (i.e. flush) when the application terminates. */
size_t __write(int handle, const unsigned char * buffer, size_t size){ /* Remove the #if #endif pair to enable the implementation */
size_t nChars = 0;
if (buffer == 0) { /* * This means that we should flush internal buffers. Since we * don't we just return. (Remember, "handle" == -1 means that all * handles should be flushed.) */ return 0; }
/* This template only writes to "standard out" and "standard err", * for all other file handles it returns failure. */ if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) { return _LLIO_ERROR; }
for (/* Empty */; size != 0; --size) { if (MyLowLevelPutchar(*buffer++) < 0) { return _LLIO_ERROR; }
++nChars; }
return nChars;
/* Always return error code when implementation is disabled. */ return _LLIO_ERROR;
}
_STD_END
/******************* * * Copyright 1998-2003 IAR Systems. All rights reserved. * * $Revision: 3161 $ * * This is a template implementation of the "__read" function used by * the standard library. Replace it with a system-specific * implementation. * * The "__read" function reads a number of bytes, at most "size" into * the memory area pointed to by "buffer". It returns the number of * bytes read, 0 at the end of the file, or _LLIO_ERROR if failure * occurs. * * The template implementation below assumes that the application * provides the function "MyLowLevelGetchar". It should return a * character value, or -1 on failure. * ********************/
#include <yfuns.h>#include "type.h"
#include "LPC230x.h"
_STD_BEGIN
#pragma module_name = "?__read"
volatile int ReceivedByte=-1;int temp=0;int MyLowLevelGetchar(){ while(ReceivedByte==-1); //not received temp=ReceivedByte; ReceivedByte=-1; return temp; }
size_t __read(int handle, unsigned char * buffer, size_t size){ /* Remove the #if #endif pair to enable the implementation */
int nChars = 0;
/* This template only reads from "standard in", for all other file * handles it returns failure. */ if (handle != _LLIO_STDIN) { return _LLIO_ERROR; }
for (/* Empty */; size > 0; --size) { int c = MyLowLevelGetchar(); if (c < 0) break;
*buffer++ = c; ++nChars; }
return nChars;
/* Always return error code when implementation is disabled. */ return _LLIO_ERROR;
}
_STD_END
用串口调试助手测试结果
Hello,World! This demo is modified by hammergo!Welcome to arm programming world!Please input test value:test>0
Hello,World! This demo is modified by hammergo!Welcome to arm programming world!Please input test value:test<=0
