在单片机中使用最多的通信接口基本就是串口了,说起串口就不得不提串口中最常用的一个函数就是打印函数printf()函数,通常使用这个函数都是直接调用库函数来实现的,在单片机中如何要使用printf()函数一般都是在串口中进行重映射。如要在串口1中使用printf()函数,可以使用下面的代码进行重映射。

//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{while((USART1->SR & 0X40) == 0); //循环发送,直到发送完毕USART1->DR = (u8) ch;return ch;
}
#endif

  在串口1的c文件中,添加上面的代码后,使用printf()函数时,就可以通过串口1来打印了。那么不通过库函数的话,自己能不能实现printf()函数的功能呢?当然是可以的,下面就通过串口2来演示,如何在串口2上直接实现printf()函数的功能。

void UART2_Init(u32 bound)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 1、串口时钟使能 GPIO时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);// 2、串口复位USART_DeInit(USART2);// 3、GPIO端口设置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                  //PA2 TXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                           //PA3 RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 4、串口参数初始化USART_InitStructure.USART_BaudRate = bound;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(USART2, &USART_InitStructure);// 5、初始化NVICNVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 6、开启中断USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);// 7、使能串口USART_Cmd(USART2, ENABLE);}
void USART2_IRQHandler(void)
{u8 res;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){res = USART_ReceiveData(USART2);USART_SendData(USART2, res);            //把接收到的数据发送出去}
}

  首先初始化串口2,初始化方式和正常情况下一样,初始化完成之后开始自定义一个函数来实现printf()函数的功能。

//自定义串口2 的printf 函数
char UART2_TX_BUF[200];
void u2_printf(char* fmt, ...)    //无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表
{u16 i, j;va_list ap;          //va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。va_start(ap, fmt);   //va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束vsprintf((char*)UART2_TX_BUF, fmt, ap);   // 把生成的格式化的字符串存放在这里va_end(ap);i = strlen((const char*)UART2_TX_BUF);              //此次发送数据的长度for(j = 0; j < i; j++)                                                    //循环发送数据{while((USART2->SR & 0X40) == 0);                    //循环发送,直到发送完毕USART2->DR = UART2_TX_BUF[j];}
}

  这个函数名定义为 :u2_printf(char* fmt, …) 使用省略号表示当前参数为可变参数。接下里就可以直接使用这个函数来打印数据了。在主函数中通过一段代码来测试串口1和串口2 printf函数的功能。

int main(void)
{u8 t;u8 len;u16 times = 0;delay_init();       //延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);LED_Init();UART2_Init(115200);printf("USART1 AND USART2 TEST!!!");while(1){if(USART_RX_STA & 0x8000){LED1 = !LED1;len = USART_RX_STA & 0x3fff;        //获取本次接收数据长度printf("\r\n您发送的消息为:\r\n");for(t = 0; t < len; t++){USART_SendData(USART1, USART_RX_BUF[t]); //向串口1发送数据while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); //等待发送完成}printf("\r\n");USART_RX_STA = 0;}else{times++;if(times % 5000 == 0){printf("串口实验\r\n");u2_printf("串口实验\r\n");                                 //调用串口2 printf 函数}if(times % 300 == 0){printf("请输入数据,以回车键结束\r\n");u2_printf("请输入数据,以回车键结束\r\n");        //调用串口2 printf 函数}if(times % 30 == 0)LED0 = !LED0;delay_ms(10);}}
}

  通过串口1和串口2输出同样的提示信息,然后用串口助手分别给串口1和串口2发送数据,当串口1和串口2接收到数据后就会通过串口打印出来。串口1和串口2输出的提示信息都是用printf函数输出的。

  可以看出串口2的printf函数和功能和串口1的printf函数功能一样,可以正常输出字符串。也可以使用串口2的printf函数打印变量值,比如在代码中增加一句变量打印的功能。

  每次输出提示信息的时候,顺便打印一下变量times的值。

  可以看到变量times的值也可以正常打印。

