STM32串口定时器延时接收不定数组和串口发送

发布时间 2023-03-31 00:06:43作者: 在下彦祖
#include "user_uart.h"
#include "stm32f10x.h"
#include <stdio.h>


/******************************************************************************************/
/*串口接收部分代码移植需要改动3处*/
/******************************************************************************************/


/******************************************************************************************/
/********************************串口接收部分代码*******************************************/
/******************************************************************************************/


/******************************************************************************************/
/*此结构体类型无需改动*/
/******************************************************************************************/
typedef struct
{
    volatile unsigned int uart_delay_flag;    //串口进入中断后,定时器开启标志位
    volatile unsigned int uart_delay_count;   //串口进入中断后,定时器计数变量,自加
    volatile unsigned char uart_array_num;    //接受数据的数组的序号
  volatile unsigned char uart_receive_flag; //串口接收数据完成标志位
}User_Uart_InitTypeDef;
/*******************************************************************************************/

  
/******************************************************************************************************/
/*串口结构体数组,预设5个串口,如增加新串口,可按格式增加,如不需要增加串口,此结构体无需改动*/
/******************************************************************************************************/
User_Uart_InitTypeDef uart_array[UART_NUM_ALL] =  
{
 {0,0,0,0,},
 
 #if UART_NUM_ALL > 1 
 {0,0,0,0,},
 #endif
 
  #if UART_NUM_ALL > 2 
 {0,0,0,0,},
 #endif
 
  #if UART_NUM_ALL > 3 
 {0,0,0,0,},
 #endif
 
  #if UART_NUM_ALL > 4 
 {0,0,0,0,},
 #endif
};
/***************************************************************************************************/


/***************************************************************************************************/
/*串口接收数组声明,预设5个串口,如增加新串口,可按格式增加,如不需要增加串口,此结构体无需改动*/
/***************************************************************************************************/
volatile unsigned char uart1_array_receive_buff[N1_UART];

#if UART_NUM_ALL > 1
volatile unsigned char uart2_array_receive_buff[N2_UART];
#endif

#if UART_NUM_ALL > 2
volatile unsigned char uart3_array_receive_buff[N3_UART];
#endif

#if UART_NUM_ALL > 3
volatile unsigned char uart4_array_receive_buff[N4_UART];
#endif

#if UART_NUM_ALL > 4
volatile unsigned char uart5_array_receive_buff[N5_UART];
#endif
/***************************************************************************************************/


/**********************************移植需改动的第1处***********************************/
/*串口初始化代码*/
/*************************************************************************************/
void user_uart_init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct; 
     USART_InitTypeDef USART_InitStruct;
   NVIC_InitTypeDef NVIC_InitStruct;
     
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
     
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    
   GPIO_Init(GPIOA, &GPIO_InitStruct);
    
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    
   GPIO_Init(GPIOA, &GPIO_InitStruct);
    
     USART_InitStruct.USART_BaudRate = 115200;
     USART_InitStruct.USART_WordLength = USART_WordLength_8b;
     USART_InitStruct.USART_StopBits = USART_StopBits_1;
     USART_InitStruct.USART_Parity = USART_Parity_No;
     USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
     USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
     USART_Init(USART1, &USART_InitStruct);
     
     NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
     NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStruct);
     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
     
     USART_Cmd(USART1, ENABLE);
}    
/******************************************************************************************/


/***********************************移植需改动的第2处*******************************************************/
/*此函数放置到串口中断服务函数,移植需改动: 1串口清除中断标志位的函数 2串口接收数据函数*/
/*********************************************************************************************************/
void user_uart_intterrupt(unsigned char uart_id)
{
    switch(uart_id)
    {
      case 1: USART_ClearITPendingBit(USART1, USART_IT_RXNE);break;
        
        #if UART_NUM_ALL > 1
      case 2: USART_ClearITPendingBit(USART2, USART_IT_RXNE);break;
    #endif
        
        #if UART_NUM_ALL > 2
      case 3: USART_ClearITPendingBit(USART3, USART_IT_RXNE);break;
    #endif
        
        #if UART_NUM_ALL > 3
      case 4: USART_ClearITPendingBit(USART4, USART_IT_RXNE);break;
    #endif
        
        #if UART_NUM_ALL > 4
      case 4: USART_ClearITPendingBit(USART5, USART_IT_RXNE);break;
    #endif
    }
    uart_array[uart_id - 1].uart_delay_flag = 1; //进入中断后开启定时
  uart_array[uart_id - 1].uart_delay_count = 0; //清零定时器计数
    if(uart_array[uart_id - 1].uart_array_num < N1_UART)
    {
      switch(uart_id)
        {
          case 1:uart1_array_receive_buff[uart_array[uart_id - 1].uart_array_num] = USART_ReceiveData(USART1);break;
            
            #if UART_NUM_ALL > 1
      case 2:uart2_array_receive_buff[uart_array[uart_id - 1].uart_array_num] = USART_ReceiveData(USART2);break;
      #endif
            
            #if UART_NUM_ALL > 2
        case 3:uart3_array_receive_buff[uart_array[uart_id - 1].uart_array_num] = USART_ReceiveData(USART3);break;
      #endif
            
            #if UART_NUM_ALL > 3
        case 4:uart4_array_receive_buff[uart_array[uart_id - 1].uart_array_num] = USART_ReceiveData(USART4);break;
      #endif
            
            #if UART_NUM_ALL > 4
        case 4:uart4_array_receive_buff[uart_array[uart_id - 1].uart_array_num] = USART_ReceiveData(USART5);break;
      #endif
      }
    uart_array[uart_id - 1].uart_array_num++;    
    }
    else
    {
      uart_array[uart_id - 1].uart_array_num = N1_UART;  //不再接收接收数据
    }
}
/*********************************************************************************************************/


