你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM103单片机串口输出函数printf重映射

[复制链接]
STMCU小助手 发布时间:2022-3-22 13:00
在调试程序的时候经常需要使用printf’函数来打印相关调试信息,在STM103单片机中printf函数默认只能在串口1使用,有时候串口1被占用了,想要输出调试信息时会比较麻烦。现在就总结一下如何在其他串口上使用printf函数。这里使用正点原子的例程来做说明。
默认串口1初始化代码如下

  1. #if 1
  2. #pragma import(__use_no_semihosting)
  3. //标准库需要的支持函数
  4. struct __FILE
  5. {
  6.     int handle;
  7. };
  8. FILE __stdout;
  9. //定义_sys_exit()以避免使用半主机模式
  10. _sys_exit(int x)
  11. {
  12.     x = x;
  13. }
  14. //重定义fputc函数
  15. int fputc(int ch, FILE *f)
  16. {
  17.     while((USART1->SR & 0X40) == 0); //循环发送,直到发送完毕
  18.     USART1->DR = (u8) ch;
  19.     return ch;
  20. }
  21. #endif

  22. void uart_init(u32 bound) {
  23.     //GPIO端口设置
  24.     GPIO_InitTypeDef GPIO_InitStructure;
  25.     USART_InitTypeDef USART_InitStructure;
  26.     NVIC_InitTypeDef NVIC_InitStructure;

  27.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟

  28.     //USART1_TX   GPIOA.9
  29.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  30.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  32.     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

  33.     //USART1_RX          GPIOA.10初始化
  34.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  35.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  36.     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10

  37.     //Usart1 NVIC 配置
  38.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  39.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
  40.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  41.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  42.     NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器

  43.     //USART 初始化设置

  44.     USART_InitStructure.USART_BaudRate = bound;//串口波特率
  45.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  46.     USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  47.     USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  48.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  49.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  50.     USART_Init(USART1, &USART_InitStructure); //初始化串口1
  51.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  52.     USART_Cmd(USART1, ENABLE);                    //使能串口1

  53. }
复制代码

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


  1. void uart_init(u32 bound) {
  2.     //GPIO端口设置
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     USART_InitTypeDef USART_InitStructure;
  5.     NVIC_InitTypeDef NVIC_InitStructure;

  6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟

  7.     //USART1_TX   GPIOA.9
  8.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  11.     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

  12.     //USART1_RX          GPIOA.10初始化
  13.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  14.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  15.     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10

  16.     //Usart1 NVIC 配置
  17.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  18.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
  19.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  20.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  21.     NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器

  22.     //USART 初始化设置

  23.     USART_InitStructure.USART_BaudRate = bound;//串口波特率
  24.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  25.     USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  26.     USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  27.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  28.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  29.     USART_Init(USART1, &USART_InitStructure); //初始化串口1
  30.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  31.     USART_Cmd(USART1, ENABLE);                    //使能串口1

  32. }
复制代码

串口3初始化代码

  1. #if 1
  2. #pragma import(__use_no_semihosting)
  3. //标准库需要的支持函数
  4. struct __FILE
  5. {
  6.     int handle;

  7. };

  8. FILE __stdout;
  9. //定义_sys_exit()以避免使用半主机模式
  10. _sys_exit(int x)
  11. {
  12.     x = x;
  13. }
  14. //重定义fputc函数
  15. int fputc(int ch, FILE *f)
  16. {
  17.     while((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕
  18.     USART3->DR = (u8) ch;
  19.     return ch;
  20. }
  21. #endif




  22. void  uart3_init(u16 baud)
  23. {
  24.     GPIO_InitTypeDef GPIO_InitStructure;
  25.     USART_InitTypeDef USART_InitStructure;
  26.     NVIC_InitTypeDef  NVIC_InitStructure;

  27.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  28.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  29.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  30.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  31.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  32.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  33.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  34.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  35.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  36.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  37.     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  38.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  39.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  40.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  41.     NVIC_Init(&NVIC_InitStructure);

  42.     USART_InitStructure.USART_BaudRate = baud;
  43.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  44.     USART_InitStructure.USART_StopBits = USART_StopBits_1;
  45.     USART_InitStructure.USART_Parity = USART_Parity_No;
  46.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  47.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

  48.     USART_Init(USART3, &USART_InitStructure);

  49.     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
  50.     USART_Cmd(USART3, ENABLE);

  51. }
复制代码

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

  1. #pragma import(__use_no_semihosting)
  2. //标准库需要的支持函数
  3. struct __FILE
  4. {
  5.     int handle;

  6. };

  7. FILE __stdout;
  8. //定义_sys_exit()以避免使用半主机模式
  9. _sys_exit(int x)
  10. {
  11.     x = x;
  12. }
  13. //重定义fputc函数
  14. int fputc(int ch, FILE *f)
  15. {
  16.     while((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕
  17.     USART3->DR = (u8) ch;
  18.     return ch;
  19. }
复制代码

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


收藏 评论0 发布时间:2022-3-22 13:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版