longor 发表于 2021-11-1 19:12:49

【UART】串口发送数据跑到串口接收缓冲区去了

遇到2个很莫名的问题,使用的芯片FM33LC023和FM33L025
1.目前在FM33L025上出现,串口4用作调试串口,同时串口0和1作为数据串口。开机打印log时,调试串口会产生接收中断,会收到log信息。即发送的信息跑到接收去了。
2.两个芯片上都遇到过,程序运行一段时间后,卡死在等待发送移位寄存器置位那里,即发送了数据但是硬件没有置位标志。使用的时串口0.
很奇怪的,希望能帮忙解惑。

顾博文 发表于 2021-11-3 08:58:09

1、这个问题没看明白,是4出的问题? 那说0,1是什么意思。第一,串口初始化过程中可能会产生中断标志位,这个需要你去清掉。第二 ,每个串口从硬件上是独立的,不存在共用。所以如果串口间的串扰很可能是软件问题。

2、这个问题,很有可能是发送时用了循环发送。死等标志位导致。 在发送判断标志时加上超时退出就能解决。 原理是读改写问题。这个标志在中断中被清掉了。所以在主程序里等不到发送完成标志。

longor 发表于 2021-11-3 09:34:25

顾博文 发表于 2021-11-3 08:58
1、这个问题没看明白,是4出的问题? 那说0,1是什么意思。第一,串口初始化过程中可能会产生中断标志位,这 ...

1的问题中说串口0和1只是描述下大概用了哪些串口。4用作打印log用,mcu-tx接usb转串口的rx连接电脑,mcu-rx悬空,没接。初始化后打印了一些参数信息,但是初始化完成后,串口产生了中断,而且缓冲区中有数据,数据就是log发送的数据。
下面是初始化函数和中断函数
static void MF_UART_Init(void)
{

    GPIO_InitTypeDef    GPIO_InitStruct;

    UART_SInitTypeDef    UART_para;
    RCC_ClocksType RCC_Clocks;
   
    //Lora接口:UART0
    AltFunIO(LORA_PORT, LORA_RX_PIN, ALTFUN_NORMAL);
    AltFunIO(LORA_PORT, LORA_TX_PIN, ALTFUN_NORMAL);
    //RX
//    GPIO_InitStruct.Pin = LORA_RX_PIN;   
//    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
//    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
//    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
//    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

//    GPIO_Init( LORA_PORT, &GPIO_InitStruct );
//    // TX
//    GPIO_InitStruct.Pin = LORA_TX_PIN;   
//    GPIO_Init( LORA_PORT, &GPIO_InitStruct );

    UART_para.ClockSrc = RCC_OPC_CR1_UART0CKS_RCHF;
    UART_para.BaudRate = 115200;
    UART_para.DataBit = Eight8Bit;
    UART_para.StopBit = OneBit;
    UART_para.ParityBit = NONE;
//    gotoSleepMode();

    UART_SInit(UART_LORA,&UART_para, &RCC_Clocks);

    RCC_PERCLK_SetableEx(UART0CLK,ENABLE);//开启外设时钟
    RCC_PERCLK_SetableEx(UART1CLK,ENABLE);
    RCC_PERCLK_SetableEx(UART4CLK,ENABLE);
   
    UARTx_CSR_RXEN_Setable(UART_LORA, ENABLE);//打开接收使能
    UARTx_CSR_TXEN_Setable(UART_LORA, ENABLE);//打开发送使能
    UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);   //发送缓冲区空且移位寄存器空中断使能
    UARTx_IER_RXBF_IE_Setable(UART_LORA, ENABLE); //接收缓存满中断使能
//   
    //以下函数用于开启接收超时功能
    UARTx_CSR_RXTOEN_Setable(UART_LORA, ENABLE);    //使能接收超时功能
    UARTx_IER_RXTO_IE_Setable(UART_LORA, ENABLE);   //使能接收超时中断
    UARTx_TODR_RXTO_LEN_Set(UART_LORA, 255); //设置接收超时为最大255 baud
   
    //AT接口:UART1
    AltFunIO(AT_PORT, AT_RX_PIN, ALTFUN_NORMAL);
    AltFunIO(AT_PORT, AT_TX_PIN, ALTFUN_NORMAL);
    //RX
