在调试程序的时候经常需要使用printf’函数来打印相关调试信息,在STM103单片机中printf函数默认只能在串口1使用,有时候串口1被占用了,想要输出调试信息时会比较麻烦。现在就总结一下如何在其他串口上使用printf函数。这里使用正点原子的例程来做说明。
默认串口1初始化代码如下

#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;
}
#endifvoid uart_init(u32 bound) {//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  //使能USART1,GPIOA时钟//USART1_TX   GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX     GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;      //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器//USART 初始化设置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_Rx | USART_Mode_Tx;   //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE);                    //使能串口1}

初始化函数uart_init()上面的部分就是关于printf函数的相关设置,默认情况下printf函数是通过串口1输出数据的。
假如我们现在要将printf函数重新定义到串口3上,那么就可以将uart_init()上面的一部分代码剪切到串口3初始化函数前面去,同时将fputc()函数中的串口1修改为串口3就行。
重新修改后的代码如下:
串口1初始化代码


void uart_init(u32 bound) {//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟//USART1_TX   GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX     GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;      //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器//USART 初始化设置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_Rx | USART_Mode_Tx;   //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE);                    //使能串口1}

串口3初始化代码

#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((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕USART3->DR = (u8) ch;return ch;
}
#endifvoid  uart3_init(u16 baud)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef  NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);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);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);USART_InitStructure.USART_BaudRate = baud;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART3, &USART_InitStructure);USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);USART_Cmd(USART3, ENABLE);}

修改后再使用printf函数时,就可以通过串口3输出了。
关于printf函数的设置核心代码如下:

#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((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕USART3->DR = (u8) ch;return ch;
}

通过上面几个函数可以看出,要重新定义printf函数的输出串口时,只需要修改fputc()函数中关于串口的定义就行。

STM103单片机串口输出函数printf重映射相关推荐

  1. STC15单片机-串口打印printf重定向

    printf函数重定向为往串口打印信息 在UART.h.UART1.h和UART.c文件的内容编写好后,在main函数中实现通过串口发送一串字符串和一个不断加1的变量 方法一: 使用sprintf函数 ...

  2. C语言printf重入,单片机中printf函数的重映射

    单片机中printf函数的重映射 一.源自于:大侠有话说 1.如果你在学习单片机之前学过C语言,那么一定知道printf这个函数.它最最好用的功能 除了打印你想要的字符到屏幕上外,还能把数字进行格式化 ...

  3. STM32F103单片机JTAG端口重映射

    STM32单片机复位后,JTAG口默认是被占用的.如果想将JTAG占用的几个IO口设置为普通IO口,就需要进行端口重映射. 复位后端口默认功能可以在STM32参考手册上看到 要将JTAG占用的这些口设 ...

  4. RT-Thread—重映射串口到rt_kprintf

    文章目录 重映射 rt_kprintf()函数定义 自定义rt_hw_console_output() 重映射 在初学C语言时,用的最多的怕是printf()函数了,其作用就是将传入的参数打印到屏幕上 ...

  5. GD32F305 串口的重映射

    工作中使用需要USART2 重映射到PC10 和PC11 上: 1.根据手册查只能部分映射 2.程序中采用部分映射 3.附上串口初始化程序: void USART2_init(void) {      ...

  6. stm32单片机端口映射_STM32单片机的重映射与地址映射的使用方法及步骤

    重映射 STM32 中对于一些端口的外设已经被其他引脚所使用,这是就需要用端口重映射来解决 了,很方便. 以 USART1 为例 重映射的步骤为: 打开重映射时钟和 USART 重映射后的 I/O 口 ...

  7. c语言输入输出重定向到串口,关于printf重定向到串口的问题分析 - 全文

    关于printf重定向到串口的问题 简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosTIng(半主机模式), 标准库函数的默认输出设备是显示器,要实现在串口 ...

  8. 蓝桥杯单片机串口通信学习提升笔记

    今日得以继续蓝桥杯国赛备赛之旅: 有道是 "不知何事萦怀抱,醒也无聊,醉也无聊,梦也何曾到谢桥." 那我们该如何 让这位诗人纳兰 "再听乐府曲 ,畅解相思苦"呢 ...

  9. STM32之端口复用与重映射

    STM32 --端口复用和重映射 首先来说下什么是端口复用. STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用的.也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GP ...

最新文章

  1. 库存事务处理现有量检查
  2. 配置MUX VLAN示例(汇聚层设备)
  3. toolbar + DrawerLayout 实现抽屉菜单
  4. linux内核实现ipsec,基于IPv6的IPSec原理分析和在Linux内核中的实现
  5. Hive中分组取前N个值
  6. 【实习之T100开发】Genero FGL (TIPTOP4GL) 学习笔记(2)
  7. MySQL某列增加标注_MySQL 使用CASE表达式给行做标记
  8. 全网首发:首个安卓摄像头预览加显示的项目
  9. java输出date_Java萌新的小小总结:Date日期类数据以给定格式打印输出
  10. 服务器保存qq群聊天图片无法显示,电脑中qq群聊天图片无法查看的解决方法
  11. 解决黑苹果(bigsur)ALC255声卡声音发虚问题
  12. etax导入账户不让勾选_【问答】自然人电子税务局网页版扣缴功能常见问题解答!...
  13. 【学习笔记】图像纹理特征
  14. 查找手机号绑定的百度账号
  15. python读取文件时的相对路径
  16. 一张图回顾Hadoop十年:Hadoop老矣,尚能饭否?
  17. 网易运营微专业_用户运营
  18. 港科夜闻|香港科大(广州)与深圳湾实验室签署重要战略合作协议,共同促进粤港澳大湾区产业升级、社会发展与科技进步...
  19. 计算机更改显卡,如何更换显卡
  20. ctf解题--后台登录(web)

热门文章

  1. mysql高效获取两张表共同字段的交集数据
  2. android的listview点击获取当前选项值的方法
  3. 手动为linux系统添加新用户——过程详解
  4. 《虚无的十字架》—— 读后总结
  5. 使用FileZilla连接Linux
  6. HTML Table 冻结行列
  7. 【转】JAVA 读写二进制文件
  8. 感谢Karen--oracle的system密码忘记修改办法|附sqlplus /nolog|
  9. Windows Phone开发之路(14) 加载位图
  10. 【Linux】关于Linux操作系统的基本操作