本帖最后由 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
最后,看一下演示效果吧:
|