一、C語言的格式化輸出
C語言的printf是一個標(biāo)準(zhǔn)庫函數(shù),用于將格式化的數(shù)據(jù)輸出到標(biāo)準(zhǔn)的輸出設(shè)備(通常是終端)
- 基本語法:
int printf(const char *format, ...);
其中的第一個參數(shù)const char *format
表示輸出格式,后面的參數(shù)是可變參數(shù),用于填充格式化字符串中的占位符。
- 字符輸出原理:
- 格式化字符串處理:printf函數(shù)將第一個參數(shù)
const char *format
中的格式占位符解析出來,然后根據(jù)占位符的類型和順序依次取可變參數(shù)中的值,將這些值轉(zhuǎn)換為字符串,并將其按照格式化字符串中的順序和樣式組合成最終的輸出字符串。 - 輸出字符串存儲:printf函數(shù)將格式化后的輸出字符串存儲在內(nèi)存緩沖區(qū)中。
- 輸出字符串顯示:printf函數(shù)將內(nèi)存緩沖區(qū)中的輸出字符串顯示到標(biāo)準(zhǔn)輸出設(shè)備上,通常是終端。
在學(xué)習(xí)C語言的時候,在調(diào)用頭文件
#include "stdio.h"
的時候,就可以使用printf函數(shù)進(jìn)行格式化打印
#include <stdio.h>
int a = 10;
char str[] = "hello,world!";
int main(void)
{
printf("%s\n",str);
printf("a = %d",a);
return 0;
}
[result]
hello,world!
a = 10
但是在Keil中,在stm32的使用中是不能直接使用C語言的打印函數(shù)的,需要添加支持設(shè)置,即調(diào)用MDK的微庫(MicroLib) 稱之為printf的重定向。其實(shí)不僅僅可以把打印字符重定向,而且還可以將獲取字符重定向。
二、開發(fā)準(zhǔn)備
-
基于STM32L431RCT6的小熊派開發(fā)板
-
windows系統(tǒng)并安裝Cubemx和Keil MDK的電腦
三、初始化片上外設(shè)
本次開發(fā)介紹的主要是串口的重定向,因此就是需要初始化串口外設(shè)。
設(shè)置串口通信為異步通信,波特率115200
生成代碼,并選擇keil-MDK打開該工程
四、設(shè)置重定向
4.1 點(diǎn)擊魔術(shù)棒,然后勾選使用微庫(Use MicroLIB)
針對MicroLIB的介紹:
? MicroLIB是Keil公司提供的一個C標(biāo)準(zhǔn)庫,專為嵌入式系統(tǒng)設(shè)計(jì)而開發(fā)。相對于標(biāo)準(zhǔn)C庫,MicroLIB庫更加輕量級,代碼量更小,適用于嵌入式系統(tǒng)等資源受限的環(huán)境。MicroLIB庫支持ISO/ANSI C標(biāo)準(zhǔn)的大部分函數(shù),并增加了一些嵌入式系統(tǒng)常用的函數(shù),例如串口通信、GPIO控制等。在MDK的工程中,開發(fā)者可以選擇使用MicroLIB庫來進(jìn)行開發(fā),以減小程序的代碼大小和占用內(nèi)存的空間。
? 需要注意的是,MicroLIB庫并不是一個完整的C標(biāo)準(zhǔn)庫,它只實(shí)現(xiàn)了一部分的C標(biāo)準(zhǔn)函數(shù),并且一些函數(shù)的實(shí)現(xiàn)與標(biāo)準(zhǔn)C庫可能存在差異。如果需要使用標(biāo)準(zhǔn)C庫的函數(shù)或者功能更加完整的C標(biāo)準(zhǔn)庫,開發(fā)者需要使用其他的C標(biāo)準(zhǔn)庫,例如GNU C Library(glibc)等。
4.2 添加串口重定向代碼
在main.c
函數(shù)中添加頭文件:
#include "stdio.h"
在main.c
函數(shù)的/* USER CODE BEGIN 4 */
內(nèi)添加下面代碼即可:
int fputc(int c,FILE *f)
{
uint8_t ch; //定義一個無符號8位整型變量ch 并將字符C賦值給它
ch = c;
HAL_UART_Transmit(&huart1,&ch,1,1000);
// 調(diào)用HAL庫的串口發(fā)送函數(shù),將ch發(fā)送到USART1串口,等待時間為1000ms
return c;
}
4.3 在主循環(huán)中添加代碼進(jìn)行測試
/* USER CODE BEGIN 2 */
uint8_t str[] = "Hello GearLong!";
uint8_t num1 = 10;
float f = 3.1415926;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("%s\r\n",str);
printf("num = %d\r\n",num1);
printf("f1 = %f\r\n",f);
printf("f2 = %.2f\r\n",f);
printf("f3 = %8.3f\r\n",f);
HAL_Delay(1000);
}
4.4 編譯、下載,然后打開串口調(diào)試助手查看執(zhí)行
記得將AT開關(guān)撥到AT_MCU
4.5 不使用微庫打印數(shù)據(jù)
下面的代碼來自正點(diǎn)原子的HAL庫代碼中的串口打印 ,將代碼復(fù)制到
usart.c
的代碼添加處,并取消勾選微庫,并移除上面已經(jīng)設(shè)置的重定向代碼。
在usart.c
函數(shù)中添加頭文件:
#include "stdio.h"
在usart.c
函數(shù)/* USER CODE BEGIN 1 */
內(nèi)添加下面代碼即可:
/* 加入以下代碼, 支持printf函數(shù), 而不需要選擇use MicroLIB */
#if 1
#if (__ARMCC_VERSION >= 6010050) /* 使用AC6編譯器時 */
__asm(".global __use_no_semihosting\n\t"); /* 聲明不使用半主機(jī)模式 */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6下需要聲明main函數(shù)為無參數(shù)格式,否則部分例程可能出現(xiàn)半主機(jī)模式 */
#else
/* 使用AC5編譯器時, 要在這里定義__FILE 和 不使用半主機(jī)模式 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* 不使用半主機(jī)模式,至少需要重定義_ttywrch\_sys_exit\_sys_command_string函數(shù),以同時兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* 定義_sys_exit()以避免使用半主機(jī)模式 */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE 在 stdio.h里面定義. */
FILE __stdout;
/* 重定義fputc函數(shù), printf函數(shù)最終會通過調(diào)用fputc輸出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0); /* 等待上一個字符發(fā)送完成 */
USART1->DR = (uint8_t)ch; /* 將要發(fā)送的字符 ch 寫入到DR寄存器 */
return ch;
}
#endif
注意
在使用Cubmex生成的HAL庫代碼中,USART1的相關(guān)寄存器
可能隨著不同型號的MCU會發(fā)生變化,如果編譯不通過及時修改即可。文章來源:http://www.zghlxwxcb.cn/news/detail-676032.html
4.6 打印輸出的結(jié)果是一致的文章來源地址http://www.zghlxwxcb.cn/news/detail-676032.html
到了這里,關(guān)于STM32-HAL-串口的printf重定向的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!