IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FreeRTOS移植STM32 printf()函数重定向到USART3 -> 正文阅读

[嵌入式]FreeRTOS移植STM32 printf()函数重定向到USART3

? ? ? ? 我们在移植FreeRTOS过程中如果没有printf()函数打印调试信息到串口精灵,则程序开发就会非常不方便。本文实现STM32工程上的printf()函数,方便用于程序开发中调试信息打印到电脑上的串口调试精灵。

? ? ? ? 最简单的方法就是使用MicroLIB库。

一、KEIL-MDK中勾选Use MicroLIB选项

? ? ? ? 在MDK开发环境中,勾选Use MicroLIB选项。

?? ? ? ? MicroLib是缺省c库的备选库,它可装入少量内存中,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行。
?? ? ? ? MicroLib进行了高度优化以使代码变得很小,功能比缺省c库少,不具备某些ISO c特性,部分库函数的运行速度也比较慢,如内存拷贝函数memcpy()。
?? ? ? ? MicroLib与缺省c库之间的主要差异在网上有许多文章都有写到,这里摘抄记录:


(1)MicroLib 不符合 ISO C 库标准。 不支持某些 ISO 特性,并且其他特性具有的功能也较少。
(2)MicroLib 不符合 IEEE 754 二进制浮点算法标准。
(3)MicroLib 进行了高度优化以使代码变得很小。
(4)无法对区域设置进行配置。 缺省 C 区域设置是唯一可用的区域设置。
(5)不能将 main() 声明为使用参数,并且不能返回内容。
(6)不支持 stdio,但未缓冲的 stdin、stdout 和 stderr 除外。
(7)MicroLib对 C99 函数提供有限的支持。
(8)MicroLib不支持操作系统函数。
(9)MicroLib不支持与位置无关的代码。
(10)MicroLib不提供互斥锁来防止非线程安全的代码。
(11)MicroLib不支持宽字符或多字节字符串。
(12)与stdlib不同,MicroLib不支持可选择的单或双区内存模型。MicroLib只提供双区内存模型,即单独的堆栈和堆区。

?
?? ? ? ? MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr,那么也就是说勾选了Use MicroLib选项后,在代码工程中就可以使用printf()函数吗?
?? ? ? ? 然而事实并非如此,这样直接使用printf()函数,其打印的字符串最终不知道打印到何处。我们要做的是将调试信息打印到USART3中,所以需要对printf()函数所依赖的打印输出函数fputc()重定向(MicroLib中的printf()函数打印操作依赖fputc())。

?

二、重定向fputc函数

?? ? ? ? 在MicroLib的stdio.h中,fputc()函数的原型为:

int fputc(int ch, FILE* stream)

?? ? ? ? 1、重定向fputc()函数?

?? ? ? ? 此函数原本是将字符ch打印到文件指针stream所指向的文件流去的,现在我们不需要打印到文件流,而是打印到串口3。因此重定向到串口3的代码如下:


//
//	函 数 名: fputc
//	功能说明: 重定义putc函数,这样可以使用printf函数从串口3打印输出
//	形    参: 无
//	返 回 值: 无
//
int fputc(int ch, FILE *f)
{

	USART_SendData(USART3, (uint8_t) ch);
	// 等待发送结束
	while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
	return ch;
}

??? ? ? ? 2、编写串口3端口初始化程序

static void print_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;


	// 第1步: 开启GPIO和UART时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	// 第2步:将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	// 第3步:将USART Rx的GPIO配置为浮空输入模式
	//	由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
	//	但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
	//
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//  第3步已经做了,因此这步可以不做
	//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	// 第4步: 配置串口硬件参数 
	USART_InitStructure.USART_BaudRate = 57600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART3, &USART_InitStructure);

	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);	// 使能接收中断
	//
	//	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	//	注意: 不要在此处打开发送中断
	//	发送中断使能在SendUart()函数打开
	//
	USART_Cmd(USART3, ENABLE);		// 使能串口 

	// CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
	//	如下语句解决第1个字节无法正确发送出去的问题
	USART_ClearFlag(USART3, USART_FLAG_TC);   //清发送完成标志,Transmission Complete flag
}

??? ? ? ? 注意,需要包含头文件stdio.h,否则FILE类型未定义。
?? ? ? ? 勾选了Use MicroLib选项,重定向fputc()函数后,我们就可以在工程代码中使用printf()函数了。

三、实例

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
//------------------------------------------------------------------------------------
#include  <stdio.h>
#include  <stdlib.h>





void vTaskDT_Poll(void *pvParameters)
{	
    while(1)
    {	
		printf("vTaskDT_Poll run...\r\n");	
		GPIO_LED4_ON();
		vTaskDelay(250);
		GPIO_LED4_OFF();	
		vTaskDelay(250);
    }
}




int main(void)
{
	__set_PRIMASK(1); 	
	
	GPIO_Configuration();	
	NVIC_Configuration();
	

	print_init();	//重定向print()函数到USART3串口

	
	//创建任务通信机制
	 AppObjCreate();
	//创建任务
	AppTaskCreate();
	//启动调度器
	vTaskStartScheduler();	
	
    while (1);	
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:42:58  更:2022-11-05 00:44:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 20:03:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码