Keil MDK uses the serial port and the C standard library function printf to debug output for cortex-m3

Publisher:等放假的zr0Latest update time:2020-01-03 Source: eefocusKeywords:Keil  MDK  lpc1788 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Summary:

The printf function in the C standard library is used to output to the display. By modifying the printf function and redirecting its output to the serial port, the purpose can be achieved. The printf function calls the fputc function to actually output a single character, so the fputc function can be modified to complete the work of sending a single character to the serial port.


Note:

The methodological content of this article mainly comes from "Solutions for using printf function in Keil MDK environment" and "Problems with using Printf() function in STM32 serial port". In addition to using the C standard library, you can also use the microLib provided by keil mdk, which is introduced in the article "Problems with using Printf() function in STM32 serial port". In addition, the article also mentions that if you use the C standard library function, you should avoid linking the function using the semihost mode. The #pragma import(__use_no_semihosting_swi) and _sys_exit function implementation in the retarge.c file are to ensure that the semihost mode function is not linked.


Implementation steps:

1. Keil MDK has provided us with such an interface file:


File location: C:KeilARMStartup, (C:Keil is the root directory of my Keil installation)


File name: Retarget.c


document content:


/**************************************************************************************/

/* RETARGET.C: 'Retarget' layer for target-dependent low level functions */

/**************************************************************************************/

/* This file is part of the uVision/ARM development tools. */

/* Copyright (c) 2005 Keil Software. All rights reserved. */

/* This software may only be used under the terms of a valid, current, */

/* end user licence from KEIL for a compatible version of KEIL software */

/* development tools. Nothing else gives you the right to use this software. */

/**************************************************************************************/


#include

#include

#include


#pragma import(__use_no_semihosting_swi)



extern int sendchar(int ch); /* in Serial.c */

extern int getkey(void); /* in Serial.c */

extern long timeval; /* in Time.c */



struct __FILE { int handle; /* Add whatever you need here */ };

FILE __stdout;

FILE __stdin;



int fputc(int ch, FILE *f) {

  return (sendchar(ch));

}


int fgetc(FILE *f) {

  return (sendchar(getkey()));

}



int ferror(FILE *f) {

  /* Your implementation of ferror */

  return EOF;

}



void _ttywrch(int ch) {

  sendchar(ch);

}



void _sys_exit(int return_code) {

  while (1); /* endless loop */

}


So our job is to:


(1) Add the Retarget.c file to your project


(2) Provide the Serial.c file, in which sendchar and getkey() are implemented


sendchar is the function for sending a single character through the serial port.


2. Serial.c file implementation (lpc1788 chip)


Here we use the uart 0 port of lpc1788 to implement the rs232 function


 

#include "lpc177x_8x.h"


// SET32BIT macro sets bits l to h of 32-bit variable x to val.

// For example:

// x = 0x03; binary 000000000000000000000000000000011

// SET32BIT(x,1,3,6);

// Then x becomes 0x0D, binary 000000000000000000000000000001101

#define SET32BIT(x,l,h,val) {(x) &= (~((~(0xfffffffful<<(h-l+1)))<

void uart0_init()

{

    //Configure P0.2, P0.3 as UART interface (i.e. use UART0)

    SET32BIT(LPC_IOCON->P0_2,0,2,1); // TXD0

    SET32BIT(LPC_IOCON->P0_3,0,2,1); // RXD0

    // RXD0 port is set to internal pull-up. In 232 communication protocol, when the level is TTL level, in addition to logic 1, the idle state is also represented by a high level, so connecting a pull-up does not affect communication.

    // At the same time, it will clamp the level when idle to avoid introducing interference signals. Of course, this is just my own understanding...

    SET32BIT(LPC_IOCON->P0_3,3,4,2); 


    // Supply power to the UART0 module (UART0 is powered by default when the microcontroller is powered on, but UART2 and 3 are not powered and need to be manually set as shown here)

    SET32BIT(LPC_SC->PCONP,0,2,1);


    // Configure the NVIC interrupt enable register to enable the interrupt capability of the UART0 module (this is the first level of configuration management of the kernel for interrupts)

    NVIC->ISER[0] |= 0x01<<5;


    //Configure UART0 FCR FIFO control register

    // Enable FIFO. If not enabled, then... I think it must be enabled. If not enabled, the serial port will have no cache queue, which is disabled.

    LPC_UART0->FCR |= 0x01<<0;

    // Clear the cache. Each time you clear the cache, you only need to change the following positions:

    LPC_UART0->FCR |= 0x01<<1; // Clear receive buffer

    LPC_UART0->FCR |= 0x01<<2; // Clear the send buffer

    // Set the receive interrupt trigger event

    SET32BIT(LPC_UART0->FCR,6,7,1); // Set the trigger point 1 event (the default is to trigger the receive interrupt when there are no less than 4 bytes in the receive buffer)


    //Configure UART0 LCR line control register

    SET32BIT(LPC_UART0->LCR,0,1,3); // 8bit data bit

    SET32BIT(LPC_UART0->LCR,2,2,0); // 1bit stop bit

    SET32BIT(LPC_UART0->LCR,3,3,0); // No verification


    // Configure UART0 interrupt enable register IER to enable UART0 interrupt response (this is the second level of interrupt management

    // On LPC1788, generally each module or IO interrupt requires two levels of control, including enabling and disabling

    // IER can only be read and written when the LSB and MSB of the frequency division divisor register are locked, that is, access is prohibited. The default value after power-on is locked (the corresponding DLAB bit of LCR is 0)

    // Locking is achieved by setting the DLAB bit in the LCR control register. The default value at power-on is 0, indicating that access to the LSB and MSB is prohibited.

    SET32BIT(LPC_UART0->LCR,7,7,0); // DLAB is assigned 0, access to LSB and MSB is prohibited

    LPC_UART0->IER |= 0x1<<0; // Enable UART0 receive event interrupt, trigger interrupt when the event set by FCR occurs


    // After power-on, lpc1788 uses the internal 12MHz crystal oscillator by default. The PCLK clock frequency set by the SystemInit function is 60MHz

    // To get the configuration value of the UART0 frequency division divisor register according to the desired baud rate and PCLK clock frequency, you need to open access to the LSB and MSB first

    LPC_UART0->LCR |= 0x1<<7; // DLAB is assigned 1, allowing access to LSB and MSB

    // For a baud rate of 9600 and a PCLK of 60Mhz (60000000), calculate the following register values ​​according to the algorithm provided in the lpc1788 manual

    // The baud rate determined by the values ​​of these registers is 9615, which has a 0.15% error from 9600.

    SET32BIT(LPC_UART0->FDR,0,3,1); // Assign 1 to the fractional division register DIVADDVAL

    SET32BIT(LPC_UART0->FDR,4,7,2); // Assign 2 to the fractional frequency register MULVAL

    SET32BIT(LPC_UART0->DLL,0,7,4); // LSB register is assigned 4

    SET32BIT(LPC_UART0->DLM,0,7,1); // assign 1 to the MSB register

    SET32BIT(LPC_UART0->LCR,7,7,0); // After LSB and MSB configuration, access to LSB and MSB must be prohibited, otherwise some functions of UART cannot be used

}


