STM32
直播中

杨平

7年用户 1582经验值
私信 关注
[问答]

STM32串口总线空闲检测,输出cnt值的疑问求解

前几天在群里看到有人咨询STM32串口总线空闲检测的问题,之前也一直没用过该特性,后来看了下手册学习了一下,编辑了一些代码进行测试发现一个小问题,uart源文件代码如下:

  • #include "uart.h"

  • uint8_t buffer[100];
  • __IO uint32_t cnt = 0,idle_detect = 0;

  • void uart_init (uint32_t baud)
  • {
  •         USART_InitTypeDef USART_InitStructure;
  •         GPIO_InitTypeDef GPIO_InitStructure;
  •         NVIC_InitTypeDef NVIC_InitStructure;

  •         RCC_AHBPeriphClockCmd(USARTx_GPIO_CLK, ENABLE);
  •         USARTx_CLK_ENABLE();

  •         GPIO_PinAFConfig(USARTx_GPIO_PORT, USARTx_TX_SOURCE, USARTx_TX_AF);
  •         GPIO_PinAFConfig(USARTx_GPIO_PORT, USARTx_RX_SOURCE, USARTx_RX_AF);

  •         GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN| USARTx_RX_PIN;
  •         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  •         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  •         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  •         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
  •         GPIO_Init(USARTx_GPIO_PORT,  GPIO_InitStructure);

  •         USART_InitStructure.USART_BaudRate            = baud ;
  •         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(USARTx,  USART_InitStructure);

  •         USART_ITConfig(USARTx,USART_IT_RXNE,ENABLE);
  •         USART_ITConfig(USARTx,USART_IT_PE,ENABLE);
  •         USART_ITConfig(USARTx,USART_IT_ERR,ENABLE);
  •         USART_ITConfig(USARTx,USART_IT_IDLE,ENABLE);


  •         NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn;
  •         NVIC_InitStructure.NVIC_IRQChannelPriority=0;
  •         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  •         NVIC_Init( NVIC_InitStructure);

  •         USART_Cmd(USARTx, ENABLE);
  • }

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

  • void USARTx_IRQHandler(void)
  • {
  •         uint8_t temp = 0;

  •         if(USART_GetFlagStatus(USARTx,USART_FLAG_ORE) != RESET)
  •         {
  •                 temp = USART_ReceiveData(USARTx);
  •                 (void)temp;
  •                 USART_ClearFlag(USARTx,USART_FLAG_ORE);
  •         }
  •         if(USART_GetFlagStatus(USARTx,USART_FLAG_NE) != RESET)
  •         {
  •                 USART_ClearFlag(USARTx,USART_FLAG_NE);
  •         }
  •         if(USART_GetFlagStatus(USARTx,USART_FLAG_FE) != RESET)
  •         {
  •                 USART_ClearFlag(USARTx,USART_FLAG_FE);
  •         }
  •         if(USART_GetFlagStatus(USARTx,USART_FLAG_PE) != RESET)
  •         {
  •                 USART_ClearFlag(USARTx,USART_FLAG_PE);
  •         }

  •         if(USART_GetiTStatus(USARTx, USART_IT_RXNE) != RESET)
  •         {
  •                 buffer[cnt++]=USART_ReceiveData(USARTx);
  •                 if(cnt >= 100)
  •                 {
  •                         cnt = 0;
  •                 }
  •                 USART_ClearITPendingBit(USARTx, USART_IT_RXNE);
  •         }
  •         if(USART_GetITStatus(USARTx, USART_IT_IDLE) != RESET)
  •         {
  •                 USART_ClearITPendingBit(USARTx, USART_IT_IDLE);
  •                 idle_detect = 1;
  •                 cnt = cnt;
  •         }
  •         return;
  • }

主函数中的测试代码如下:

  • #include "uart.h"

  • extern __IO uint32_t idle_detect,cnt;
  • extern uint8_t buffer[100];
  • int main (void)
  • {
  •         uint8_t i = 0;
  •         uart_init(115200);

  •         while(1)
  •         {
  •                 if(1 == idle_detect    cnt > 0)
  •                 {
  •                         idle_detect = 0;

  •                         printf("rncnt:%X,ctx:",cnt);
  •                         for(i = 0; i < cnt; i++)
  •                         {
  •                                 printf("%02X ",buffer);
  •                         }
  •                         cnt = 0;
  •                 }
  •         }
  • }

它输出的cnt值一直为1,但数据内容是正确的,而把cnt的判断放在if条件语句的里面就不会出问题,如下:

  • #include "uart.h"

  • extern __IO uint32_t idle_detect,cnt;
  • extern uint8_t buffer[100];
  • int main (void)
  • {
  •         uint8_t i = 0;
  •         uart_init(115200);

  •         while(1)
  •         {
  •                 if(1 == idle_detect)
  •                 {
  •                         idle_detect = 0;

  •                         if(cnt == 0)
  •                                 continue;
  •                         printf("rncnt:%X,ctx:",cnt);
  •                         for(i = 0; i < cnt; i++)
  •                         {
  •                                 printf("%02X ",buffer);
  •                         }
  •                         cnt = 0;
  •                 }
  •         }
  • }


此时输出的cnt的值是正确的,有人知道会是什么问题导致的吗?

回帖(1)

李英

2024-5-9 16:26:28
首先,让我们了解一下STM32串口总线空闲检测的基本概念。在串口通信中,空闲检测是一种检测接收线上是否没有数据传输的方法。这对于确定何时开始接收数据或何时结束接收数据非常有用。STM32微控制器提供了空闲线检测功能,可以通过配置UART的中断和相关寄存器来实现。

现在,让我们分析您提供的代码片段。代码中包含了一些初始化串口和相关硬件的函数。但是,代码片段不完整,因此我们需要补充一些内容以实现空闲检测功能。

以下是实现STM32串口总线空闲检测的步骤:

1. 初始化串口和GPIO:这部分已经在您的代码中完成了。确保正确配置了串口的波特率、数据位、停止位等参数。

2. 配置NVIC(嵌套向量中断控制器):这一步是为了使能串口的中断。您需要配置NVIC_InitTypeDef结构体,然后调用NVIC_Init()函数。

3. 配置串口中断:您需要配置串口的中断优先级和使能空闲线中断。这可以通过设置USART_ITConfig()函数和USART_Cmd()函数来实现。

4. 编写中断服务函数:在您的代码中,需要添加一个UART中断服务函数,用于处理空闲线中断。在这个函数中,您可以实现空闲检测逻辑,例如增加cnt计数器的值。

以下是补充后的代码示例:

```c
#include "stm32f10x.h"

uint8_t buffer[100];
__IO uint32_t cnt = 0, idle_detect = 0;

void uart_init(uint32_t baud) {
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // ...(省略初始化串口和GPIO的代码)

    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能串口接收中断和空闲线中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
    USART_Cmd(USART1, ENABLE);
}

void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        // 处理接收到的数据
    }

    if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) {
        // 空闲线检测
        cnt++;
        idle_detect = 1;
        USART_ClearITPendingBit(USART1, USART_IT_IDLE);
    }
}
```

请注意,这个示例代码是基于STM32F10x系列微控制器的。如果您使用的是其他系列的STM32微控制器,可能需要对代码进行相应的调整。
举报

更多回帖

×
20
完善资料,
赚取积分