/*********************************************************************************************************/
/*此函数放置到systick或者定时器中断函数去,此结构体无需改动*/
/*********************************************************************************************************/
void user_uart_scan(void)
{
  unsigned char uart_index;
    for(uart_index =0;uart_index < UART_NUM_ALL;uart_index++)
    {    
        if(uart_array[uart_index].uart_delay_flag == 1)     //判断标志位,串口启动定时延时
        {
            uart_array[uart_index].uart_delay_count++;        //延时计数
            if(uart_array[uart_index].uart_delay_count > UART_DELAY_TIME) //延时计数超过设定值
            {
                uart_array[uart_index].uart_delay_count = 0;   //延时计数清零
                uart_array[uart_index].uart_delay_flag = 0;    //延时计数的标志位清零,关串口计数定时器
                uart_array[uart_index].uart_array_num = 0;     //串口数组的下标归零,以便下次串口接收数据从0下标开始
                uart_array[uart_index].uart_receive_flag = 1;  //接收完成,标志位赋值
            }
        }
    }    
}
/**********************************************************************************************************/


/***********************************************************************************/
/*判断串口数据是否接收完成,一般在主函数使用,并处理串口接收到的数据,此结构体无需改动*/
/***********************************************************************************/
unsigned char user_uart_get_flag(unsigned char uart_id)
{
  unsigned char uart_local_param = 0;
    if(uart_array[uart_id - 1].uart_receive_flag == 1)
    {
      uart_array[uart_id - 1].uart_receive_flag = 0;
        uart_local_param = 1;
  }
    else
    {
      uart_local_param = 0;
    }
    return uart_local_param;
}
/*****************************************************************************/


/******************************移植需要改动的第3处*******************************/
/*串口中断服务函数,如移植需重写串口对应的中断服务函数*/
/*****************************************************************************/
void USART1_IRQHandler()
{
  user_uart_intterrupt(1);
}


#if UART_NUM_ALL > 1
void USART2_IRQHandler()
{
  user_uart_intterrupt(2);
}
#endif
/*****************************************************************************/


/*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/分界线/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/******************************************************************************************/


/******************************************************************************************/
/*串口发送部分代码移植需要改动2处*/
/******************************************************************************************/


/****************************************************************************/
/***************************串口发送部分代码*********************************/
/****************************************************************************/


/****************************************************************************/
/*不用勾选使用keil的Use MicroLIB,不需要改动*/
/****************************************************************************/
#if 1
#pragma import(__use_no_semihosting)
void _sys_exit(int x){x = x;}   //定义_sys_exit()以避免使用半主机模式 
struct __FILE{int handle;};     //标准库需要的支持函数 
FILE __stdout;
#endif
/*****************************************************************************/


/**************************移植需要改动的第1处********************************/
/*重定义print函数,如移植需重写串口发送单个字节函数,和获取标志位函数*/
/****************************************************************************/
int fputc(int ch, FILE *f)
{
  USART_SendData(USART1,(uint8_t)ch);   //发送一字节数据
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成
    return ch;
}
/*****************************************************************************/


