查看: 4395|回复: 3

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

[复制链接]

8

主题

15

帖子

144

积分

中级工程师

Rank: 2

积分
144
发表于 2021-11-1 19:12:49 | 显示全部楼层 |阅读模式
遇到2个很莫名的问题,使用的芯片FM33LC023和FM33L025
1.目前在FM33L025上出现,串口4用作调试串口,同时串口0和1作为数据串口。开机打印log时,调试串口会产生接收中断,会收到log信息。即发送的信息跑到接收去了。
2.两个芯片上都遇到过,程序运行一段时间后,卡死在等待发送移位寄存器置位那里,即发送了数据但是硬件没有置位标志。使用的时串口0.
很奇怪的,希望能帮忙解惑。
回复

使用道具 举报

154

主题

846

帖子

4624

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4624
发表于 2021-11-3 08:58:09 | 显示全部楼层
1、这个问题没看明白,是4出的问题? 那说0,1是什么意思。第一,串口初始化过程中可能会产生中断标志位,这个需要你去清掉。第二 ,每个串口从硬件上是独立的,不存在共用。所以如果串口间的串扰很可能是软件问题。

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

使用道具 举报

8

主题

15

帖子

144

积分

中级工程师

Rank: 2

积分
144
 楼主| 发表于 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发送的数据。
下面是初始化函数和中断函数
  1. static void MF_UART_Init(void)
  2. {

  3.     GPIO_InitTypeDef    GPIO_InitStruct;

  4.     UART_SInitTypeDef    UART_para;
  5.     RCC_ClocksType RCC_Clocks;
  6.    
  7.     //Lora接口:UART0
  8.     AltFunIO(LORA_PORT, LORA_RX_PIN, ALTFUN_NORMAL);
  9.     AltFunIO(LORA_PORT, LORA_TX_PIN, ALTFUN_NORMAL);
  10.     //RX
  11. //    GPIO_InitStruct.Pin = LORA_RX_PIN;   
  12. //    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
  13. //    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
  14. //    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
  15. //    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

  16. //    GPIO_Init( LORA_PORT, &GPIO_InitStruct );
  17. //    // TX
  18. //    GPIO_InitStruct.Pin = LORA_TX_PIN;   
  19. //    GPIO_Init( LORA_PORT, &GPIO_InitStruct );

  20.     UART_para.ClockSrc = RCC_OPC_CR1_UART0CKS_RCHF;
  21.     UART_para.BaudRate = 115200;
  22.     UART_para.DataBit = Eight8Bit;
  23.     UART_para.StopBit = OneBit;
  24.     UART_para.ParityBit = NONE;
  25. //    gotoSleepMode();

  26.     UART_SInit(UART_LORA,&UART_para, &RCC_Clocks);

  27.     RCC_PERCLK_SetableEx(UART0CLK,ENABLE);  //开启外设时钟
  28.     RCC_PERCLK_SetableEx(UART1CLK,ENABLE);
  29.     RCC_PERCLK_SetableEx(UART4CLK,ENABLE);
  30.    
  31.     UARTx_CSR_RXEN_Setable(UART_LORA, ENABLE);  //打开接收使能
  32.     UARTx_CSR_TXEN_Setable(UART_LORA, ENABLE);  //打开发送使能
  33.     UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);   //发送缓冲区空且移位寄存器空中断使能
  34.     UARTx_IER_RXBF_IE_Setable(UART_LORA, ENABLE); //接收缓存满中断使能
  35. //   
  36.     //以下函数用于开启接收超时功能
  37.     UARTx_CSR_RXTOEN_Setable(UART_LORA, ENABLE);    //使能接收超时功能
  38.     UARTx_IER_RXTO_IE_Setable(UART_LORA, ENABLE);   //使能接收超时中断
  39.     UARTx_TODR_RXTO_LEN_Set(UART_LORA, 255); //设置接收超时为最大255 baud
  40.    
  41.     //AT接口:UART1
  42.     AltFunIO(AT_PORT, AT_RX_PIN, ALTFUN_NORMAL);
  43.     AltFunIO(AT_PORT, AT_TX_PIN, ALTFUN_NORMAL);
  44.     //RX
  45. //    GPIO_InitStruct.Pin = AT_RX_PIN;
  46. //    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
  47. //    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
  48. //    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
  49. //    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

  50. //    GPIO_Init( AT_PORT, &GPIO_InitStruct );
  51. //    // TX
  52. //    GPIO_InitStruct.Pin = AT_TX_PIN;
  53. //    GPIO_InitStruct.PxFCR = GPIO_FCR_DIG;
  54. //    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
  55. //    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
  56. //    GPIO_InitStruct.PxODEN = GPIO_OD_Dis;

  57. //    GPIO_Init( AT_PORT, &GPIO_InitStruct );

  58.     UART_para.ClockSrc = RCC_OPC_CR1_UART1CKS_RCHF;
  59.     UART_para.BaudRate = 115200;
  60.     UART_para.DataBit = Eight8Bit;
  61.     UART_para.StopBit = OneBit;
  62.     UART_para.ParityBit = NONE;

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


  79.     //UART4--debug
  80.     AltFunIO(PC_PORT, PC_RX_PIN, ALTFUN_NORMAL);
  81.     AltFunIO(PC_PORT, PC_TX_PIN, ALTFUN_NORMAL);

  82. //    GPIO_InitStruct.Pin = PC_RX_PIN;
  83. //    GPIO_Init( PC_PORT, &GPIO_InitStruct );
  84. //    GPIO_InitStruct.Pin = PC_TX_PIN;
  85. //    GPIO_Init( PC_PORT, &GPIO_InitStruct );
  86.    
  87.     UART_SInit(UART_DEBUG, &UART_para, &RCC_Clocks);

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

  93.     UARTx_ISR_TXSE_Clr(UART_DEBUG); //清除发送中断标志
  94.     UARTx_ISR_TXSE_Clr(UART_AT);
  95.     UARTx_ISR_TXSE_Clr(UART_LORA);
  96. }
