stm32实现printf打印log的几种办法

发布者:tanjunhui最新更新时间:2019-01-17 来源: eefocus关键字:stm32  printf  打印log 手机看文章 扫描二维码
随时随地手机看文章

在stm32单片机下,改一些bug的时候,光靠调试还不行,有时候需要打印log来查看某些变量在一段时间内的变化趋势,但是板卡又没有接串口,没办法重定向到串口打印,上网查资料研究了一下,发现以下几种办法可实现单片机像在pc终端一样打印log:


方法1:使用串口重定向,将printf打印的信息输出到串口,再将串口连接pc端串口接收终端,在终端上查看log.主要2个步骤:修改printf函数底层调用到的fputc函数和避免使用semihos TIng(半主机模式)。


a.如果使用mdk作为编译工具,在Target选项框里选Use MicroLib 选项,即为使用微库模式,不会使用半主机模式;


b.工程中添加串口配置代码,方便后续使用串口发送数据


void UART1_Configuration(void)

{

USART_InitTypeDef USART_InitStructure;

USART_ClockInitTypeDef  USART_ClockInitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 |RCC_APB2Periph_USART1, ENABLE  );


USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;   // 时钟低电平活动

USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;     // 时钟低电平

USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;  // 时钟第二个边沿进行数据捕获

USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;  // 最后一位数据的时钟脉冲不从SCLK输出

/* Configure the USART1 synchronous paramters */

USART_ClockInit(USART1, &USART_ClockInitStructure);  // 时钟参数初始化设置

 

USART_InitStructure.USART_BaudRate = 115200;    // 波特率为:115200

USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据

USART_InitStructure.USART_StopBits = USART_StopBits_1;  // 在帧结尾传输1个停止位

USART_InitStructure.USART_Parity = USART_Parity_No ;   // 奇偶失能

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制失能


USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 发送使能+接收使能

/* Configure USART1 basic and asynchronous paramters */

USART_Init(USART1, &USART_InitStructure);


  /* Enable USART1 */

USART_ClearFlag(USART1, USART_IT_RXNE); //清中断,以免一启用中断后立即产生中断

USART_ITConfig(USART1,USART_IT_RXNE, ENABLE); //使能USART1中断源

USART_Cmd(USART1, ENABLE); //USART1总开关:开启

}

c.添加串口中断程序 


#define TxBufferSize   (countof(TxBuffer) - 1)

#define RxBufferSize   0x20

 

/* Private macro -------------------------------------------------------------*/

#define countof(a)   (sizeof(a) / sizeof(*(a)))

 

/* Private variables ---------------------------------------------------------*/

u8 TxBuffer[] = "\n\rUSART Hyperterminal Interrupts Example: USART-Hyperterminal\

communication using Interrupt\n\r";

u8 RxBuffer[RxBufferSize];

u8 NbrOfDataToTransfer = TxBufferSize;

u8 NbrOfDataToRead = RxBufferSize;

u8 TxCounter = 0; 

u16 RxCounter = 0;

 

 

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

* Function Name  : USART1_IRQHandler

* Description    : This function handles USART1 global interrupt request.

* Input          : None

* Output         : None

* Return         : None

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

void USART1_IRQHandler(void)

{

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

  {

    /* Read one byte from the receive data register */

    RxBuffer[RxCounter++] = (USART_ReceiveData(USART1) & 0x7F);

   if(RxCounter == NbrOfDataToRead)

    {

      /* Disable the USART Receive interrupt */

          RxCounter = 0;

      //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

    }

  }

 

  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)

  {   

    /* Write one byte to the transmit data register */

    USART_SendData(USART1, TxBuffer[TxCounter++]);                    

 

   if(TxCounter == NbrOfDataToTransfer)

    {

      /* Disable the USART1 Transmit interrupt */

      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

    }    

  }           

}

d.修改fputc和fgetc函数


int fputc(int ch, FILE *f)