/******************************************移植需要改动的第2处********************************************/
/*串口发送函数,如移植需重写串口发送单个字节函数,和获取标志位函数*/
/****************************************************************************/
void user_uart_send(unsigned char uart_id,unsigned char *uart_p,unsigned char uart_array_member_total)
{
  unsigned char uart_local_param;
    switch(uart_id)
    {
      case 1: for(uart_local_param = 0;uart_local_param < uart_array_member_total;uart_local_param++)
                {
                          USART_SendData(USART1,(uint8_t)uart_p[uart_local_param]);   //发送一字节数据
                while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成
                            USART_ClearFlag(USART1,USART_FLAG_TC);                      //清除发送标志位
                        };break;
        
        #if UART_NUM_ALL > 1
        case 2: for(uart_local_param = 0;uart_local_param < uart_array_member_total;uart_local_param++)
                {
                          USART_SendData(USART2,(uint8_t)uart_p[uart_local_param]);   //发送一字节数据
                while(USART_GetFlagStatus(USART2,USART_FLAG_TXE) == RESET); //等待发送完成
                            USART_ClearFlag(USART2,USART_FLAG_TC);                      //清除发送标志位
                        };break;
      #endif                    
      
        #if UART_NUM_ALL > 2
        case 3: for(uart_local_param = 0;uart_local_param < uart_array_member_total;uart_local_param++)
                {
                          USART_SendData(USART3,(uint8_t)uart_p[uart_local_param]);   //发送一字节数据
                while(USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET); //等待发送完成
                            USART_ClearFlag(USART3,USART_FLAG_TC);                      //清除发送标志位
                        };break;
        #endif                
      
        #if UART_NUM_ALL > 3
        case 4: for(uart_local_param = 0;uart_local_param < uart_array_member_total;uart_local_param++)
                {
                          USART_SendData(USART4,(uint8_t)uart_p[uart_local_param]);   //发送一字节数据
                while(USART_GetFlagStatus(USART4,USART_FLAG_TXE) == RESET); //等待发送完成
                            USART_ClearFlag(USART4,USART_FLAG_TC);                      //清除发送标志位
                        };break;
                        
        #endif

    #if UART_NUM_ALL > 4        
      case 5: for(uart_local_param = 0;uart_local_param < uart_array_member_total;uart_local_param++)
                {
                          USART_SendData(USART5,(uint8_t)uart_p[uart_local_param]);   //发送一字节数据
                while(USART_GetFlagStatus(USART5,USART_FLAG_TXE) == RESET); //等待发送完成
                            USART_ClearFlag(USART5,USART_FLAG_TC);                      //清除发送标志位
                        };break;
    #endif                        
    }
}
/**********************************************************************************************************/


/*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/分界线/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/******************************************************************************************/


/****************************************************************************/
/*串口数组数据清除,适用于所有数组*/
/****************************************************************************/
 void array_clear(unsigned char *array_p,unsigned char array_num)
 {
   unsigned char array_local_param;
     for(array_local_param = 0;array_local_param < array_num;array_local_param++)
     {
       array_p[array_local_param] = 0;
     }
 }
 /****************************************************************************/
 
  
#ifndef _user_uart_h_
#define _user_uart_h_


/******************************************************************************************/
/*串口接收部分代码移植需要改动3处*/
/******************************************************************************************/


/***************移植需改动的第1处*********************/
/*宏定义串口的总个数*/
/****************************************************/
#define UART_NUM_ALL 1
/****************************************************/


/****************移植需改动的第2处********************/
/*宏定义串口延时接收时间设置*/
/****************************************************/
#define UART_DELAY_TIME 10
/****************************************************/


/****************移植需改动的第3处*******************/
/*宏定义串口接收数组的大小*/
/****************************************************/
#define N1_UART 10 

#if UART_NUM_ALL > 1
N2_UART 10
#endif

#if UART_NUM_ALL > 2
N3_UART 10
#endif

#if UART_NUM_ALL > 3
N4_UART 10
#endif

#if UART_NUM_ALL > 4
N5_UART 10
#endif
/****************************************************/


/******************************************************************/
/*声明串口数据接收数组外部调用,无需改动*/
/******************************************************************/
extern volatile unsigned char uart1_array_receive_buff[N1_UART];

#if UART_NUM_ALL > 1
extern volatile unsigned char uart2_array_receive_buff[N2_UART];
#endif

#if UART_NUM_ALL > 2
extern volatile unsigned char uart3_array_receive_buff[N3_UART];
#endif

#if UART_NUM_ALL > 3
extern volatile unsigned char uart4_array_receive_buff[N4_UART];
#endif

#if UART_NUM_ALL > 4
extern volatile unsigned char uart5_array_receive_buff[N5_UART];
#endif
/*******************************************************************/


/****************************************************/
/*串口初始化*/
void user_uart_init(void);
/****************************************************/



/*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/分界线/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/******************************************************************************************/


/*与串口发送有关的函数*/
/****************************************************/
/*此函数放置到串口中断服务函数*/
void user_uart_intterrupt(unsigned char uart_id);
/****************************************************/


/****************************************************************/
/*此函数放置到systick或者定时器中断函数去*/
void user_uart_scan(void);
/****************************************************************/


/******************************************************************/
/*判断串口数据是否接收完成,一般在主函数使用,并处理串口接收到的数据*/
unsigned char user_uart_get_flag(unsigned char uart_id);
/******************************************************************/



/*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/分界线/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/******************************************************************************************/


/******************************************************************************************************/
/*串口发送函数*/
void user_uart_send(unsigned char uart_id,unsigned char *uart_p,unsigned char uart_array_member_total);
/******************************************************************************************************/

  
/*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/分界线/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/******************************************************************************************/

 
/*****************************************************************/
/*串口数组数据清除,适用于所有数组*/
void array_clear(unsigned char *array_p,unsigned char array_num);
/*****************************************************************/


#endif