int sendchar(int ch)

{

    LPC_UART0->THR = (uint8_t)ch;

    while((LPC_UART0->LSR&0x40)==0){};

    return ch;

}


int getkey(void)

{

    while((LPC_UART0->LSR&0x1)==0){};

    return LPC_UART0->RBR;

}


3. Add Serial.c to the project and you can use printf



#include "lpc177x_8x.h"

#include


void uart0_init(void);


int main()

{

    uart0_init(void);

    printf("hello world");

    return 0;

}


Keywords:Keil  MDK  lpc1788 Reference address:Keil MDK uses the serial port and the C standard library function printf to debug output for cortex-m3

Previous article:lpc177x_8x, 1pc32xx series chip external SDRAM configuration
Next article:Install and configure arm-linux-gcc

Recommended ReadingLatest update time:2024-11-15 15:28

KEIL output window (Build Output) information meaning
(1) The compilation result of the STARTUP.A51 file has been loaded when creating a new project (uVision V4.02) After successful compilation, the information from line 1 to line 6 in the output window means: ① Compile target "Target 1"; ② Assemble the startup file STARTUP.A51; ③ Link: Merge
[Microcontroller]
KEIL output window (Build Output) information meaning
Detailed explanation of how to create a new project and a new file in Keil4
To learn about microcontrollers, you need to use code compilation software such as Keil. Beginners need to start from the first step of creating a new project. Only by doing the first step well can they go further and further. Tools/Raw Materials Computer, Keil software Methods/Steps Open the Keil software,
[Microcontroller]
Detailed explanation of how to create a new project and a new file in Keil4
Keil C51 Tutorial---Advanced Programming (IV)
This chapter discusses the following:         ●Absolute address access ●Interface between C and assembly         ●Common files in C51 software package         ●Segment name conversion and program optimization Section 1 Absolute Address Access     C51 provides three methods to access absolute addresses: 1. Absolute m
[Microcontroller]
Keil Cx51 Compiler Compilation Mode
Keil Cx51 compiler provides three compilation mode control commands: SMALL, COMPACT, LARGE, and their effects on variable memory space are as follows. SMALL: All variables are defined in the on-chip RAM of the 8051 microcontroller, and the access speed to such variables is the fastest. In addition, the stack must also
[Microcontroller]
How to define XDATA, CODE and other types of structures in keil c51
Define the CODE type: typedef struct MenuItem      {              int i;            unsigned char j; }code _MenuItem; //Data is stored in FLASH Define XDATA type: typedef struct MenuItem      {              int i;            unsigned char j; }xdata _MenuItem; //Data is stored in external RAM Exam
[Microcontroller]
Keil C51 detailed settings
1. Change the target name After opening Keil, the target in the Project Workspace on the left can be modified. The method is: right-click Target - Manage Compnents - double-click the item to be modified. If you want to add, use the corresponding toolbar in the dialog box. 2. Option for target setting TARGET item 1
[Microcontroller]
Comparison between Keil C51 and Standard C
One of the keys to learning C51 is to deeply understand and apply C51's extensions to standard ANSI C. This is because most of the extensions are directly targeted at the 8051 series CPU hardware. There are roughly 8 categories: 8051 memory types and memory areas Storage Mode Memory Type Declaration Variable t
[Microcontroller]
Keil c51 infrared remote control decoding program
This keil c51 program is suitable for uPC1621/uPC1622 and compatible infrared remote control chips, occupies external interrupt 0 and timer 1, decodes in interrupt mode, saves system resources, and detects whether the remote control signal is valid in query mode. Decoding ideas: The infrared rays are decoded by the
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号