//    GPIO_InitStruct.Pin = AT_RX_PIN;
//    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
//    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
//    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
//    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

//    GPIO_Init( AT_PORT, &GPIO_InitStruct );
//    // TX
//    GPIO_InitStruct.Pin = AT_TX_PIN;
//    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
//    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
//    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
//    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

//    GPIO_Init( AT_PORT, &GPIO_InitStruct );

    UART_para.ClockSrc = RCC_OPC_CR1_UART1CKS_RCHF;
    UART_para.BaudRate = 115200;
    UART_para.DataBit = Eight8Bit;
    UART_para.StopBit = OneBit;
    UART_para.ParityBit = NONE;

    UART_SInit(UART_AT,&UART_para, &RCC_Clocks);
   
    //这2个io口需要使能额外的数字功能选择,以区分使用哪种数字功能
    GPIOx_DFS_Setable(AT_PORT, AT_RX_PIN, DISABLE);
    GPIOx_DFS_Setable(AT_PORT, AT_TX_PIN, DISABLE);
   
    UARTx_CSR_RXEN_Setable(UART_AT, ENABLE);//打开接收使能
    UARTx_CSR_TXEN_Setable(UART_AT, ENABLE);                //打开发送使能
//    UARTx_IER_TXSE_IE_Setable(UART_AT, ENABLE);   //发送缓冲区空且移位寄存器空中断使能
    UARTx_IER_RXBF_IE_Setable(UART_AT, ENABLE); //接收缓存满中断使能
//   
    //以下函数用于开启接收超时功能
    UARTx_CSR_RXTOEN_Setable(UART_AT, ENABLE);    //使能接收超时功能
    UARTx_IER_RXTO_IE_Setable(UART_AT, ENABLE);   //使能接收超时中断
    UARTx_TODR_RXTO_LEN_Set(UART_AT, 255); //设置接收超时为最大255 baud
   


    //UART4--debug
    AltFunIO(PC_PORT, PC_RX_PIN, ALTFUN_NORMAL);
    AltFunIO(PC_PORT, PC_TX_PIN, ALTFUN_NORMAL);

//    GPIO_InitStruct.Pin = PC_RX_PIN;
//    GPIO_Init( PC_PORT, &GPIO_InitStruct );
//    GPIO_InitStruct.Pin = PC_TX_PIN;
//    GPIO_Init( PC_PORT, &GPIO_InitStruct );
   
    UART_SInit(UART_DEBUG, &UART_para, &RCC_Clocks);

    UART_para.BaudRate = 115200;
    UART_SInit(UART_DEBUG,&UART_para, &RCC_Clocks);
    UARTx_CSR_RXEN_Setable(UART_DEBUG, ENABLE);//打开接收使能
    UARTx_CSR_TXEN_Setable(UART_DEBUG, ENABLE);                //打开发送使能
    UARTx_IER_RXBF_IE_Setable(UART_DEBUG, ENABLE); //接收缓存满中断使能

    UARTx_ISR_TXSE_Clr(UART_DEBUG); //清除发送中断标志
    UARTx_ISR_TXSE_Clr(UART_AT);
    UARTx_ISR_TXSE_Clr(UART_LORA);
}


void UART4_IRQHandler(void)
{
    uint8_t tmp = 0;
    //接收中断处理
    if (UARTx_ISR_RXBF_Chk(UART_DEBUG) == SET)
    {
      irf_cnt++;
      tmp = UARTx_RXBUF_Read(UART_DEBUG);
      g_tUartDebug.pRxBuf = tmp;//接收中断标志可通过读取rxreg寄存器清除
      if (g_tUartDebug.usRxWrite >= g_tUartDebug.usRxBufSize)
      {
            g_tUartDebug.usRxWrite = 0;
      }
      if (g_tUartDebug.usRxCount < g_tUartDebug.usRxBufSize)
      {
            g_tUartDebug.usRxCount++;
      }
//      UARTx_TXBUF_Write(UART_DEBUG, tmp);
      UARTx_ISR_RXBF_Clr(UART_DEBUG);
    }
}

