STM32
直播中

打马过草原

9年用户 867经验值
擅长:可编程逻辑 电源/新能源
私信 关注
[问答]

串口重定向是什么意思?

串口重定向是什么意思?

回帖(1)

臧超楠

2021-12-8 11:48:38

前言
串口是经常要使用的模块,比如利用串口中断进行通讯,或者打印字符串,此处只说一些细节。


串口重定向
1.重定向是什么意思呢?我们知道printf函数打印信息默认输出设备是显示器,而不是串口,我们通过printf重定向就可以将printf打印的信息输出在串口,方便上位机调试。
2.要实现printf重定向,即重写printf内部调用的fputc这个库函数,下面是usart1重定向的源码


int fputc(int ch,FILE *f)
{
        USART_SendData(USART1,(uint8_t) ch);
        while (USART_GetFlagStatus(USART1,USART1_FLAG_TC) != SET);
        return (ch);
}


3.如果不想使用printf,想自定义格式化输出函数,可以参考下面代码


//串口发送缓冲区       
__align(8) u8 USART_BT_TX_BUF[USART_BT_MAX_SEND_LEN];         //发送缓冲,最大USART3_MAX_SEND_LEN字节
void u3_printf(char* fmt,...)                           //括号内表示可变参,多个可变参组成一个可变参数列表
{  
        u16 i,j;
        va_list ap;                                         //初始化指向可变参数列表的指针
        va_start(ap,fmt);                                   //将第一个可变参数的地址付给ap,即 ap指向可变参数列表的开始
        vsprintf((char*)USART_BT_TX_BUF,fmt,ap);           // 将参数fmt,ap指向的可变参数一起转换成格式化字符串,存入USART_BT_TX_BUF数组;作用同sprintf,只是参数类型不同
        va_end(ap);                                        //没有任何意义,只是为了程序健壮性
        i=strlen((const char*)USART_BT_TX_BUF);
        for(j=0;j         {
          while(USART_GetFlagStatus(USART_BT,USART_FLAG_TC)==RESET);  
                USART_SendData(USART_BT,(uint8_t)USART_BT_TX_BUF[j]);        
        }
       
}


4.当链接器发现用户写的函数和库函数名字相同时,会优先执行用户自定义的函数。


清标志位
void USART1_IRQHandler(void)       //stm32中断服务程序的名字一般都是固定的,在启动文件里有定义                 
{
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //查看相应的标志位有没有置位
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);           //清中断标志位


                /****************处理语句******************************/                       
        }
}


说明:有些中断标志位只要读取数据或者访问某些寄存器就会自动清除,比如串口的发送接收完成,发送缓冲区空等。但是大部分的中断标记需要手动清除,比如定时器,所以保险起见的话都加上清标志位语句。(读不一定是软件读,打开外设寄存器窗口观察寄存器的值也算是读,至少串口是这样)


串口数据流向
1.数据接收流程
RXD–》移位寄存器–》RDG(接收数据缓冲器)–》内核
2.数据发送流程
内核–》TDG(输出数据缓冲器)–》移位寄存器–》TXD


HAL库串口中断使用
如果使用的是CUBE库来进行软件开发的话,CUBEMX配置好之后,使用串口中断只需要两步
1.串口初始化函数里添加如下代码,打开串口中断


void MX_USART1_UART_Init(void)
{
   if(HAL_UART_Receive_IT(&UART1Handle, Rxbuf, 3) != HAL_OK)
  {
     Error_Handler();
  }
}


2.重载串口接收中断的CallBack函数


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit_IT(&UART1Handle,Rxbuf,3);
    if(HAL_UART_Receive_IT(&UART1Handle, Rxbuf,3) != HAL_OK)  //由于中断处理流程里面会进去一次就关掉,所以要重新打开
   {
        Error_Handler();
   }


}


说明
(1)HAL_UART_Receive_IT
这个函数的作用主要是传参和打开相应的中断,并不是真正的发送接收函数
(2)中断处理流程相关函数
USART1_IRQHandler >> HAL_UART_IRQHandler >> UART_Receive_IT >>HAL_UART_RxCpltCallback
(3)发送中断的流程同上
举报

更多回帖

发帖
×
20
完善资料,
赚取积分