{

/* 发送一个字节数据到USART1 */

USART_SendData(USART1, (u8) ch);


/* 等待发送完毕 */

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


return (ch);

}

 

// 重定向c库函数scanf到USART1

int fgetc(FILE *f)

{

/* 等待串口1输入数据 */

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

 

return (int)USART_ReceiveData(USART1);

}

d.现在就可以直接在代码中使用printf就可以在串口连接的pc端看到打印信息了


方法2:利用mdk自带的ITM功能查看log打印,这种办法优点是不占用串口,速度快,但还是依赖mdk来显示,在keil官网有相关的详细介绍http://www.keil.com/support/man/docs/uv4/uv4_db_dbg_printf_viewer.htm,有兴趣的朋友可以试试


方法3:使用Jlink自带的RTT工具打印。相比前2种,速度更快,也不依赖编译工具,只要有JLink即可。步骤如下:


a.需要使用新版的JLINK软件,最低要V4.90版本以上,旧版的jlink没有该功能,这是官方下载链接https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack、


b.从官网下载的JLINK程序安装后,再找到包里以下4个个文件添加到工程中


å¾ 2  éè¦æ·»å å°å·¥ç¨çæ件


c.这就可以直接使用SEGGER_RTT_printf函数打印,函数使用格式如下:


