STM32
直播中

张强

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

STM32F103串口中断是如何去接收不定长字符串的

STM32F103串口中断是如何去接收不定长字符串的?有什么方法吗?

回帖(2)

訾存贵

2021-12-8 09:12:47
一、应用简介

本文介绍串口中断接收不定长字符串的方法。将串口1配置接收中断使能、空闲中断使能来接收不定长数据。
也就是在配置串口中断的时候使能接收中断和空闲中断。如下:

...
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);       
...
USART_IT_RXNE:接收中断,串口每收到一个字节就会产生一个此中断。
USART_IT_IDLE:空闲中断,总线上在一个字节的时间内没有再接收到数据的时候发生的。
之后在串口中断处理函数中分别判断处理2种中断就好了,如下:


// 接收数组大小
#define  RECEIVE_BUF_SIZE           255


uint8_t g_usart1RxFlag = 0;                                                        // 串口1接收标志0-未接受1-接收
uint8_t  g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];           // 串口1接收缓冲  
uint16_t g_uart1Len = 0;                                                        // 串口1接收长度  
/**
@brief USART1中断
@param 无
@retval 无
*/
void USART1_IRQHandler(void)  
{  
        // 接收中断的时候收集数据包
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART1, USART_IT_RXNE); //只USART_ReceiveData也可以


        g_uart1ReceiveBuff[g_uart1Len] = USART_ReceiveData(USART1);


        g_uart1Len++;
    }
    // 空闲中断的时候说明串口没数据了,收集完成
    else if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET)
    {
        USART1->SR;
        USART1->DR;
                // 标志位,代表有数据,此数据放到main处理去,不要放中断处理。我只打印一下
        g_usart1RxFlag = 1;
                printf("shoudao1:%s", g_uart1ReceiveBuff);


    }
}


最后,main函数,如下


int main(void)
{
        ...
    while (1)
    {
                // 数据处理
        if(g_usart1RxFlag == 1)
                {
                        // 数据处理,这里添加用户自定义处理,处理g_uart1ReceiveBuff后清空
                       


                        g_usart1RxFlag = 0;
                        g_uart1Len = 0;
                        memset(g_uart1ReceiveBuff, 0x00, sizeof(g_uart1ReceiveBuff));
                }       
                vTaskDelay(1);   /* 1ms启动读一次 */
    }
        ...
}
二、实例

bsp_usart.h

/**===========================================================================
  @file     bsp_usart.h
  @brief    本文件是用于串口驱动
  @author   青梅煮久
  @version  r0.1
  @date     2021/04/26
----------------------------------------------------------------------------
  Remark: (备注描述)
        串口1的驱动。
        串口1:用于日志打印、指令配置
----------------------------------------------------------------------------
                                History
----------------------------------------------------------------------------
       | |        |
-------------|-----------|----------------|---------------------------------
  2021/04/26 | r0.1      | 青梅煮久        | 创建
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
============================================================================*/
#ifndef __BSP_USART_H
#define        __BSP_USART_H


/*********************************************************************
* INCLUDES
*/
#include "stm32f10x.h"
#include


/*********************************************************************
* DEFINITIONS
*/       
// 接收数组大小
#define  RECEIVE_BUF_SIZE           255


/**
* 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
* 2-修改GPIO的宏
*/
/********************************串口1**********************************/
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200


#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10


#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler




/*********************************************************************
* GLOBAL VARIABLES
*/
extern uint8_t g_usart1RxFlag;                                                        // 串口1接收标志0-未接受1-接收
extern uint8_t  g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];   // 串口1接收缓冲  
extern uint16_t g_uart1Len;                                                                // 串口1接收长度  
/*********************************************************************
* API FUNCTIONS
*/
void USART1_Config(void);


#endif /* __BSP_USART_H */


bsp_usart.c


/**===========================================================================
  @file     bsp_usart.h
  @brief    本文件是用于串口驱动
  @author   青梅煮久
  @version  r0.1
  @date     2021/04/26
----------------------------------------------------------------------------
  Remark: (备注描述)
        串口1的驱动。
        串口1:用于日志打印、指令配置
----------------------------------------------------------------------------
                                History
----------------------------------------------------------------------------
       | |        |
-------------|-----------|----------------|---------------------------------
  2021/04/26 | r0.1      | 青梅煮久        | 创建
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
============================================================================*/


/*********************************************************************
* INCLUDES
*/
#include "bsp_usart.h"
#include "stm32f10x.h"
#include "string.h"


static void NVIC_Configuration(void);


