打印
[应用相关]

stm32学习笔记----双串口同时打开时的printf()问题

[复制链接]
806|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
operating|  楼主 | 2019-6-18 10:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其将打印的信息重定向至串口1。但是当在程序中调用printf()时,却发现上位机无论如何都接收不到信息,而且printf()之后的语句也不再执行,想必程序在printf()函数里面死掉了吧。当时觉得很纳闷,因为单独只使用一个串口时,printf()是没有问题的。

使用特权

评论回复
沙发
operating|  楼主 | 2019-6-18 10:37 | 只看该作者
往下说之前,先贴一下双串口的配置和printf()的书写,mark一下。
void USART_Config()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    //配置串口1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    //配置串口2时钟,使用复用功能,打开AFIO,管脚重映射到PD5,PD6
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
   GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
   
    /*配置串口1(USART1 Tx(PA.09))*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);   
    /* 配置串口1(USART1 Tx(PA.10))*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
   
        /*串口1工作模式(USART1 mode)配置 */
    USART_InitStructure.USART_BaudRate = 115200;
    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(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);//使能串口
   
    /*配置串口2(USART2 Tx(PD.05))*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
   
    /*配置串口2(USART2 Tx(PD.05))*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
   
    /*串口2工作模式(USART2 mode)配置 */
   
    USART_InitStructure.USART_BaudRate = 115200;
    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);
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART2, ENABLE);
   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
              /*串口2中断配置*/                                
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*printf()函数重定向*/
int fputc(int ch, FILE *f)
{
    //将printf()内容发往串口1
    USART_SendData(USART1, (unsigned char) ch);
    while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);   
    return (ch);
}

使用特权

评论回复
板凳
operating|  楼主 | 2019-6-18 10:38 | 只看该作者
当只开串口1时,printf()是可以正常使用的,但是同时使用串口1和串口2时,使用printf()就会输出不了信息,并且程序无法往下执行;但如果不用printf()函数,而直接使用USART_SendData(USART1,(unsigned char) ch)时,串口1也能正常打印;但这样太麻烦辣,每次打印一个字符。

使用特权

评论回复
地板
operating|  楼主 | 2019-6-18 10:38 | 只看该作者
于是网上查了一下,也有人遇到类似问题,而后评论下方有一个函数,说是可以双串口同时打开时,也可以一次性打印一串信息。抱着试一试的心态,将函数程序搬到我的工程中,没想到,还真行。下面贴出代码:
/*
* 函数名:itoa
* 描述  :将整形数据转换成字符串
* 输入  :-radix =10 表示10进制,其他结果为0
*         -value 要转换的整形数
*         -buf 转换后的字符串
*         -radix = 10
* 输出  :无
* 返回  :无
* 调用  :被USART_printf()调用
*/
static char *itoa(int value, char *string, int radix)
{
        int     i, d;
        int     flag = 0;
        char    *ptr = string;

    /* This implementation only works for decimal numbers. */
        if (radix != 10)
        {
            *ptr = 0;
            return string;
        }

        if (!value)
        {
            *ptr++ = 0x30;
            *ptr = 0;
            return string;
        }

    /* if this is a negative value insert the minus sign. */
        if (value < 0)
        {
            *ptr++ = '-';

            /* Make the value positive. */
            value *= -1;
        }

        for (i = 10000; i > 0; i /= 10)
       {
            d = value / i;

            if (d || flag)
            {
                *ptr++ = (char)(d + 0x30);
                value -= (d * i);
                flag = 1;
            }
        }

        /* Null terminate the string. */
        *ptr = 0;

        return string;

}

/*
* 函数名:USART_printf
* 描述  :格式化输出,类似于C库中的printf,但这里没有用到C库
* 输入  :-USARTx 串口通道
*                     -Data   要发送到串口的内容的指针
*                           -...    其他参数
* 输出  :无
* 返回  :无
* 调用  :外部调用
*         典型应用USART_printf( USART1, "\r\n this is a demo \r\n" );
*                             USART_printf( USART2, "\r\n %d \r\n", i );
*                             USART_printf( USART3, "\r\n %s \r\n", j );
*/
void USART_printf(USART_TypeDef* USARTx, uint8_t *Data,...)
{
      const char *s;
      int d;   
      char buf[16];
      va_list ap;
      va_start(ap, Data);

      while ( *Data != 0)     // 判断是否到达字符串结束符
      {                                                         
                if ( *Data == 0x5c )  //'\'
                {                                                                          
                        switch ( *++Data )
                        {
                                case 'r':                   //回车符                                                   
                                        USART_SendData(USARTx, 0x0d);
                                        Data ++;
                                        break;

                                case 'n':                 //换行符                                                          //???
                                        USART_SendData(USARTx, 0x0a);        
                                        Data ++;
                                        break;
                                
                                default:
                                        Data ++;
                                    break;
                        }                        
                }
                else if ( *Data == '%')
                {                                                                          //
                        switch ( *++Data )
                        {                                
                                case 's':                //字符串                                                                  
                                        s = va_arg(ap, const char *);
          for ( ; *s; s++)
                                        {
                                                USART_SendData(USARTx,*s);
                                                while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
          }
                                        Data++;
          break;

        case 'd':                      //十进制                                                         
          d = va_arg(ap, int);
          itoa(d, buf, 10);
          for (s = buf; *s; s++)
                                        {
                                                USART_SendData(USARTx,*s);
                                                while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
          }
                                        Data++;
          break;
                                 default:
                                                Data++;
                                    break;
                        }                 
                } /* end of else if */
                else USART_SendData(USARTx, *Data++);
                while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
        }
}

使用特权

评论回复
5
keaibukelian| | 2019-7-8 11:23 | 只看该作者
感谢楼主分享啊

使用特权

评论回复
6
labasi| | 2019-7-8 11:32 | 只看该作者

非常感谢楼主分享

使用特权

评论回复
7
paotangsan| | 2019-7-8 11:36 | 只看该作者

非常感谢楼主分享

使用特权

评论回复
8
renzheshengui| | 2019-7-8 11:41 | 只看该作者

非常感谢楼主分享

使用特权

评论回复
9
kayman| | 2019-10-21 08:29 | 只看该作者
特意回来评论。

使用楼主方法不要忘了添加一下include
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

255

帖子

0

粉丝