STM32L496HAL库串口不定长通讯(DMA+空闲中断+定时器)

首先打开时钟,本项目使用的是HSE。

打开串口,DMA,中断

打开定时器以及定时器中断,因为我测试的数据量较大,定时器设置的5ms,具体计算如下。

这里我们 arr=4799  psc=49 Tclk=48Mhz        Tout = (4800*50)/48000000  = 5ms。可以根据实际情况,数据量大小来调整定时时间。

生成工程,不会的可以去查一下怎么生成,很多教程。

需要添加的代码如下

/*
这些是串口通信所用到的变量
*/

#define USART_RXC_MAX  			6000  	//定义最大接收字节数 6000
#define USART_TXC_MAX  			6000  	//定义最大发送字节数 6000

#define USART_RXC_SIZE  			200  	//定义最大临时接收字节数 200
#define USART_TXC_SIZE  			200  	//定义最大临时发送字节数 200


typedef struct {
  uint8_t  USART_MAX[USART_RXC_MAX];     //接收最大缓冲区
  uint8_t  USART_BUF[USART_RXC_SIZE];     //接收临时缓冲区
  volatile uint16_t USART_STA;                    //接收标志位
  volatile uint16_t USART_SIZE;                   //接收数据量
  DMA_HandleTypeDef hdma_usart1_rx;               //DMA
}USART_RX;

typedef struct {
  uint8_t  USART_MAX[USART_TXC_MAX];     //发送最大缓冲区
  uint8_t  USART_BUF[USART_TXC_SIZE];     //发送临时缓冲区
  volatile uint16_t USART_STA;                    //发送标志位
  volatile uint16_t USART_SIZE;                   //发送数据量
  DMA_HandleTypeDef hdma_usart1_tx;               //DMA
}USART_TX;

typedef struct __USART_CUSTOM
{
  UART_HandleTypeDef huart;
  USART_RX USART_RX;
  USART_TX USART_TX;
}USART_CUSTOM;

extern USART_CUSTOM huart1;

/*
这些是中断中所要更改的
#include "stm32l4xx_it.c"
*/
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1.huart);

  /* USER CODE BEGIN USART1_IRQn 1 */
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1.huart,huart1.USART_RX.USART_BUF,USART_RXC_SIZE);	//重新开启串口空闲中断和DMA接收,一定要放在这里

  /* USER CODE END USART1_IRQn 1 */
}

/*
这些是相关回调函数
*/

//这个我放倒了tim.c里
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	 if(htim==(&htim1))
	  {
      huart1.USART_RX.USART_STA = 1;
	    HAL_TIM_Base_Stop_IT(&htim1);//关闭定时
	  }
}

//这些我放倒了usart.c里面
uint16_t cnt;

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)     //接收中断回调函数
{
    if (huart->Instance == USART1)
    {
      if(huart1.USART_RX.USART_STA == 0){
          __HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_UPDATE);
          HAL_TIM_Base_Start_IT(&htim1);
      }
      cnt = USART_RXC_SIZE - __HAL_DMA_GET_COUNTER(&huart1.USART_RX.hdma_usart1_rx);

      if((cnt+huart1.USART_RX.USART_SIZE) < USART_RXC_MAX){

        memcpy(&huart1.USART_RX.USART_MAX[huart1.USART_RX.USART_SIZE],huart1.USART_RX.USART_BUF,cnt);

        huart1.USART_RX.USART_SIZE += cnt;
        __HAL_TIM_SET_COUNTER(&htim1,0);
      }
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)         //发送完成回调函数
{
	if(huart->Instance==USART1)
	{
    memset(huart1.USART_RX.USART_MAX, 0, sizeof(huart1.USART_RX.USART_MAX));
    huart1.USART_RX.USART_SIZE = 0;
    huart1.USART_RX.USART_STA = 0;
	}
}

/*
这些是main.c里面的
*/

void huart1_initialize()    //串口自定义相关变量的结构体初始化
{
  huart1.USART_RX.USART_SIZE = 0;
  huart1.USART_RX.USART_STA = 0;
  huart1.USART_TX.USART_SIZE = 0;
  huart1.USART_TX.USART_STA = 0;
}

//重要提醒//
//这个我放到了void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)函数里面的最后面,可以根据各位喜好,放到main函数内或者其它可行的地方都可以。

__HAL_UART_ENABLE_IT(&huart1.huart, UART_IT_IDLE);    /* 开启串口空闲中断 */

//主函数
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  huart1_initialize();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    if(huart1.USART_RX.USART_STA == 1)
    {
      HAL_UART_Transmit_DMA(&huart1.huart,huart1.USART_RX.USART_MAX, huart1.USART_RX.USART_SIZE);	//将接受到的数据再发回上位机
      while(__HAL_UART_GET_FLAG(&huart1.huart, UART_FLAG_TC) == RESET){}///<等待发送完成
    }
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

实现效果,这里我一次性发送的是5000字节。

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值