[APM32F407] 优雅使用IAR9.3调用printf打印信息

本文档详细介绍了在升级IAR编译器从8.5到9.30.1版本后,如何解决APM32F4xx_SDK_V1.1中printf功能失效的问题。在IAR9.x中,printf重定向需要实现__write函数,而非像8.x版本那样简单设置。文中提供了具体的重定向代码示例,并说明了USART_Transmit函数的使用。完成重定向后,程序便能正常使用printf进行串口打印。
摘要由CSDN通过智能技术生成

最近发现IAR 发布了新版本9.30.1,在新版本中Geehy的众多MCU都完成了支持。



我这边刚好有APM32F407IG的MINIBOARD,想着使用IAR编译一下工程下载运行一下程序。不料却发现了问题,APM32F4xx_SDK_V1.1中的IAR例程是基于 IAR8.5制作的,关于printf的重定向都已经在工程内进行了设置。使用8.5的工程也可以正常使用printf功能。但在9.x的IAR对printf重定向有了新的要求,导致IAR 9.x版本无法运行含有printf功能的例程。

本文档就解决APM32F4xx_SDK_V1.1中使用IAR9.3进行编译使用printf功能进行记录分享。

值得注意的是:

- printf重定向前需完成对应串口的初始化操作。

1 IAR 8.x的printf重定向

IAR 8.x的printf重定向与Keil并无差异,仅需在内部的任意一个C文件中重定向printf后设置工程的相应参数即可完成。

1. 重定向printf代码如下(发送串口为串口1,头文件需包含stdio.h)

/* Includes */

#include "stdio.h"

/*!

 * [url=home.php?mod=space&uid=247401]@brief[/url]       Redirect C Library function printf to serial port.

 *              After Redirection, you can use printf function.

 *

 * @param       ch:  The characters that need to be send.

 *

 * @param       *f:  pointer to a FILE that can recording all information

 *              needed to control a stream

 *

 * @retval      The characters that need to be send.

 */

int fputc(int ch, FILE *f)

{

    /** send a byte of data to the serial port */

    USART_TxData(DEBUG_USART,(uint8_t)ch);

    /** wait for the data to be send  */

    while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);

    return (ch);

}

2. 设置工程相应参数,将General Option 的 Library Configuration 选项卡下Library选择为“Full”,CMSIS 项目勾选“Use CMSIS”。

   

至此程序中便可以正常使用printf函数。

2 IAR 9.x的printf重定向

通过查阅IAR的开发文档。(在Help选项卡下打开“C/C++ Development Guide”)



在开发文档的“BRIEFLY ABOUT RETARGETING”章节,我们可以看到IAR9.x要求我们使用printf时需要重定向__write函数。



重定向的详细内容请查阅文档,此处不在赘述。这里给出参考操作。

1. 在源码目录下,新建“write.c”文件用于存放我们重定向的代码。

2. 打开需要重定向的工程,在工程中添加我们刚刚新建的“write.c”。



3. 编辑“write.c”文件,添加重定向代码。代码内容如下。

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

 *

 * Copyright 1998-2017 IAR Systems AB.

 *

 * 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 <LowLevelIOInterface.h>

#include "Board.h"

#include "apm32f4xx.h"

#pragma module_name = "?__write"

uint8_t USART_Transmit(USART_T* usart, uint8_t *pdata, uint16_t Size);

/*

 * 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)

{

  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;

  }

  

  /* Sending in normal mode */

  if(USART_Transmit(USART1,(uint8_t *)buffer,size) == 1)

  {

    return size;

  }

  else

  {

    return _LLIO_ERROR;

  }

}

uint8_t USART_Transmit(USART_T* usart, uint8_t *pdata, uint16_t Size)

{

  uint8_t ch = 0;

  uint16_t i = 0;

  uint16_t timeout = 0x1000;

  

  for(i=0;i<Size;i++)

  {

    ch = pdata[i];

   

    /** send a byte of data to the serial port */

    USART_TxData(usart,(uint8_t)ch);

    /** wait for the data to be send  */

    while ((USART_ReadStatusFlag(usart, USART_FLAG_TXBE) == RESET) && (timeout -- ));

   

    if(timeout == 0)

    {

      return 0;

    }

   

    timeout = 0x1000;

   

  }

  

  return 1;

}

    __write函数为IAR要求我们进行重定向的函数,这里使用的发送串口是串口1,若需要使用其他串口,请相应修改“USART_Transmit(USART1,(uint8_t *)buffer,size) == 1”中的USART1参数。

    USART_Transmit函数是为了便捷使用发送功能进行定义的函数,其采用的是轮训发送的操作,有超时设置,返回1为发送成功,返回0为发送失败。

至此程序中便可以正常使用printf函数。

以上便是APM32F4xx_SDK_V1.1中的IAR工程使用9.30打开后如何使用printf进行打印的全部内容。
---------------------
作者:kai迪皮
链接:https://bbs.21ic.com/icview-3234134-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值