/*********************************************************************
* GLOBAL VARIABLES
*/
uint8_t g_usart1RxFlag = 0;                                                        // 串口1接收标志0-未接受1-接收
uint8_t  g_uart1ReceiveBuff[RECEIVE_BUF_SIZE];           // 串口1接收缓冲  
uint16_t g_uart1Len = 0;                                                        // 串口1接收长度  


/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief  USART1 GPIO 配置,工作参数配置
@param  无
@retval 无
*/
void USART1_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;


        // 打开串口GPIO的时钟
        DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
       
        // 打开串口外设的时钟
        DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
       
        /*
        *  配置串口
        *  USART1_TX -> PA9 , USART1_RX ->        PA10
        */       
        // 将USART Tx的GPIO配置为推挽复用模式
        GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);


        // 将USART Rx的GPIO配置为浮空输入模式
        GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
       
        USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
        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(DEBUG_USARTx, &USART_InitStructure);


        // 串口中断优先级配置
        NVIC_Configuration();
       
        // 使能串口中断
        USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
        USART_ITConfig(DEBUG_USARTx, USART_IT_IDLE, ENABLE);       
       
        // 使能串口
        USART_Cmd(DEBUG_USARTx, ENABLE);          


}


/**
@brief 发送一个字节
@param pUSARTx -[in] 串口
@param ch -[in] 发送数据
@retval 无
*/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
        /* 发送一个字节数据到USART */
        USART_SendData(pUSARTx,ch);
               
        /* 等待发送数据寄存器为空 */
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);       
}


/**
@brief 发送8位的数组
@param pUSARTx -[in] 串口
@param array -[in] 发送数据
@param num -[in] 发送长度
@retval 无
*/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{
  uint8_t i;
       
        for(i=0; i   {
            /* 发送一个字节数据到USART */
            Usart_SendByte(pUSARTx,array);       
  
  }
        /* 等待发送完成 */
        while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}


/**
@brief 发送字符串
@param pUSARTx -[in] 串口
@param str -[in] 发送数据
@retval 无
*/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
        unsigned int k=0;
  do
  {
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='');
  
  /* 等待发送完成 */
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}


/**
@brief 发送一个16位数
@param pUSARTx -[in] 串口
@param ch -[in] 发送数据
@retval 无
*/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
        uint8_t temp_h, temp_l;
       
        /* 取出高八位 */
        temp_h = (ch&0XFF00)>>8;
        /* 取出低八位 */
        temp_l = ch&0XFF;
       
        /* 发送高八位 */
        USART_SendData(pUSARTx,temp_h);       
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
       
        /* 发送低八位 */
        USART_SendData(pUSARTx,temp_l);       
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);       
}


/**
@brief 重定向c库函数printf到串口,重定向后可使用printf函数
*/
int fputc(int ch, FILE *f)
{
                /* 发送一个字节数据到串口 */
                USART_SendData(DEBUG_USARTx, (uint8_t) ch);
               
                /* 等待发送完毕 */
                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);               
       
                return (ch);
}


/**
@brief 重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
*/
int fgetc(FILE *f)
{
                /* 等待串口输入数据 */
                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);


                return (int)USART_ReceiveData(DEBUG_USARTx);
}


/**
@brief USART1中断
@param 无
@retval 无
*/
void USART1_IRQHandler(void)  
{  
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART1, USART_IT_RXNE); //只USART_ReceiveData也可以


        g_uart1ReceiveBuff[g_uart1Len] = USART_ReceiveData(USART1);


        g_uart1Len++;
    }
    else if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET)
    {
        USART1->SR;
        USART1->DR;


        g_usart1RxFlag = 1;
                printf("shoudao1:%s", g_uart1ReceiveBuff);


    }
}


/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief  配置嵌套向量中断控制器NVIC
@param  无
@retval 无
*/
static void NVIC_Configuration(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
  
        /* 嵌套向量中断控制器组选择 */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


        /* 配置串口的 NVIC设置*/
        NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


}
举报

张蕾

2021-12-8 09:12:50
main.c


#include "bsp_usart.h"


int main(void)
{
        ...
        USART1_Config();
        ...
    while (1)
    {
                // 数据处理
        if(g_usart1RxFlag == 1)
                {
                        // 数据处理,这里添加用户自定义处理,处理g_uart1ReceiveBuff后清空
                       


                        g_usart1RxFlag = 0;
                        g_uart1Len = 0;
                        memset(g_uart1ReceiveBuff, 0x00, sizeof(g_uart1ReceiveBuff));
                }       
                vTaskDelay(1);   /* 1ms启动读一次 */
    }
        ...
}
举报

更多回帖

×
20
完善资料,
赚取积分