log打印后,打印了中断服务函数中的irf_cnt的值,为180多,每次不等,就说明这个过程中串口产生了中断,然后打印g_tUartDebug.pRxBuf中的数据,就是发生的log数据。

2的问题,确实是循环发送,死等标志位,我在循环发送前已经关闭发送中断了,还是会出现
void uartSendBufBlock(UART_Type *UARTx, uint8_t *buf, uint16_t len)
{
    uint16_t i = 0;
    uint16_t j = 0;
    UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);   //发送缓冲区空且移位寄存器空中断禁止
    for (i = 0; i < len; i++)
    {
      UARTx_TXBUF_Write(UARTx, buf);
      j = 0;
      while(UARTx_ISR_TXSE_Chk(UARTx) != SET)
      {
            j++;
            if(j >1000)
            {
                j = 0;
                _DBG("\r\nsend time out %d", ((uint32_t)UARTx - UART0_BASE)>>5);
                break;
            }
      }
      UARTx_ISR_TXSE_Clr(UARTx);
    }
    UARTx_IER_TXSE_IE_Setable(UART_LORA, ENABLE);   //发送缓冲区空且移位寄存器空中断使能
}



void UART0_IRQHandler(void)
{
    uint8_t tmp = 0;
    //接收中断处理
    if (UARTx_ISR_RXBF_Chk(UART_LORA) == SET)
    {
      tmp = UARTx_RXBUF_Read(UART_LORA);
      g_tUartLora.pRxBuf = tmp;//接收中断标志可通过读取rxreg寄存器清除
      if (g_tUartLora.usRxWrite >= g_tUartLora.usRxBufSize)
      {
            g_tUartLora.usRxWrite = 0;
      }
      if (g_tUartLora.usRxCount < g_tUartLora.usRxBufSize)
      {
            g_tUartLora.usRxCount++;
      }
    }
    else if(UARTx_ISR_RXTO_Chk(UART_LORA) == SET)
    {
      UARTx_ISR_RXTO_Clr(UART_LORA);
      g_tUartLora.rxTimeoutFlag = 1;
    }
//    UARTx_TXBUF_Write(UART_DEBUG, tmp);

    //发送中断处理
    if(SET == UARTx_ISR_TXSE_Chk(UART_LORA))
    {
      //发送中断标志可通过写txreg寄存器清除或txif写1清除
      //发送指定长度的数据
      if(g_tUartLora.usTxCount == 0)
      {
            UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);
      }
      else
      {
            UARTx_TXBUF_Write(UART_LORA, g_tUartLora.pTxBuf); //发送一个数据
            if(++g_tUartLora.usTxRead >= g_tUartLora.usTxBufSize)
                g_tUartLora.usTxRead = 0;
            g_tUartLora.usTxCount--;
      }
      UARTx_ISR_TXSE_Clr(UART_LORA);//清除发送中断标志
    }

}

顾博文 发表于 2021-11-4 08:47:32

longor 发表于 2021-11-3 09:34
1的问题中说串口0和1只是描述下大概用了哪些串口。4用作打印log用,mcu-tx接usb转串口的rx连接电脑,mcu- ...
针对第一个问题:   
1、看看硬件上芯片引脚 是不是连在一起了 ,虚焊等等 。2、rx引脚什么都不接,那就开启内部上拉,不接也不开上拉,那就是浮空态,

针对第二个问题:
死等肯定是不行的,加个超时退出就能解决。暂时也没用户反应有问题、遇到的都是读改写这种。




页: [1]
查看完整版本: 【UART】串口发送数据跑到串口接收缓冲区去了