STM32F103自定义的printf函数的实现相关推荐

  1. STM32F103串口1 printf函数的实现

      在单片机中使用最多的通信接口基本就是串口了,说起串口就不得不提串口中最常用的一个函数就是打印函数printf()函数,在上位机上中这个函数直接从库函数中调用就可以了,那么在单片机中这个函数要怎么使 ...

  2. STM32多串口printf函数

    1.配置usart2的串口配置,gpio,rcc enable,跟上面类似 2.勾选usb micro lib,跟上面类似 3.添加头文件#include <stdarg.h>,编写USA ...

  3. C语言 va_start / va_end / va_arg 自定义 printf 函数 - C语言零基础入门教程

    目录 一.前言 二.函数不定长参数简介 1.va_start 2.va_arg 3.va_end 三.win32 控制台版本 四.MFC 对话框版本 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : ...

  4. STM8S系列基于STVD开发,自定义printf函数+TIM5精确延时函数模块化工程示例

    STM8S系列基于STVD开发,自定义printf函数+TIM5精确延时函数模块化工程示例

  5. c语言自定义char*函数返回值是乱码_[每日C语言」printf()函数的修饰符和返回值...

    在上一个小demo<printf()函数(1)>中主要说了一下printf()函数的转换说明符,这些转移说明符是可以被修饰的.我们可以在%d和定义的转义字符之间通过插入修饰符对基本的转换说 ...

  6. C语言 vprintf 函数和 printf 函数区别 - C语言零基础入门教程

    目录 一.vprintf 函数和 printf 函数声明简介 1.printf 函数声明 2.vprintf 函数声明 二.vprintf 函数和 printf 函数使用 三.猜你喜欢 零基础 C/C ...

  7. c语言学习-自定义并调用函数求三个数的最小公倍数

    c语言自定义并调用函数求三个数的最小公倍数 程序流程图: 代码: #include<stdio.h> int la1(int m ,int n,int p); int la2(int m ...

  8. 可变参数列表来实现printf函数的输出

    #include<stdio.h> #include<stdarg.h> void my_printf(const char*str,...) {va_list arg;//创 ...

  9. DSP 调试自定义变参打印函数

    在DSP调试打印信息往往需要打印的信息数量及长度不相等,而每次打印我们又想知道错误所在文件,以及行号等信息等,若直接用printf函数,每次都要输入这些参数会感觉繁琐,所以我们会自定义一个变参函数来代 ...

最新文章

  1. 腾讯云的Ubuntu 18.04的镜像地址
  2. python多个线程join_python-使用`thread.join()`时多线程冻结
  3. linux .ssh隐藏,linux安全配置-将ssh服务隐藏于Internet(端口碰撞)
  4. major头文件_JPEG头文件结构及组成
  5. 巧妙的查看FORM中的 LOV查询语句
  6. mysql的远程帐号密码_MySQL设置远程客户端访问权限和修改账户密码
  7. C#与C++在语言层面的区别(不断补充)
  8. 剑指Offer的学习笔记(C#篇)-- 二叉树的下一个节点(好理解版本)
  9. 两天来的Java IO Tips
  10. 办公室学什么计算机,(计算机)办公室文员、助理都可以学学,留着迟早用得着
  11. 截止今年六月底的s9t9
  12. 小说更新太慢怎么办_5本更新慢如龟速的网络小说,书虫追更很煎熬,却依旧不离不弃...
  13. 如何运行element ui
  14. 用python解决放苹果问题_放苹果问题(组合数学经典)
  15. datagrid的deleteRow使用
  16. mac下配置Charles,安装证书
  17. 约瑟夫问题 pku1012(转自奋斗青春(亚伟)blog)
  18. 地平线4显示与服务器通讯发生错误,地平线4加载失败发生不明错误的解决方法 - 系统家园...
  19. 【2018十大VR眼镜排行榜】VR眼镜有哪些品牌。哪个牌子的VR眼镜比较好,性价比高,适合玩VR游戏的
  20. 获取高匿代理ip的想法思路

热门文章

  1. browser.html – HTML 实现 Firefox UI
  2. db2 快速清除表中所以的数据
  3. ASP.NET Session的七点认识
  4. cisco6509 2811 配置备份
  5. JZOJ 3461. 【NOIP2013模拟联考5】小麦亩产一千八(kela)
  6. android 相对布局例子代码
  7. HTML表格的简单使用1
  8. python中数字类型与处理工具
  9. webstrom 里面使用github
  10. 归并排序的C++实现