SEGGER_RTT_printf((0,"hello test %d times\r\n",++u32Counter);


d.先启动调试程序,然后可以在安装的Jlink目录找到J-link RTT Client.exe(还有其他查看log工具),打开此程序,打印的信息即可显示在该窗口


å¾3


e.查看RTT输出的工具有三个:


RTTViewer:不支持中文。至少要进入一次Debugger才能正常显示输出。建议进入Debugger之后再打开,否则经常不能正常显示输出


RTTLogger:支持中文,并且可以保存为log文件。使用具体的正确使用方法不清楚。根据手册说明,log只接收RTT通道1的输出,即SEGGER_RTT_printf(1,"字符串",输出格式)。但是实测,只能输出RTT通道0的信息,并且要求代码中要有使用到通道1的语句。否则收不到数据。


RTTClient:必须配合RTTLogger或者keil的Debugger来使用,而RTTLogger也必须配合Debugger使用。Client、Logger和Debugger三个窗口都打开的时候,Client和Logger只有其中一个能正常显示,另外一个会严重丢失数据。


方法4:使用图形化显示数据的调试法宝—JScope。


J-Scope是SEGGER公司推出的,可以在目标MCU运行时,实时分析数据并图形化显示的软件。它不需要像SWO那样需要MCU上面额外的引脚,而是使用标准的调试接口。J-Link驱动4.90之后的版本都有这个软件哦。


关键字:stm32  printf  打印log 引用地址:stm32实现printf打印log的几种办法

上一篇:STM32学习记录——printf函数重定位
下一篇:STM32在IAR中如何使用printf函数

推荐阅读最新更新时间:2024-03-16 16:22

STM32串口——5个串口的使用方法
串口是我们常用的一个数据传输接口,STM32F103系列单片机共有5个串口,其中1-3是通用同步/异步串行接口USART(Universal Synchronous/Asynchronous Receiver/Transmitter),4,、5是通用异步串行接口UART(Universal Asynchronous Receiver/Transmitter)。 配置串口包括三部分内容: 1. I/O口配置:TXD配置为复用推挽输出(GPIO_Mode_AF_PP),RXD配置为浮空输入(GPIO_Mode_IN_FLOATING); 2. 串口配置:波特率等; 3. 中断向量配置:一般用中断方式接收数据。 注
[单片机]
<font color='red'>STM32</font>串口——5个串口的使用方法
STM32 - ADC、DMA、USART使用
这是一个综合的例子,演示了ADC模块、DMA模块和USART模块的基本使用。   我们在这里设置ADC为连续转换模式,常规转换序列中有两路转换通道,分别是ADC_CH10(PC0)和ADC_CH16(片内温度传感器)。因为使用了自动多通道转换,数据的取出工作最适合使用DMA方式取出,so,我们在内存里开辟了一个u16 AD_Value 数组,并设置了相应的DMA模块,使ADC在每个通道转换结束后启动DMA传输,其缓冲区数据量为2个HalfWord,使两路通道的转换结果自动的分别落到AD_Value 和AD_Value 中。   然后,在主函数里,就无需手动启动AD转换,等待转换结束,再取结果了。我们可以在主函数里随时取AD_V
[单片机]
STM32 结构体对齐规则
1、对齐算法 在相同的对齐方式下,结构体内部数据定义的顺序不同,结构体整体占据内存空间也不同。 如下结构体定义: struct A { // a 的自身对齐值为 4,偏移地址为 0x00~0x03,a 的起始地址 0x00 满足 0x00%4=0 int a; // b 的自身对齐值为 1,由于紧跟 a 之后的地址,即 0x04 满足 0x04%1=0,所以 b 存放在 0x04 地址空间 char b; // c的自身对齐值为2,由于紧跟b之后的地址0x05%2不是0,而0x06%2=0 // 因此c的存放起始地址为0x06,存放在0x06~0x07空间。 // 在b和c之间的0x05地址则补空字节 shor
[单片机]
【stm32f103】stm32 外部中断(寄存器版)
中断分类 STM32的EXTI控制器支持19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/ 事件都有独立的触发和屏蔽设置。 STM32的19个外部中断对应着19路中断线,分别是EXTI_Line0-EXTI_Line18: 线0~15:对应外部 IO口的输入中断。 线16:连接到 PVD 输出。 线17:连接到 RTC 闹钟事件。 线18:连接到 USB 唤醒事件。 触发方式:STM32 的外部中断是通过边沿来触发的,不支持电平触发。 外部中断分组:STM32 的每一个GP
[单片机]
【stm32f103】<font color='red'>stm32</font> 外部中断(寄存器版)
STM32学习记录——printf函数重定位
功能: 重定位printf函数,使printf作为串口打印输出函数。代替usart_send_string()函数 步骤: usart.c中包含USART初始化函数 1、USART初始化(使能时钟、使能GPIO、GPIO和USART初始化) 2、打开USART 3、在usart.c中加入如下代码 #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker- Libraries- Small printf set to 'Yes') calls __io_putchar() */ #define PUT
[单片机]
基于STM32的多功能数字钟(中文版)
/************************************************************************************** 程序功能:基于STM32的多功能数字钟(中文版) ************************************************************************************** 1、时钟的基准用STM32F103RCT6自带的RTC实现。 2、这三个按键的功能分别为: 设置 、 加 、 减 。(WAKEUP KEY0 KEY1) 三个按键作为这三个功能: 键盘上的WAKEUP用作 设置 ,KE
[单片机]
ulink-Jlink下在ram和flash中调试STM32的方法
Keil MDK3.20 在ULINK下调试stm32方法 1. 程序在RAM中运行 要点:(1)程序的下载地址改到RAM空间中 (2)程序的debug之前要设定SP,PC指针到Ram空间 新建工程,选择STM32 的具体型号,我买的万利的开发板,选择stm32f103Vb。 设定程序下载地址,如下图所示,IROM1的地址指向了STM32的ram空间。 空间大小如何分配取决于自己的需求。本款处理器内部ram大小为20K,分配16K给只读区,4K给可读可写区。这样IROM设定的大小为0x4000,IRAM1的起始就变为0X20004000,大小只剩下0X1000。 Debug标签选择ULINK1 Corte
[单片机]
ulink-Jlink下在ram和flash中调试<font color='red'>STM32</font>的方法
STM32 独立看门狗简介
STM32的独立看门狗由内部专门的40Khz低速时钟驱动,即使主时钟发生故障,它也仍然有效。 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示MCU已经挂了),便实现处理器的自动复位重启(发送复位信号)。 在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。无论何时,只要键寄存器IWDG_KR中被写入0xAAAA,IWDG_RLR中的值就会被重新加载到计
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved