本帖最后由 caizhiwei 于 2023-7-14 21:43 编辑
#申请原创# #申请开发板# @21小跑堂 @21ic小喇叭
一,板卡简介:
APM32F407 Tiny Board搭载一颗基于Arm® Cortex®-M4F内核的32位工业级高性能APM32F407 MCU,工作主频168MHz,Flash 1MB,SRAM 192+4KB;该Tiny板配备使用说明书、原理图、SDK等,可协助开发者快速上手,支持实时系统Free RTOS和RT-Thread,可使用的开发工具包含Keil MDK-ARM、IAR Embedded Workbench、Visual Studio Code、Eclipse。
二, 背景
printf和scanf是学习C语言是首先会接触的内容。在单片机上也可以使用这两个函数实现打印功能,需要结合串口实现,也需要IDE支持,不同的IDE实现scanf接收和printf打印的方法是不一样的。本文将讲解如何使用KEIL实现printf和scanf。
首先是确定串口连接,下载APM407的数据手册,可以看到USART1连接到了PA9(TX)和PA10(RX)上,正好官方提供的例程也是使用的USART1,所以将官方例程直接拿过来修改完成我们需要的功能即可。
三,问题原因
在 IAR 9.30.xx 的 IAR 对 printf 重定向有了新的要求,导致 IAR 9.30.xx 及以上的版本无法运行含有 printf 功能的例程。
IAR 9.30.xx 的 printf 重定向重定向的详细内容我这里给出参考操作。
四,操作步骤
在源码目录下,新建 write.c 文件用于存放我们重定向的代码;
打开需要重定向的工程,在工程中添加我们刚刚新建的 write.c ;编辑“write.c”文件,添加重定向代码。代码内容如下,需要根据 UART 设置修改相关函数。
#include "printf.h"
#if defined (__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
/*!
* [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.
* @note
*/
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
UartX_Put_Char(DEBUG_USART, (uint8_t)ch);
return (ch);
}
#elif defined (__GNUC__)
/*!
* [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.
*
* @retval The characters that need to be send.
*
* @note
*/
int __io_putchar(int ch)
{
/* send a byte of data to the serial port */
UartX_Put_Char(DEBUG_USART, ch);
return ch;
}
int _write(int file, char* ptr, int len)
{
int i;
for (i = 0; i < len; i++)
{
__io_putchar(*ptr++);
}
return len;
}
#elif defined (__ICCARM__) /*For IAR */
#include <LowLevelIOInterface.h>
#pragma module_name = "?__write"
int MyLowLevelPutchar(int x)
{
UartX_Put_Char(DEBUG_USART, (uint8_t)x);
return x;
}
/*
* 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 */
#if 1
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;
#else
/* Always return error code when implementation is disabled. */
return _LLIO_ERROR;
#endif
}
#else
#warning Not supported compiler type
#endif
最后,看一下演示效果吧:
|