大家好,我是单片机爱好者-MCU起航。这一节我们继续介绍如何使用库函数方式控制STM8S103F3P6片上的串口。上一节说了USART的基本用法,可以接受、发送字节,也可以发送一些字符串。但使用上不是很方便,也不够灵活。这一节我们看下它的串口如何重定向到printf上,使用printf函数来打印输出相关的数据。
printf()函数是式样化输出函数, 一般用于向准则输出设备按规定式样输出消息。
上一节,串口输出,可以是16进制数,可以是字符串。但如果是浮点型数据,那就很费劲了,需要写一堆的转换函数。
但是,这一切在printf()函数里已经给我们写好了,咱们只需要直接调用即可,但是格式一定要正确。 举例如下:
int intValue = 2;
printf(“1.正常输出整型:%i\n”,intValue);//输出2
char charValue = ‘a’;
printf(“13.字符输出:%c\n”,charValue);//输出a
float floatValue = 6.9f;
printf(“7.正常输出浮点型:%f\n”,floatValue);//输出6.900000
上面三个例子,分别对应整形、字符型和浮点型数据的输出。不同数据的输出,%后面跟着的字符不一样,大家一定要注意。
演示代码如下:
/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "uart.h"
#include <stdio.h>
const unsigned char mcu_str01[] ="hello,everyone!\r\n";
u8 send_flag = 0;
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void main(void)
{
Uart1_Init();
enableInterrupts(); //使能中断
while (1)
{
printf("\r\nhello,state gird!");
}
}
首先,包含了这个库“stdio.h”,因为函数“printf”在这个库里,要使用的话,一定要包含。
然后是串口初始化,和上一节一样,设置波特率、有效字节、停止位等,不一样的地方在于,要对printf做重定向,代码如下:
#include "uart.h"
/*
由于不同的编译器 putcha 和 getchar 形参和返回值略有不同。
因此此处采用宏定义的方式区别。
_RAISONANCE_ 和 _COSMIC_ 这2个宏是由编译器自动添加的预编译宏
*/
#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */
void Delay(uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
void Uart1_Init(void)
{
UART1_DeInit(); /* 将寄存器的值复位 */
/*
* 将UART1配置为:
* 波特率 = 115200
* 数据位 = 8
* 1位停止位
* 无校验位
* 使能接收和发送
* 使能接收中断
*/
UART1_Init((u32)9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO , UART1_SYNCMODE_CLOCK_DISABLE , UART1_MODE_TXRX_ENABLE);
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
UART1_Cmd(ENABLE);
}
void UART1_SendByte(u8 data)
{
UART1_SendData8((unsigned char)data);
/* 等待传输结束 */
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
void UART1_Sendstr(const unsigned char *p_str)
{
// u8 i = 0;
while(*p_str != '\0')
{
UART1_SendByte(*p_str);
// Delay(1000);
p_str++;
}
}
PUTCHAR_PROTOTYPE
{
/* 发送一个字符 c 到UART1 */
UART1_SendByte(c);
return (c);
}
除此之外,还要对该工程包含的库做修改:
如图,之前这里选的是normal,现在改成FULL。
这里说一下使用printf函数的优缺点,优点很明显,使用灵活、方便,无论是调试,还是打印重要信息,都可以。
同时,缺点也要注意下:1、占用flash空间,因为library从normal改成了full,同时添加了一个stdio.h库,导致小容量的单片机对这种方式非常敏感,很容易出现flash不够用的情况。
2、printf操作速度会慢一些。虽然人眼感受不到,但确实慢了。因为这种方式相当于对串口的操作做了很多封装和调用,效率自然低了。
那么,除此之外,还有没有别的实现方法?
答案当然是有的。
首先,我们的目的是什么?
使用printf函数!因为要包含相关的库,所以使用的过程中要修改library,使它包含更多的内容。
在这个过程中,因为library包含了很多无用的内容,所以导致程序占用flash空间。如何解决?
我们可以手写一个需要的库,只把我们要的功能写进来,这样就避免了flash空间的浪费。如何实现,万能的网友已经帮我们写好了。代码比较大,我就不贴了。大家感兴趣的话,直接下载工程文件即可。
打完收工!
想要获取相关程序完整的工程文件,可以关注公众号:单片机爱好者,然后回复关键词:STM8S。可以获取完整的下载链接,里面包含工程文件、视频、PPT、数据手册等所有相关资料。