复制代码


  1. void UART4_IRQHandler(void)
  2. {
  3.     uint8_t tmp = 0;
  4.     //接收中断处理
  5.     if (UARTx_ISR_RXBF_Chk(UART_DEBUG) == SET)
  6.     {
  7.         irf_cnt++;
  8.         tmp = UARTx_RXBUF_Read(UART_DEBUG);
  9.         g_tUartDebug.pRxBuf[g_tUartDebug.usRxWrite++] = tmp;//接收中断标志可通过读取rxreg寄存器清除
  10.         if (g_tUartDebug.usRxWrite >= g_tUartDebug.usRxBufSize)
  11.         {
  12.             g_tUartDebug.usRxWrite = 0;
  13.         }
  14.         if (g_tUartDebug.usRxCount < g_tUartDebug.usRxBufSize)
  15.         {
  16.             g_tUartDebug.usRxCount++;
  17.         }
  18. //        UARTx_TXBUF_Write(UART_DEBUG, tmp);
  19.         UARTx_ISR_RXBF_Clr(UART_DEBUG);
  20.     }
  21. }
复制代码


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

2的问题,确实是循环发送,死等标志位,我在循环发送前已经关闭发送中断了,还是会出现
  1. void uartSendBufBlock(UART_Type *UARTx, uint8_t *buf, uint16_t len)
  2. {
  3.     uint16_t i = 0;
  4.     uint16_t j = 0;
  5.     UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);   //发送缓冲区空且移位寄存器空中断禁止
  6.     for (i = 0; i < len; i++)
  7.     {
  8.         UARTx_TXBUF_Write(UARTx, buf[i]);
  9.         j = 0;
  10.         while(UARTx_ISR_TXSE_Chk(UARTx) != SET)
  11.         {
  12.             j++;
  13.             if(j >1000)
  14.             {
  15.                 j = 0;
  16.                 _DBG("\r\nsend time out %d", ((uint32_t)UARTx - UART0_BASE)>>5);
  17.                 break;
  18.             }
  19.         }
  20.         UARTx_ISR_TXSE_Clr(UARTx);
  21.     }
  22.     UARTx_IER_TXSE_IE_Setable(UART_LORA, ENABLE);   //发送缓冲区空且移位寄存器空中断使能
  23. }
复制代码



  1. void UART0_IRQHandler(void)
  2. {
  3.     uint8_t tmp = 0;
  4.     //接收中断处理
  5.     if (UARTx_ISR_RXBF_Chk(UART_LORA) == SET)
  6.     {
  7.         tmp = UARTx_RXBUF_Read(UART_LORA);
  8.         g_tUartLora.pRxBuf[g_tUartLora.usRxWrite++] = tmp;//接收中断标志可通过读取rxreg寄存器清除
  9.         if (g_tUartLora.usRxWrite >= g_tUartLora.usRxBufSize)
  10.         {
  11.             g_tUartLora.usRxWrite = 0;
  12.         }
  13.         if (g_tUartLora.usRxCount < g_tUartLora.usRxBufSize)
  14.         {
  15.             g_tUartLora.usRxCount++;
  16.         }
  17.     }
  18.     else if(UARTx_ISR_RXTO_Chk(UART_LORA) == SET)
  19.     {
  20.         UARTx_ISR_RXTO_Clr(UART_LORA);
  21.         g_tUartLora.rxTimeoutFlag = 1;
  22.     }
  23. //    UARTx_TXBUF_Write(UART_DEBUG, tmp);

  24.     //发送中断处理
  25.     if(SET == UARTx_ISR_TXSE_Chk(UART_LORA))
  26.     {
  27.         //发送中断标志可通过写txreg寄存器清除或txif写1清除
  28.         //发送指定长度的数据
  29.         if(g_tUartLora.usTxCount == 0)
  30.         {
  31.             UARTx_IER_TXSE_IE_Setable(UART_LORA, DISABLE);
  32.         }
  33.         else
  34.         {
  35.             UARTx_TXBUF_Write(UART_LORA, g_tUartLora.pTxBuf[g_tUartLora.usTxRead]); //发送一个数据
  36.             if(++g_tUartLora.usTxRead >= g_tUartLora.usTxBufSize)
  37.                 g_tUartLora.usTxRead = 0;
  38.             g_tUartLora.usTxCount--;
  39.         }
  40.         UARTx_ISR_TXSE_Clr(UART_LORA);  //清除发送中断标志
  41.     }

  42. }
复制代码


回复

使用道具 举报

154

主题

846

帖子

4624

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4624
发表于 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引脚什么都不接,那就开启内部上拉,不接也不开上拉,那就是浮空态,

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




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表