zoukankan      html  css  js  c++  java
  • STM32标准库_03 | 串口printf打印

    本篇文章主要介绍STM32的调试利器,串口printf打印输出,希望能给人以收获。

    1.开发环境

    软件环境

    使用MDK5.25版本,芯片包为STM32F4系列。

    硬件环境

    开发板:STM32F407VGT6开发板,是一款大容量芯片,最高能跑168MHz。

    烧录器:STlink或者Jlink。

    2.工程搭建

    直接复制上一篇代码,在工程栏加入/LIB/src文件夹下的串口库函数文件stm32f4xx_usart.c,在/APP文件夹下加入usart.c和usart.h文件并添加到MDK工程栏。

    开始编写串口初始化函数和重定义printf打印函数。

    在usart.c文件中添加串口初始化函数,F407和F103有些区别,1是串口挂载的时钟总线,2是F103对于串口TX和RX是分别初始化为复用推挽输出和上拉输入的。

    /*
    *********************************************************************************************************
    *	函 数 名: uart1_Init
    *	功能说明: 串口1初始化函数
    *	形    参: 1.bound(串口波特率)
    *	返 回 值: 无
    *********************************************************************************************************
    */ 
    void uart1_Init(u32 bound)
    {
            //GPIO端口设置
            GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
     
    	//串口1对应引脚复用映射
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
    	
    	//USART1端口配置
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
    
            //USART1 初始化设置
    	USART_InitStructure.USART_BaudRate = bound;//波特率设置
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    	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_Tx;	//收发模式
            USART_Init(USART1, &USART_InitStructure); //初始化串口1
    	
            USART_Cmd(USART1, ENABLE);  //使能串口1 
    	//USART_ClearFlag(USART1, USART_FLAG_TC);   //解决第一个字节丢失问题,如果第一个字节丢失可以加上这行
    }
    

    对于重定义printf函数有两种方法,一种是使用微库,一种是不是用微库(正点原子)使用的方法。

    1.使用微库重定义printf函数

    注意:printf函数依赖于"stdio.h",在使用的时候记得添加上"stdio.h"。

    如果是C++文件则修改成

    2.不使用微库重定义printf函数

    在原来的fputc函数的基础上再加入避免使用半主机模式的一些代码(参考正点原子)。

    可以参考这篇对于半主机模式的理解

    小结:所谓重定义就是修改fputc函数的底层代码,修改成运行一次串口发送一个字节的数据。

    3.测试

    3.打印方案

    编写打印代码

    于我而言,我个人把打印分成两种,一种是错误打印(一般用于else的后面,或者校验失败的地方),另一种就是常规打印,这些打印还可能遇到一些场景,例如我的单片机资源比较少,我就写程序的时候用一下,或者我想控制我的打印输出等等。

    直接上代码开讲

    USER_DEBUG是程序控制的开关,用于单片机资源比较少的时候,我们调试的时候用一下。

    Print_Switch是一个接口控制的开关,可用于远程网络或者本地串口修改,来开启或者关闭打印。

    当然,我们还可以分很多级别的打印,希望各位举一反三。

    测试

    4.总结

    这个宏定义最好放在.h头文件中,方便其他.c文件,后续我会加在Dbg.c和Dbg.h中,对于逻辑复杂的状态机,用打印的方法是一个很好的调试手段,当然如果遇到死机,那得用仿真器Debug了。

    代码已全部上传到gitee,希望各位小伙伴们在下载的同时不忘点击Star,地址:https://gitee.com/Notmi/stm32-standard-peripheral-libraries

  • 相关阅读:
    Harbor1.5.2批量清理无效镜像
    前端私服地址修改
    Paxos算法
    缓存淘汰算法--LRU算法
    一致性哈希
    mysql常见知识点总结
    mysql分库分表(二)
    mysql分库分表(一)
    dubbo学习小结
    dubbo超时重试和异常处理
  • 原文地址:https://www.cnblogs.com/zhanxiaohong0303/p/xh_2020_7_1.html
Copyright © 2011-2022 走看看