# 前言
printf和scanf是学习C语言是首先会接触的内容。在单片机上也可以使用这两个函数实现打印功能,需要结合串口实现,也需要IDE支持,不同的IDE实现scanf接收和printf打印的方法是不一样的。本文将讲解如何使用KEIL实现printf和scanf。
本文试验的测试环境:
- 系统:win10
- IDE:KEIL V5.34
- 单片机:极海APM407IGT6
# 1 硬件连接
首先是确定串口连接,下载APM407的数据手册,可以看到USART1连接到了PA9(TX)和PA10(RX)上,正好官方提供的例程也是使用的USART1,所以将官方例程直接拿过来修改完成我们需要的功能即可。
连接线路如下:
| USB-TTL | APM32F407 |
| ------- | --------- |
| RX | PA9 |
| TX | PA10 |
| GND | GND |
> 注:官方例程是基于MINI开发板的,我们这块是TINY开发板,所以使用的库是不一样的,需要修改,后面讲述方法。
# 2 软件代码编写
要实现printf和scanf,本质上是实现fputc和fgetc函数。
需要实现对单个字符的接收和发送即可。实现代码如下:
```c
// fputs for printf or other print function in standard
int fputc(int ch, FILE *f)
{
(void)f;
/** Wait until end of transmission */
USART_TxData(TINY_COM1, (uint8_t)ch);
while(USART_ReadStatusFlag(TINY_COM1, USART_FLAG_TXBE) == RESET) {};
return ch;
}
// fgets for scanf or other input function in standard
int fgetc(FILE *f)
{
uint8_t ch;
(void)f;
while(USART_ReadStatusFlag(TINY_COM1, USART_FLAG_RXBNE) == RESET) {};
ch = USART_RxData(TINY_COM1);
return (int)ch;
}
```
主函数实现如下:
功能:
- 初始化LED2和LED3,上电时为熄灭状态
- 初始化串口USART1,波特率为115200
- 打印信息到串口,然后从串口接收一个整数并通过串口打印出来
- 完成之后LED2和LED3亮
```c
int main(void)
{
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
USART_Init();
printf ("APM32F407 printf test\r\n");
printf ("Please input a number with int type\r\n");
int a;
scanf ("%d", &a);
printf ("The number you input is: %d", a);
APM_TINY_LEDOn(LED2);
APM_TINY_LEDOn(LED3);
while(1)
{
}
}
```
# 3 注意事项
## 3.1 勾选 Use MicroLIB
如果需要成功使用 `printf`和 `scanf`功能,需要勾选 `Use MicroLIB`使用KEIL的内置库,不然使用printf和scanf的时候会导致程序卡死。
## 3.2 修改编译器宏
官方提供的Demo程序使用的是MINI板子的代码,我们的板子是TINY板子,所以需要修改KEIL编译器宏为 `APM32F407_TINY`,用来定位到TINY板子所包含的头文件。
> 注:代码中关于MINI的部分都修改为TINY即可。
# 4 实现效果
如下,测试成功,后续就可以使用printf来打印以及使用scanf来接收命令了。