STM32使用printf发送数据配置方法--串口UART,JTAGSWO,JLINKRTT

  • 格式:pdf
  • 大小:2.00 MB
  • 文档页数:6

STM32使⽤printf发送数据配置⽅法--串⼝UART,JTAGSWO,JLINKRTT

STM32串⼝通信中使⽤printf发送数据配置⽅法(开发环境 Keil RVMDK)

在STM32串⼝通信程序中使⽤printf发送数据,⾮常的⽅便。可在刚开始使⽤的时候总是遇到问题,常见的是硬件访真时⽆法进⼊main主函数,其实只要简单的配置⼀下就可以了。

下⾯就说⼀下使⽤printf需要做哪些配置。 有两种配置⽅法: ⼀、对⼯程属性进⾏配置,详细步骤如下

1、⾸先要在你的main ⽂件中 包含“stdio.h” (标准输⼊输出头⽂件)。

2、在main⽂件中重定义函数 如下:

// 发送数据

int

fputc(

int ch, FILE *f) {

USART_SendData(USART1, (unsigned

char

) ch);

// USART1 可以换成 USART2 等

while (!(USART1->SR & USART_FLAG_TXE));

return (ch); }

// 接收数据

int

GetKey (

void) {

while (!(USART1->SR & USART_FLAG_RXNE));

return

((

int

)(USART1->DR &

0x1FF)); }

这样在使⽤printf时就会调⽤⾃定义的fputc函数,来发送字符。

3、在⼯程属性的 “Target" -> "Code Generation" 选项中勾选 "Use MicroLIB"

MicroLIB 是缺省C的备份库,关于它可以到⽹上查找详细资料。

⼆、第⼆种⽅法是在⼯程中添加“Regtarge.c”⽂件

1、在main⽂件中包含 “stdio.h” ⽂件

2、在⼯程中创建⼀个⽂件保存为 Regtarge.c , 然后将其添加⼯程中在⽂件中输⼊如下内容(直接复制即可)#include #include

#pragma import(__use_no_semihosting_swi)

extern

int

SendChar(

int

ch);

// 声明外部函数,在main⽂件中定义

extern

int

GetKey(

void);

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()));}

void

_ttywrch(

int ch) { SendChar (ch);}

int

ferror(FILE *f) { // Your implementation of ferror

return EOF;}

void

_sys_exit(

int return_code) {

label:

goto

label; // endless loop}

3、在main⽂件中添加定义以下两个函数

int

SendChar (

int ch) {

while

(!(USART1->SR & USART_FLAG_TXE));

// USART1 可换成你程序中通信的串⼝

USART1->DR = (ch &

0x1FF);

return (ch);}

int

GetKey (

void) {

while (!(USART1->SR & USART_FLAG_RXNE));

return

((

int

)(USART1->DR &

0x1FF));}

⾄此完成配置,可以在main⽂件中随意使⽤ printf 。

STM32程序添加printf函数后⽆法运⾏的解决⽅法(串⼝实验)

标准库函数的默认输出设备是显⽰器,要实现在串⼝或LCD输出,必须重定义标准库函数⾥调⽤的与输出设备相关的函数.

例如:printf输出到串⼝,需要将fputc⾥⾯的输出指向串⼝(重定向),⽅法如下:

只要⾃⼰添加⼀个int fputc(int ch, FILE *f)函数,能够输出字符就可以了

#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */PUTCHAR_PROTOTYPE{ /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

return ch;}

因printf()之类的函数,使⽤了半主机模式。使⽤标准库会导致程序⽆法运⾏,以下是解决⽅法:

⽅法1.使⽤微库,因为使⽤微库的话,不会使⽤半主机模式.

⽅法2.仍然使⽤标准库,在主程序添加下⾯代码:

#pragma import(__use_no_semihosting)

_sys_exit(

int x) { x = x; }

struct __FILE {

int handle; }; FILE __stdout; IAR EWARM

General Options -- Library Configuration -- Library : Full < file descriptor support >#include #ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else

#define

PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */PUTCHAR_PROTOTYPE{

/* Place your implementation of fputc here */

/* e.g. write a character to the USART */ USART_SendData(USART1, (uint8_t) ch);

/* Loop until the end of transmission */

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

return ch;}

General Options -- Library Configuration -- Library : Normal < NO file descriptor support >#include size_t __write(int handle, const unsigned char * buffer, size_t size){ // byte by byte write

}size_t __dwrite(int handle, const unsigned char * buffer, size_t size){

// buffer[ 0x50 ]} Buffered Terminal Output : Enabledxxwritebuffered.c

#define STORE_SIZE 80

static

size_t storeLen =

0;

static

unsigned

char store[STORE_SIZE]; uint8_t store[ 0x50 ];uint32_t storelen;

printf() -->

__dwrite() : buffer[0x50] Buffered Terminal Output : Disabled

printf() -->

__write(), byte by byte ⾃定义输出缓冲区

#define LOG_MAX_STR_LEN 512

void

log_printf(

const

char * fmt, ... ){

char log_buf[ LOG_MAX_STR_LEN ]; va_list args; va_start( args, fmt );

int count = vsnprintf( log_buf, LOG_MAX_STR_LEN, fmt, args ); va_end( args ); // If an output error is encountered, a negative value is returned.

if ( count < 0 ) return; // "123456" [123456][0X] : count = 6, n = 8 // "1234567" [1234567][0] : count = 7, n = 8 // "12345678" [1234567][0] : count = 8, n = 8 // "123456789" [1234567][0] : count = 9, n = 8 if ( count >= LOG_MAX_STR_LEN ) count = LOG_MAX_STR_LEN - 1; // now log_buf is C string with the terminating null character __write(0, log_buf, count );}

log_printf --> __write()

, bufferred

stm32系列单⽚机之printf重定向在程序的调试过程中,除了那些⾼⼤上的调试⼿段外,printf⽆疑是我们最熟悉最顺⼿的调试⽅法。

通过使⽤printf,我们可以很⽅便很直观的获取当前程序的运⾏状态。

printf()函数是格式化输出函数, ⼀般⽤于向标准输出设备按规定格式输出信息。

但是在单⽚机开发中,⼀般情况下并不存在标准输出设备,因此我们需要将printf的输出信息重定向,也就是输出到其他输出设备中去。

在stm32平台上实现重定向的⽅式有两种,重定向⾄UART,或者通过JTAG的SW模式将printf重定向⾄SWO引脚输出。

⾸先介绍第⼀种,重定向⾄UART,这种⽅式我们⽐较熟悉,ST官⽅提供的固件库中也是使⽤的这种⽅法。代码如下:在对UART进⾏初始化后,通过如下代码对printf进⾏重定向int fputc(int ch, FILE *f){ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)